Wp-Insert - Version 2.2

Version Description

Download this release

Release Info

Developer namith.jawahar
Plugin Icon 128x128 Wp-Insert
Version 2.2
Comparing to
See all releases

Code changes from version 2.1.8 to 2.2

Files changed (35) hide show
  1. includes/adstxt.php +73 -0
  2. includes/adwidgets.php +31 -2
  3. includes/apis/vi/api.php +421 -0
  4. includes/assets/css/wp-insert.css +400 -2
  5. includes/assets/images/advertisement-preview.png +0 -0
  6. includes/assets/images/vi-big-logo.png +0 -0
  7. includes/assets/images/vi-empty-graph.jpg +0 -0
  8. includes/assets/images/vi-logo-large.png +0 -0
  9. includes/assets/images/vi-logo-small.png +0 -0
  10. includes/assets/images/vi-no-data.jpg +0 -0
  11. includes/assets/images/wpinsert-vi.png +0 -0
  12. includes/assets/js/Chart.bundle.min.js +10 -0
  13. includes/assets/js/uncompressed/jQuery-Chart/Chart.bundle.js +18494 -0
  14. includes/assets/js/uncompressed/jQuery-Chart/LICENSE.md +9 -0
  15. includes/assets/js/wp-insert.js +502 -7
  16. includes/common/abtesting.php +19 -1
  17. includes/common/adstxt.php +42 -0
  18. includes/common/common.php +9 -0
  19. includes/common/control-panel.php +32 -118
  20. includes/common/geotargeting.php +66 -8
  21. includes/controls/assets/css/controls.css +339 -7
  22. includes/controls/assets/images/jquery.minicolors.png +0 -0
  23. includes/controls/assets/js/controls.js +12 -1
  24. includes/controls/assets/js/uncompressed/jQuery-TE/jquery-te-1.4.0.js +1347 -0
  25. includes/controls/assets/js/uncompressed/jQuery-TE/license/AUTHOR.txt +6 -0
  26. includes/controls/assets/js/uncompressed/jQuery-TE/license/MIT-LICENSE.txt +7 -0
  27. includes/controls/assets/js/uncompressed/jQuery-chosen/LICENSE.md +23 -0
  28. includes/controls/assets/js/uncompressed/jQuery-chosen/chosen.jquery.js +1349 -0
  29. includes/controls/assets/js/uncompressed/jQuery-minicolors/LICENSE.md +7 -0
  30. includes/controls/assets/js/uncompressed/jQuery-minicolors/jquery.minicolors.js +1108 -0
  31. includes/controls/controls.php +23 -2
  32. includes/inpostads.php +90 -16
  33. includes/inthemeads.php +31 -2
  34. includes/tracking-codes.php +17 -0
  35. includes/vi-integration.php +363 -0
includes/adstxt.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* Begin Add Card in Admin Panel */
3
+ add_action('wp_insert_plugin_card', 'wp_insert_adstxt_plugin_card', 70);
4
+ function wp_insert_adstxt_plugin_card() {
5
+ echo '<div class="plugin-card adstxt-card">';
6
+ echo '<div class="plugin-card-top">';
7
+ echo '<h4>Authorized Digital Sellers / ads.txt</h4>';
8
+ echo '<p>Authorized Digital Sellers, or ads.txt, is an <a href="https://iabtechlab.com/">IAB</a> initiative to improve transparency in programmatic advertising.</p>';
9
+ echo '<p>You can easily manage your ads.txt from within Wp-Insert, providing confidence to brands they are buying authentic publisher inventory, protect you from counterfiet inventory and might even lead to higher monetization for your ad invertory.</p>';
10
+ echo '</div>';
11
+ echo '<div class="plugin-card-bottom">';
12
+ if(wp_insert_adstxt_file_exists()) {
13
+ echo '<a id="wp_insert_adstxt_generate" href="javascript:;" class="button button-primary">Modify ads.txt</a>';
14
+ } else {
15
+ echo '<a id="wp_insert_adstxt_generate" href="javascript:;" class="button button-primary">Generate ads.txt</a>';
16
+ }
17
+ echo '</div>';
18
+ echo '</div>';
19
+ }
20
+ /* End Add Card in Admin Panel */
21
+
22
+ /* Begin Create Ads.txt */
23
+ add_action('wp_ajax_wp_insert_adstxt_generate_form_get_content', 'wp_insert_adstxt_generate_form_get_content');
24
+ function wp_insert_adstxt_generate_form_get_content() {
25
+ check_ajax_referer('wp-insert', 'wp_insert_nonce');
26
+ echo '<div class="wp_insert_popup_content_wrapper">';
27
+ echo '<div id="wp_insert_adstxt_accordion">';
28
+ $control = new smartlogixControls();
29
+ echo '<h3>ads.txt Content</h3>';
30
+ echo '<div>';
31
+ $control->add_control(array('type' => 'textarea', 'id' => 'wp_insert_adstxt_content', 'name' => 'wp_insert_adstxt_content', 'style' => 'height: 220px;', 'value' => wp_insert_adstxt_get_content(), 'helpText' => 'You can directly edit the entries here or you can use the entry generator below to quickly create new entries'));
32
+ $control->create_section('ads.txt Content');
33
+ echo $control->HTML;
34
+ $control->clear_controls();
35
+ echo '</div>';
36
+ echo '<h3>Entry Generator</h3>';
37
+ echo '<div>';
38
+ $control->add_control(array('type' => 'text', 'id' => 'wp_insert_adstxt_new_entry_domain', 'name' => 'wp_insert_adstxt_new_entry_domain', 'label' => 'Domain name of the advertising system <small style="font-size: 10px;">(Required)</small>', 'value' => '', 'helpText' => 'For Google Adsense Use "google.com"; for other networks, contact your service provider for values.'));
39
+ $control->add_control(array('type' => 'text', 'id' => 'wp_insert_adstxt_new_entry_pid', 'name' => 'wp_insert_adstxt_new_entry_pid', 'label' => 'Publisher’s Account ID <small style="font-size: 10px;">(Required)</small>', 'value' => '', 'helpText' => 'For Google Adsense Use your Publisher ID "pub-xxxxxxxxxxxxxxxx"; for other networks, contact your service provider for values.'));
40
+ $control->add_control(array('type' => 'select', 'id' => 'wp_insert_adstxt_new_entry_type', 'name' => 'wp_insert_adstxt_new_entry_type', 'label' => 'Type of Account / Relationship <small style="font-size: 10px;">(Required)</small>', 'value' => '', 'options' => array(array('text' => 'Direct', 'value' => 'DIRECT'), array('text' => 'Reseller', 'value' => 'RESELLER')), 'helpText' => 'For Google Adsense select "Reseller"; for other networks, contact your service provider for values.'));
41
+ $control->add_control(array('type' => 'text', 'id' => 'wp_insert_adstxt_new_entry_certauthority', 'name' => 'wp_insert_adstxt_new_entry_certauthority', 'label' => 'Certification Authority ID', 'value' => '', 'helpText' => 'Contact your service provider for values.'));
42
+ $control->HTML .= '<p><input id="wp_insert_adstxt_add_entry" onclick="wp_insert_adstxt_add_entry()" type="button" value="Add Entry" class="button button-primary" /></p>';
43
+ $control->create_section('Entry Generator');
44
+ echo $control->HTML;
45
+ echo '</div>';
46
+ echo '</div>';
47
+ echo '<script type="text/javascript">';
48
+ echo $control->JS;
49
+ echo 'jQuery("#wp_insert_adstxt_accordion").accordion({ icons: { header: "ui-icon-circle-arrow-e", activeHeader: "ui-icon-circle-arrow-s" }, heightStyle: "fill" });';
50
+ //echo 'jQuery(".ui-dialog-buttonset").find("button").first().remove();';
51
+ echo '</script>';
52
+ echo '</div>';
53
+ die();
54
+ }
55
+
56
+ add_action('wp_ajax_wp_insert_adstxt_generate_form_save_action', 'wp_insert_adstxt_generate_form_save_action');
57
+ function wp_insert_adstxt_generate_form_save_action() {
58
+ check_ajax_referer('wp-insert', 'wp_insert_nonce');
59
+ $content = ((isset($_POST['wp_insert_adstxt_content']))?$_POST['wp_insert_adstxt_content']:'');
60
+ $output = wp_insert_adstxt_updation_failed_message($content);
61
+ $output .= '<script type="text/javascript">';
62
+ $output .= 'jQuery(".ui-dialog-buttonset").find("button").first().hide();';
63
+ $output .= '</script>';
64
+
65
+ if(wp_insert_adstxt_update_content($content)) {
66
+ echo '###SUCCESS###';
67
+ } else {
68
+ echo $output;
69
+ }
70
+ die();
71
+ }
72
+ /* End Create Ads.txt */
73
+ ?>
includes/adwidgets.php CHANGED
@@ -1,4 +1,28 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /* Begin Add New Adwidget Content */
3
  add_action('wp_ajax_wp_insert_adwidgets_new_form_get_content', 'wp_insert_adwidgets_new_form_get_content');
4
  function wp_insert_adwidgets_new_form_get_content() {
@@ -138,8 +162,10 @@ function wp_insert_adwidgets_form_get_content($identifier) {
138
  echo '</div>';
139
  echo '<h3>Geo Targeting</h3>';
140
  echo '<div>';
141
- echo '<p><b>This feature is temporarily unavailable as the servers we were using for FREE Geo Ip service has shut down.</b><br />(If you are interested in supporting us setup our own servers for continuing this service please contact the Author via support@smartlogix.co.in)</p>';
142
- echo '<p>A Geo Targeted Ads have a higher priority than Ads configured via Multiple Ad Networks / A-B Testing.<br />If a Geo Targeting match is found all other Ads (Primary, Secondary and Tertiary Networks) will be ignored.</p>';
 
 
143
  $control->add_control(array('type' => 'choosen-multiselect', 'label' => 'Countries', 'optionName' => 'geo_group1_countries', 'options' => wp_insert_get_countries()));
144
  $control->add_control(array('type' => 'textarea', 'label' => 'Ad Code', 'style' => 'height: 220px;', 'optionName' => 'geo_group1_adcode'));
145
  $control->create_section('Group 1');
@@ -153,6 +179,9 @@ function wp_insert_adwidgets_form_get_content($identifier) {
153
  $control->set_HTML('<div class="wp_insert_rule_block">'.$control->HTML.'</div><div style="clear: both;"></div>');
154
  echo $control->HTML;
155
  $control->clear_controls();
 
 
 
156
  echo '</div>';
157
  echo '<h3>Styles</h3>';
158
  echo '<div>';
1
  <?php
2
+ /* Begin Add Card in Admin Panel */
3
+ add_action('wp_insert_plugin_card', 'wp_insert_adwidgets_plugin_card', 20);
4
+ function wp_insert_adwidgets_plugin_card() {
5
+ echo '<div class="plugin-card">';
6
+ echo '<div class="plugin-card-top">';
7
+ echo '<h4>Ad Widgets</h4>';
8
+ echo '<p>Ads shown inside widget enabled areas.</p>';
9
+ echo '</div>';
10
+ echo '<div class="plugin-card-bottom">';
11
+ $adwidgets = get_option('wp_insert_adwidgets');
12
+ if(isset($adwidgets) && is_array($adwidgets)) {
13
+ foreach($adwidgets as $key => $value) {
14
+ echo '<p>';
15
+ echo '<a id="wp_insert_adwidgets_'.$key.'" href="javascript:;" onclick="wp_insert_adwidgets_click_handler(\''.$key.'\', \''.$value['title'].'\')">Ad Widget : '.$value['title'].'</a>';
16
+ echo '<span class="dashicons dashicons-dismiss wp_insert_delete_icon" onclick="wp_insert_adwidgets_remove(\''.$key.'\')"></span>';
17
+ echo '</p>';
18
+ }
19
+ }
20
+ echo '<p style="text-align: center; padding: 20px 0 10px;"><a id="wp_insert_adwidgets_new" href="#" class="button-secondary">Add New Ad Widget</a></p>';
21
+ echo '</div>';
22
+ echo '</div>';
23
+ }
24
+ /* End Add Card in Admin Panel */
25
+
26
  /* Begin Add New Adwidget Content */
27
  add_action('wp_ajax_wp_insert_adwidgets_new_form_get_content', 'wp_insert_adwidgets_new_form_get_content');
28
  function wp_insert_adwidgets_new_form_get_content() {
162
  echo '</div>';
163
  echo '<h3>Geo Targeting</h3>';
164
  echo '<div>';
165
+ echo '<p>';
166
+ echo 'A Geo Targeted Ads have a higher priority than Ads configured via Multiple Ad Networks / A-B Testing.<br />';
167
+ echo 'If a Geo Targeting match is found all other Ads (Primary, Secondary and Tertiary Networks) will be ignored.';
168
+ echo '</p>';
169
  $control->add_control(array('type' => 'choosen-multiselect', 'label' => 'Countries', 'optionName' => 'geo_group1_countries', 'options' => wp_insert_get_countries()));
170
  $control->add_control(array('type' => 'textarea', 'label' => 'Ad Code', 'style' => 'height: 220px;', 'optionName' => 'geo_group1_adcode'));
171
  $control->create_section('Group 1');
179
  $control->set_HTML('<div class="wp_insert_rule_block">'.$control->HTML.'</div><div style="clear: both;"></div>');
180
  echo $control->HTML;
181
  $control->clear_controls();
182
+ echo '<p>';
183
+ echo 'This feature uses the Free Geo ip service from <a href="http://freegeoip.net/">freegeoip.net</a>, if you find this feature useful please consider donating to the project at <a href="http://freegeoip.net/">freegeoip.net</a>';
184
+ echo '</p>';
185
  echo '</div>';
186
  echo '<h3>Styles</h3>';
187
  echo '<div>';
includes/apis/vi/api.php ADDED
@@ -0,0 +1,421 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ function wp_insert_vi_api_get_settings() {
3
+ $viSettings = get_transient('wp_insert_vi_api_settings');
4
+ if(($viSettings === false) || !is_array($viSettings)) {
5
+ try {
6
+ $response = wp_remote_get('https://dashboard-api.vidint.net/v1/api/widget/settings', array('timeout' => 15));
7
+ if(!is_wp_error($response) && (200 == wp_remote_retrieve_response_code($response))) {
8
+ $responseBody = json_decode($response['body']);
9
+ if((json_last_error() == JSON_ERROR_NONE) && ($responseBody->status == 'ok')) {
10
+ $viSettings = array(
11
+ 'signupURL' => $responseBody->data->signupURL,
12
+ 'demoPageURL' => $responseBody->data->demoPageURL,
13
+ 'iabCategoriesURL' => $responseBody->data->iabCategoriesURL,
14
+ 'loginAPI' => $responseBody->data->loginAPI,
15
+ 'directSellURL' => $responseBody->data->directSellURL,
16
+ 'dashboardURL' => $responseBody->data->dashboardURL,
17
+ 'revenueAPI' => $responseBody->data->revenueAPI,
18
+ 'adsTxtAPI' => $responseBody->data->adsTxtAPI,
19
+ 'languages' => $responseBody->data->languages,
20
+ 'jsTagAPI' => $responseBody->data->jsTagAPI,
21
+ );
22
+ delete_transient('wp_insert_vi_api_settings');
23
+ set_transient('wp_insert_vi_api_settings', $viSettings, WEEK_IN_SECONDS);
24
+ } else {
25
+ return false;
26
+ }
27
+ }
28
+ } catch(Exception $ex) {
29
+ return false;
30
+ }
31
+ }
32
+ return $viSettings;
33
+ }
34
+
35
+ function wp_insert_vi_api_get_signupurl() {
36
+ $viSettings = wp_insert_vi_api_get_settings();
37
+ if(($viSettings != false) && is_array($viSettings)) {
38
+ return $viSettings['signupURL'];
39
+ }
40
+ return false;
41
+ }
42
+
43
+ function wp_insert_vi_api_get_dashboardurl() {
44
+ $viSettings = wp_insert_vi_api_get_settings();
45
+ if(($viSettings != false) && is_array($viSettings)) {
46
+ return $viSettings['dashboardURL'];
47
+ }
48
+ return false;
49
+ }
50
+
51
+ function wp_insert_vi_api_get_iabCategoriesURL() {
52
+ $viSettings = wp_insert_vi_api_get_settings();
53
+ if(($viSettings != false) && is_array($viSettings)) {
54
+ return $viSettings['iabCategoriesURL'];
55
+ }
56
+ return false;
57
+ }
58
+
59
+ function wp_insert_vi_api_get_languages() {
60
+ $viSettings = wp_insert_vi_api_get_settings();
61
+ if(($viSettings != false) && is_array($viSettings)) {
62
+ $languages = array();
63
+ foreach($viSettings['languages'] as $language) {
64
+ foreach($language as $key => $value) {
65
+ $languages[$key] = $value;
66
+ }
67
+ }
68
+ if(count($languages) > 0) {
69
+ return $languages;
70
+ } else {
71
+ return false;
72
+ }
73
+ }
74
+ return false;
75
+ }
76
+
77
+ function wp_insert_vi_api_get_adstxt_content() {
78
+ $viSettings = wp_insert_vi_api_get_settings();
79
+ if(($viSettings != false) && is_array($viSettings)) {
80
+ $viToken = wp_insert_vi_api_get_publisher_token();
81
+ if($viToken !== false) {
82
+ try{
83
+ $response = wp_remote_get(
84
+ $viSettings['adsTxtAPI'],
85
+ array(
86
+ 'timeout' => 15,
87
+ 'headers' => array(
88
+ 'Content-Type' => 'application/json',
89
+ 'Authorization' => $viToken
90
+ )
91
+ )
92
+ );
93
+ if(!is_wp_error($response)) {
94
+ if(200 == wp_remote_retrieve_response_code($response)) {
95
+ $responseBody = json_decode($response['body']);
96
+ if((json_last_error() == JSON_ERROR_NONE) && ($responseBody->status == 'ok')) {
97
+ return $responseBody->data;
98
+ } else {
99
+ return false;
100
+ }
101
+ } else {
102
+ return false;
103
+ }
104
+ }
105
+ } catch(Exception $ex) {
106
+ return false;
107
+ }
108
+ } else {
109
+ return false;
110
+ }
111
+ } else {
112
+ return false;
113
+ }
114
+ }
115
+
116
+ function wp_insert_vi_api_login($email, $password) {
117
+ if(($email != '') && ($password != '')) {
118
+ $viSettings = wp_insert_vi_api_get_settings();
119
+ if(($viSettings != false) && is_array($viSettings)) {
120
+ try {
121
+ $response = wp_remote_post(
122
+ $viSettings['loginAPI'],
123
+ array(
124
+ 'timeout' => 15,
125
+ 'headers' => array(
126
+ 'Content-Type' => 'application/json'
127
+ ),
128
+ 'body' => json_encode(array(
129
+ 'email' => $email,
130
+ 'password' => $password,
131
+ ))
132
+ )
133
+ );
134
+ if(!is_wp_error($response)) {
135
+ if(401 == wp_remote_retrieve_response_code($response)) {
136
+ $responseBody = json_decode($response['body']);
137
+ if((json_last_error() == JSON_ERROR_NONE) && ($responseBody->status == 'error')) {
138
+ return array(
139
+ 'status' => 'error',
140
+ 'errorCode' => 'WIVI008',
141
+ 'message' => $responseBody->error->message.':'.$responseBody->error->description.'',
142
+ );
143
+ } else {
144
+ return array(
145
+ 'status' => 'error',
146
+ 'errorCode' => 'WIVI007',
147
+ 'message' => 'Response JSON error, Please try again later!',
148
+ );
149
+ }
150
+ } else if(200 == wp_remote_retrieve_response_code($response)) {
151
+ $responseBody = json_decode($response['body']);
152
+ if((json_last_error() == JSON_ERROR_NONE) && ($responseBody->status == 'ok')) {
153
+ $viToken = $responseBody->data;
154
+ delete_transient('wp_insert_vi_api_authetication_token');
155
+ set_transient('wp_insert_vi_api_authetication_token', $viToken, MONTH_IN_SECONDS);
156
+ } else {
157
+ return array(
158
+ 'status' => 'error',
159
+ 'errorCode' => 'WIVI006',
160
+ 'message' => 'Response JSON error!',
161
+ );
162
+ }
163
+ } else {
164
+ return array(
165
+ 'status' => 'error',
166
+ 'errorCode' => 'WIVI005',
167
+ 'message' => 'Unknown response code',
168
+ );
169
+ }
170
+ } else {
171
+ return array(
172
+ 'status' => 'error',
173
+ 'errorCode' => 'WIVI004',
174
+ 'message' => 'API response error',
175
+ );
176
+ }
177
+ } catch(Exception $ex) {
178
+ return array(
179
+ 'status' => 'error',
180
+ 'errorCode' => 'WIVI003',
181
+ 'message' => 'Exception during API communication',
182
+ );
183
+ }
184
+ } else {
185
+ return array(
186
+ 'status' => 'error',
187
+ 'errorCode' => 'WIVI002',
188
+ 'message' => 'API is unreachable',
189
+ );
190
+ }
191
+ } else {
192
+ return array(
193
+ 'status' => 'error',
194
+ 'errorCode' => 'WIVI001',
195
+ 'message' => 'Email / Password is Empty!',
196
+ );
197
+ }
198
+ return $viToken;
199
+ }
200
+
201
+ function wp_insert_vi_api_logout() {
202
+ delete_transient('wp_insert_vi_api_authetication_token');
203
+ //delete_transient('wp_insert_vi_api_settings');
204
+ }
205
+
206
+ function wp_insert_vi_api_get_publisher_id() {
207
+ $viToken = get_transient('wp_insert_vi_api_authetication_token');
208
+ if($viToken === false) {
209
+ return false;
210
+ }
211
+ $viToken = explode('.', $viToken);
212
+ $viToken = base64_decode($viToken[1]);
213
+ $viToken = json_decode($viToken);
214
+ if(json_last_error() == JSON_ERROR_NONE) {
215
+ return $viToken->publisherId;
216
+ }
217
+ return false;
218
+ }
219
+
220
+ function wp_insert_vi_api_get_publisher_token() {
221
+ $viToken = get_transient('wp_insert_vi_api_authetication_token');
222
+ if($viToken === false) {
223
+ return false;
224
+ }
225
+ return $viToken;
226
+ }
227
+
228
+ function wp_insert_vi_api_is_loggedin() {
229
+ $viToken = get_transient('wp_insert_vi_api_authetication_token');
230
+ if($viToken === false) {
231
+ return false;
232
+ }
233
+ return true;
234
+ }
235
+
236
+ function wp_insert_vi_api_get_revenue_data() {
237
+ $viSettings = wp_insert_vi_api_get_settings();
238
+ if(($viSettings != false) && is_array($viSettings)) {
239
+ $viToken = wp_insert_vi_api_get_publisher_token();
240
+ if($viToken !== false) {
241
+ try{
242
+ $response = wp_remote_get(
243
+ $viSettings['revenueAPI'],
244
+ array(
245
+ 'timeout' => 15,
246
+ 'headers' => array(
247
+ 'Content-Type' => 'application/json',
248
+ 'Authorization' => $viToken
249
+ )
250
+ )
251
+ );
252
+ if(!is_wp_error($response)) {
253
+ if(200 == wp_remote_retrieve_response_code($response)) {
254
+ $responseBody = json_decode($response['body']);
255
+ if((json_last_error() == JSON_ERROR_NONE) && ($responseBody->status == 'ok')) {
256
+ return json_decode(json_encode($responseBody->data), True);
257
+ } else {
258
+ return false;
259
+ }
260
+ } else {
261
+ return false;
262
+ }
263
+ }
264
+ } catch(Exception $ex) {
265
+ return false;
266
+ }
267
+ } else {
268
+ return false;
269
+ }
270
+ } else {
271
+ return false;
272
+ }
273
+ }
274
+
275
+ function wp_insert_vi_api_set_vi_code($args = null) {
276
+ $domain = wp_insert_get_domain_name_from_url(get_bloginfo('url'));
277
+ $selectedArgs = array();
278
+ $selectedArgs['domain'] = $domain;
279
+ $selectedArgs['divId'] = 'wp_insert_vi_ad';
280
+
281
+ if(isset($args) && is_array($args)) {
282
+ if(isset($args['ad_unit_type']) && ($args['ad_unit_type'] != '') && ($args['ad_unit_type'] != 'select') && ($args['ad_unit_type'] != 'undefined')) {
283
+ $selectedArgs['adUnitType'] = $args['ad_unit_type'];
284
+ } else {
285
+ $selectedArgs['adUnitType'] = 'NATIVE_VIDEO_UNIT';
286
+ }
287
+
288
+ if(isset($args['language']) && ($args['language'] != '') && ($args['language'] != 'select') && ($args['language'] != 'undefined')) {
289
+ $selectedArgs['language'] = $args['language'];
290
+ }
291
+
292
+ if(isset($args['iab_category_child']) && ($args['iab_category_child'] != '') && ($args['iab_category_child'] != 'select') && ($args['iab_category_child'] != 'undefined')) {
293
+ $selectedArgs['iabCategory'] = $args['iab_category_child'];
294
+ }
295
+
296
+ if(isset($args['font_family']) && ($args['font_family'] != '') && ($args['font_family'] != 'select') && ($args['font_family'] != 'undefined')) {
297
+ $selectedArgs['font'] = $args['font_family'];
298
+ }
299
+
300
+ if(isset($args['font_size']) && ($args['font_size'] != '') && ($args['font_size'] != 'select') && ($args['font_size'] != 'undefined')) {
301
+ $selectedArgs['fontSize'] = $args['font_size'];
302
+ }
303
+
304
+ if(isset($args['keywords']) && ($args['keywords'] != '') && ($args['keywords'] != 'undefined')) {
305
+ $selectedArgs['keywords'] = $args['keywords'];
306
+ } else { //Send the keywords field even if it is empty
307
+ $selectedArgs['keywords'] = '';
308
+ }
309
+
310
+ if(isset($args['native_text_color']) && ($args['native_text_color'] != '') && ($args['native_text_color'] != 'undefined')) {
311
+ $selectedArgs['textColor'] = $args['native_text_color'];
312
+ }
313
+
314
+ if(isset($args['native_bg_color']) && ($args['native_bg_color'] != '') && ($args['native_bg_color'] != 'undefined')) {
315
+ $selectedArgs['backgroundColor'] = $args['native_bg_color'];
316
+ }
317
+
318
+ if(isset($args['optional_1']) && ($args['optional_1'] != '') && ($args['optional_1'] != 'undefined')) {
319
+ $selectedArgs['vioptional1'] = $args['optional_1'];
320
+ }
321
+ if(isset($args['optional_2']) && ($args['optional_2'] != '') && ($args['optional_2'] != 'undefined')) {
322
+ $selectedArgs['vioptional2'] = $args['optional_2'];
323
+ }
324
+ if(isset($args['optional_3']) && ($args['optional_3'] != '') && ($args['optional_3'] != 'undefined')) {
325
+ $selectedArgs['vioptional3'] = $args['optional_3'];
326
+ }
327
+ }
328
+
329
+ $viSettings = wp_insert_vi_api_get_settings();
330
+ if(($viSettings != false) && is_array($viSettings)) {
331
+ $viToken = wp_insert_vi_api_get_publisher_token();
332
+ if($viToken !== false) {
333
+ try{
334
+ $response = wp_remote_request(
335
+ $viSettings['jsTagAPI'],
336
+ array(
337
+ 'method' => 'POST',
338
+ 'timeout' => 15,
339
+ 'headers' => array(
340
+ 'Content-Type' => 'application/json',
341
+ 'Authorization' => $viToken
342
+ ),
343
+ 'body' => json_encode($selectedArgs)
344
+ )
345
+ );
346
+ if(!is_wp_error($response)) {
347
+ if(400 == wp_remote_retrieve_response_code($response)) {
348
+ $responseBody = json_decode($response['body']);
349
+ if((json_last_error() == JSON_ERROR_NONE) && ($responseBody->status == 'error')) {
350
+ return array(
351
+ 'status' => 'error',
352
+ 'errorCode' => 'WIVI108',
353
+ 'message' => $responseBody->error->description,
354
+ );
355
+ } else {
356
+ return array(
357
+ 'status' => 'error',
358
+ 'errorCode' => 'WIVI107',
359
+ 'message' => 'Response JSON error, Please try again later!',
360
+ );
361
+ }
362
+ } else if(201 == wp_remote_retrieve_response_code($response)) {
363
+ $responseBody = json_decode($response['body']);
364
+ if((json_last_error() == JSON_ERROR_NONE) && ($responseBody->status == 'ok')) {
365
+ delete_transient('wp_insert_vi_api_jstag');
366
+ set_transient('wp_insert_vi_api_jstag', $responseBody->data, YEAR_IN_SECONDS);
367
+ return $responseBody->data;
368
+ } else {
369
+ return array(
370
+ 'status' => 'error',
371
+ 'errorCode' => 'WIVI106',
372
+ 'message' => 'Response JSON error!',
373
+ );
374
+ }
375
+ } else {
376
+ return array(
377
+ 'status' => 'error',
378
+ 'errorCode' => 'WIVI105',
379
+ 'message' => 'Unknown response code',
380
+ );
381
+ }
382
+ }
383
+ } catch(Exception $ex) {
384
+ return array(
385
+ 'status' => 'error',
386
+ 'errorCode' => 'WIVI103',
387
+ 'message' => 'Exception during API communication',
388
+ );
389
+ }
390
+ } else {
391
+ return array(
392
+ 'status' => 'error',
393
+ 'errorCode' => 'WIVI102',
394
+ 'message' => 'Authorization Token is Missing',
395
+ );
396
+ }
397
+ } else {
398
+ return array(
399
+ 'status' => 'error',
400
+ 'errorCode' => 'WIVI101',
401
+ 'message' => 'API is unreachable',
402
+ );
403
+ }
404
+ }
405
+
406
+ function wp_insert_vi_api_get_vi_code($settingsKey = '') {
407
+ $jsTag = get_transient('wp_insert_vi_api_jstag');
408
+ if(($jsTag === false) || ($jsTag == '')) {
409
+ if($settingsKey != '') {
410
+ $vicodeSettings = get_option($settingsKey);
411
+ $jsTag = wp_insert_vi_api_set_vi_code($vicodeSettings);
412
+ } else {
413
+ $jsTag = wp_insert_vi_api_set_vi_code();
414
+ }
415
+ if(($jsTag === false) || ($jsTag == '')) {
416
+ return false;
417
+ }
418
+ }
419
+ return '<script type="text/javascript">'.$jsTag.'</script>';
420
+ }
421
+ ?>
includes/assets/css/wp-insert.css CHANGED
@@ -26,6 +26,31 @@
26
  margin: auto;
27
  }
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  .wp-insert .plugin-card-bottom .wp_insert_delete_icon {
30
  color: #b20a0a;
31
  cursor: pointer;
@@ -64,7 +89,7 @@
64
 
65
  .wp_insert_rule_block {
66
  width: calc(50% - 40px);
67
- margin: 20px;
68
  float: left;
69
  }
70
 
@@ -75,15 +100,84 @@
75
  display: block;
76
  font-weight: bold !important;
77
  height: 30px;
78
- margin: auto;
79
  text-shadow: 1px 1px 5px #000;
80
  width: 80%;
81
  }
82
 
 
 
 
 
83
  .wp_insert_rule_block .ui-button.ui-state-active {
84
  background: #C8161B !important;
85
  }
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  .codeSnippet code {
88
  display: block;
89
  font-size: 18px;
@@ -92,6 +186,310 @@
92
  word-wrap: break-word;
93
  }
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  @media screen and (max-width:768px) {
96
  .wp_insert_rule_block {
97
  width: auto;
26
  margin: auto;
27
  }
28
 
29
+ .wp-insert .plugin-card {
30
+ background: #fafafa;
31
+ transition: height 0;
32
+ }
33
+
34
+ .wp-insert .plugin-card.vi-card {
35
+ position: relative;
36
+ }
37
+
38
+ .wp-insert .plugin-card .plugin-card-top {
39
+ background: #ffffff;
40
+ }
41
+
42
+ .wp-insert .plugin-card.vi-card .plugin-card-top {
43
+ padding-bottom: 100px;
44
+ }
45
+
46
+
47
+ .wp-insert .vi-card .plugin-card-bottom {
48
+ bottom: 0;
49
+ left: 0;
50
+ right: 0;
51
+ position: absolute;
52
+ }
53
+
54
  .wp-insert .plugin-card-bottom .wp_insert_delete_icon {
55
  color: #b20a0a;
56
  cursor: pointer;
89
 
90
  .wp_insert_rule_block {
91
  width: calc(50% - 40px);
92
+ margin: 0 20px 5px;
93
  float: left;
94
  }
95
 
100
  display: block;
101
  font-weight: bold !important;
102
  height: 30px;
103
+ margin: 15px auto 0;
104
  text-shadow: 1px 1px 5px #000;
105
  width: 80%;
106
  }
107
 
108
+ .wp_insert_rule_block .ui-helper-hidden-accessible {
109
+ display: none;
110
+ }
111
+
112
  .wp_insert_rule_block .ui-button.ui-state-active {
113
  background: #C8161B !important;
114
  }
115
 
116
+ .wp_insert_popup_content_wrapper .isSelectedIndicator {
117
+ width: 18px;
118
+ height: 18px;
119
+ display: inline-block;
120
+ background: #ddd;
121
+ border-radius: 12px;
122
+ float: left;
123
+ margin-right: 10px;
124
+ cursor: pointer;
125
+ position: relative;
126
+ }
127
+
128
+ .wp_insert_popup_content_wrapper .isSelectedIndicator:after {
129
+ content: '';
130
+ width: 8px;
131
+ height: 8px;
132
+ display: block;
133
+ position: absolute;
134
+ background: #ddd;
135
+ top: 5px;
136
+ left: 5px;
137
+ border-radius: 4px;
138
+
139
+ }
140
+
141
+ .wp_insert_popup_content_wrapper .isSelectedIndicator:before {
142
+ content: '';
143
+ width: 12px;
144
+ height: 12px;
145
+ display: block;
146
+ position: absolute;
147
+ background: #fff;
148
+ top: 3px;
149
+ left: 3px;
150
+ border-radius: 12px;
151
+ }
152
+
153
+ .wp_insert_popup_content_wrapper .isSelectedIndicator:hover, .wp_insert_popup_content_wrapper label:hover .isSelectedIndicator {
154
+ background: #4D3EDB;;
155
+ }
156
+
157
+ .wp_insert_popup_content_wrapper .isSelectedIndicator:hover:after, .wp_insert_popup_content_wrapper label:hover .isSelectedIndicator:after {
158
+ background: #4D3EDB;;
159
+ }
160
+
161
+ .wp_insert_popup_content_wrapper .isSelectedIndicator.active, .wp_insert_popup_content_wrapper .isSelectedIndicator.active:after {
162
+ background: #6ddc5f;
163
+ }
164
+
165
+ .wp_insert_popup_content_wrapper .isSelectedIndicator.active:hover, .wp_insert_popup_content_wrapper label:hover .isSelectedIndicator.active {
166
+ background: #6ddc5f;;
167
+ }
168
+
169
+ .wp_insert_popup_content_wrapper .isSelectedIndicator.disabled:before {
170
+ background: #ddd;
171
+ }
172
+
173
+ .wp_insert_popup_content_wrapper .isSelectedIndicator.disabled:hover, .wp_insert_popup_content_wrapper label:hover .isSelectedIndicator.disabled {
174
+ background: #ddd;
175
+ }
176
+
177
+ .wp_insert_popup_content_wrapper .isSelectedIndicator.disabled:hover:after, .wp_insert_popup_content_wrapper label:hover .isSelectedIndicator.disabled:after {
178
+ background: #ddd;
179
+ }
180
+
181
  .codeSnippet code {
182
  display: block;
183
  font-size: 18px;
186
  word-wrap: break-word;
187
  }
188
 
189
+ .vi-card .plugin-card-top {
190
+ padding: 0;
191
+ }
192
+
193
+ .vi-card .plugin-card-top h4 {
194
+ color: #000;
195
+ font-size: 14px;
196
+ font-weight: 600;
197
+ line-height: 18px;
198
+ margin: 0;
199
+ }
200
+
201
+ .vi-card .plugin-card-top .plugin-card-top-header {
202
+ border-bottom: 1px solid #eee;
203
+ padding: 5px 10px;
204
+ }
205
+
206
+ .vi-card .plugin-card-top .plugin-card-top-content {
207
+ padding: 0 10px 5px;
208
+ font-family: arial;
209
+ font-size: 13px;
210
+ line-height: 18px;
211
+ color: #444444;
212
+ }
213
+
214
+ .vi-card .plugin-card-top .plugin-card-top-content p {
215
+ font-family: arial;
216
+ font-size: 13px;
217
+ line-height: 18px;
218
+ color: #444444;
219
+ }
220
+
221
+
222
+ .vi-card .plugin-card-top .plugin-card-top-content p.strong {
223
+ color: #000;
224
+ font-size: 15px;
225
+ }
226
+
227
+ .vi-card .plugin-card-top .plugin-card-top-content ul {
228
+ margin: 10px 0;
229
+ padding: 0 0 0 15px;
230
+ }
231
+
232
+ .vi-card .plugin-card-top .plugin-card-top-content ul li {
233
+ list-style: outside none "\2022";
234
+ margin: 0;
235
+ padding: 0 0 0 20px;
236
+ }
237
+
238
+ .vi-card .plugin-card-bottom {
239
+ text-align: right;
240
+ padding: 24px 20px;
241
+ }
242
+
243
+ .vi-card .plugin-card-bottom .button {
244
+ height: 32px;
245
+ line-height: 28px;
246
+ padding: 0 15px;
247
+ margin: 5px 0;
248
+ }
249
+
250
+ .vi-card .plugin-card-bottom .button#wp_insert_vi_signup {
251
+ margin: 5px 0 5px 15px;
252
+ }
253
+
254
+ .vi-card .plugin-card-bottom span {
255
+ display: inline;
256
+ float: left;
257
+ font-size: 13px;
258
+ text-align: left;
259
+ width: calc(100% - 200px);
260
+ font-family: arial;
261
+ line-height: 18px;
262
+ }
263
+
264
+ p.viError {
265
+ font-weight: bold;
266
+ color: #fd5740;
267
+ }
268
+
269
+ .vi-card #wp_insert_vi_earnings_wrapper {
270
+ margin-top: 50px;
271
+ }
272
+
273
+ .vi-card #wp_insert_vi_earnings_wrapper #wp_insert_vi_earnings {
274
+ float: left;
275
+ width: calc(100% - 348px);
276
+ margin-top: 38px;
277
+ min-width: 150px;
278
+ margin-bottom: 15px;
279
+ }
280
+
281
+ @media only screen and (max-width: 1256px) {
282
+ .vi-card #wp_insert_vi_earnings_wrapper {
283
+ margin-top: 0;
284
+ }
285
+
286
+ .vi-card #wp_insert_vi_earnings_wrapper #wp_insert_vi_earnings {
287
+ margin-top: 0;
288
+ }
289
+ }
290
+
291
+ .vi-card #wp_insert_vi_earnings_wrapper #wp_insert_vi_earnings #wp_insert_vi_earnings_label {
292
+ color: rgb(35, 40, 45);
293
+ display: block;
294
+ font-size: 14px;
295
+ line-height: 18px;
296
+ font-family: Arial;
297
+ }
298
+
299
+ .vi-card #wp_insert_vi_earnings_wrapper #wp_insert_vi_earnings #wp_insert_vi_earnings_value {
300
+ color: rgb(35, 40, 45);
301
+ display: block;
302
+ font-size: 32px;
303
+ font-weight: bold;
304
+ line-height: 44px;
305
+ font-family: Arial;
306
+ }
307
+
308
+ .vi-card #wp_insert_vi_earnings_wrapper #wp_insert_vi_chart_wrapper {
309
+ float: right;
310
+ height: 139px;
311
+ width: 348px;
312
+ max-width: 100%;
313
+ }
314
+
315
+ .vi-card #wp_insert_vi_earnings_wrapper #wp_insert_vi_chart_wrapper canvas {
316
+ border: 1px solid #ddd
317
+ }
318
+
319
+ .wp_insert_vi_login_error {
320
+ color: #ff0000;
321
+ font-size: 10px;
322
+ margin: -10px 0 0;
323
+ }
324
+
325
+ #wp_insert_vi_customize_adcode {
326
+ margin-left: 10px;
327
+ }
328
+
329
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_right_column {
330
+ width: calc(50% - 30px);
331
+ float: right;
332
+ margin-top: 10px;
333
+ }
334
+
335
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column {
336
+ width: calc(50% - 30px);
337
+ float: left;
338
+ margin-top: 10px;
339
+ font-family: Arial;
340
+ font-size: 13px;
341
+ line-height: 18px;
342
+ }
343
+
344
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p {
345
+ position: relative;
346
+ }
347
+
348
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p label {
349
+ float: left;
350
+ display: inline-block;
351
+ width: 180px;
352
+ }
353
+
354
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p br {
355
+ display: none;
356
+ }
357
+
358
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p input,
359
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p select,
360
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p textarea {
361
+ float: right;
362
+ width: calc(100% - 210px);
363
+ display: inline-block;
364
+ clear: none;
365
+ margin-right: 20px;
366
+ }
367
+
368
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p span.tooltipWrapper {
369
+ position: absolute;
370
+ display: inline-block;
371
+ background: #bababa;
372
+ width: 13px;
373
+ height: 13px;
374
+ border-radius: 7px;
375
+ right: 0;
376
+ top: 5px;
377
+ cursor: pointer;
378
+ }
379
+
380
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p span.tooltipWrapper:after {
381
+ content: "i";
382
+ font-size: 10px;
383
+ font-weight: 600;
384
+ color: #fff;
385
+ line-height: 13px;
386
+ position: relative;
387
+ left: 0;
388
+ right: 0;
389
+ margin: 0 auto 0;
390
+ width: 13px;
391
+ height: 13px;
392
+ display: block;
393
+ text-align: center;
394
+ }
395
+
396
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p span.tooltipWrapper:hover {
397
+ background: #000000;
398
+ }
399
+
400
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p span.tooltipWrapper span.tooltip {
401
+ visibility: hidden;
402
+ width: 142px;
403
+ background-color: #363636;
404
+ color: #fff;
405
+ text-align: left;
406
+ padding: 5px;
407
+ border-radius: 4px;
408
+ position: absolute;
409
+ top: -10px;
410
+ left: 20px;
411
+ z-index: 1;
412
+ font-size: 9px;
413
+ }
414
+
415
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p span.tooltipWrapper span.tooltip br {
416
+ display: block;
417
+ }
418
+
419
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p span.tooltipWrapper:hover span.tooltip {
420
+ visibility: visible;
421
+ }
422
+
423
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p span.tooltipWrapper span.tooltip::after {
424
+ /*content: " ";
425
+ position: absolute;
426
+ top: 50%;
427
+ right: 100%;
428
+ margin-top: -5px;
429
+ border-width: 5px;
430
+ border-style: solid;
431
+ border-color: transparent black transparent transparent;*/
432
+ }
433
+
434
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column .minicolors {
435
+ width: calc(100% - 190px);
436
+ float: right;
437
+ }
438
+
439
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column .minicolors input {
440
+ width: calc(100% - 20px);
441
+ height: 30px;
442
+ }
443
+
444
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p small {
445
+ clear: both;
446
+ height: 1px;
447
+ width: 100%;
448
+ display: block;
449
+ }
450
+
451
+ .wp_insert_popup_content_wrapper .wp_insert_vi_popup_left_column p a.textTip {
452
+ position: absolute;
453
+ right: -92px;
454
+ top: 5px;
455
+ font-size: 11px;
456
+ display: block;
457
+ font-style: italic;
458
+ }
459
+
460
+ .wp_insert_popup_content_wrapper .wp_insert_vi_delay_notice {
461
+ float: right;
462
+ width: calc(100% - 190px);
463
+ display: inline-block;
464
+ clear: both;
465
+ margin: 0 20px 0 0;
466
+ color: #5f5f5f;
467
+ font-size: 13px;
468
+ font-style: italic;
469
+ }
470
+
471
+ .wp_insert_popup_content_wrapper .wp_insert_vi_code_data_wrapper {
472
+ line-height: 24px;
473
+ margin: 18px 0 20px;
474
+ }
475
+
476
+ .wp_insert_popup_content_wrapper .wp_insert_vi_code_data_wrapper label {
477
+ width: 144px;
478
+ display: block;
479
+ font-size: 12px;
480
+ font-family: Arial;
481
+ position: absolute;
482
+ color: #444444;
483
+ }
484
+
485
+ .wp_insert_popup_content_wrapper .wp_insert_vi_code_data_wrapper b {
486
+ margin-left: 164px;
487
+ display: block;
488
+ font-size: 13px;
489
+ font-family: Arial;
490
+ color: #444444;
491
+ }
492
+
493
  @media screen and (max-width:768px) {
494
  .wp_insert_rule_block {
495
  width: auto;
includes/assets/images/advertisement-preview.png ADDED
Binary file
includes/assets/images/vi-big-logo.png ADDED
Binary file
includes/assets/images/vi-empty-graph.jpg ADDED
Binary file
includes/assets/images/vi-logo-large.png ADDED
Binary file
includes/assets/images/vi-logo-small.png ADDED
Binary file
includes/assets/images/vi-no-data.jpg ADDED
Binary file
includes/assets/images/wpinsert-vi.png DELETED
Binary file
includes/assets/js/Chart.bundle.min.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Chart.js
3
+ * http://chartjs.org/
4
+ * Version: 2.7.0
5
+ *
6
+ * Copyright 2017 Nick Downie
7
+ * Released under the MIT license
8
+ * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
9
+ */
10
+ !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function t(e,n,i){function a(o,s){if(!n[o]){if(!e[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(r)return r(o,!0);var u=new Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[o]={exports:{}};e[o][0].call(d.exports,function(t){var n=e[o][1][t];return a(n||t)},d,d.exports,t,e,n,i)}return n[o].exports}for(var r="function"==typeof require&&require,o=0;o<i.length;o++)a(i[o]);return a}({1:[function(t,e,n){function i(t){if(t){var e=/^#([a-fA-F0-9]{3})$/i,n=/^#([a-fA-F0-9]{6})$/i,i=/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,a=/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,r=/(\w+)/,o=[0,0,0],s=1,l=t.match(e);if(l){l=l[1];for(d=0;d<o.length;d++)o[d]=parseInt(l[d]+l[d],16)}else if(l=t.match(n)){l=l[1];for(d=0;d<o.length;d++)o[d]=parseInt(l.slice(2*d,2*d+2),16)}else if(l=t.match(i)){for(d=0;d<o.length;d++)o[d]=parseInt(l[d+1]);s=parseFloat(l[4])}else if(l=t.match(a)){for(d=0;d<o.length;d++)o[d]=Math.round(2.55*parseFloat(l[d+1]));s=parseFloat(l[4])}else if(l=t.match(r)){if("transparent"==l[1])return[0,0,0,0];if(!(o=c[l[1]]))return}for(var d=0;d<o.length;d++)o[d]=u(o[d],0,255);return s=s||0==s?u(s,0,1):1,o[3]=s,o}}function a(t){if(t){var e=/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,n=t.match(e);if(n){var i=parseFloat(n[4]);return[u(parseInt(n[1]),0,360),u(parseFloat(n[2]),0,100),u(parseFloat(n[3]),0,100),u(isNaN(i)?1:i,0,1)]}}}function r(t){if(t){var e=/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,n=t.match(e);if(n){var i=parseFloat(n[4]);return[u(parseInt(n[1]),0,360),u(parseFloat(n[2]),0,100),u(parseFloat(n[3]),0,100),u(isNaN(i)?1:i,0,1)]}}}function o(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function s(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function l(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function u(t,e,n){return Math.min(Math.max(e,t),n)}function d(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var c=t(5);e.exports={getRgba:i,getHsla:a,getRgb:function(t){var e=i(t);return e&&e.slice(0,3)},getHsl:function(t){var e=a(t);return e&&e.slice(0,3)},getHwb:r,getAlpha:function(t){var e=i(t);return e?e[3]:(e=a(t))?e[3]:(e=r(t))?e[3]:void 0},hexString:function(t){return"#"+d(t[0])+d(t[1])+d(t[2])},rgbString:function(t,e){return e<1||t[3]&&t[3]<1?o(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:o,percentString:function(t,e){return e<1||t[3]&&t[3]<1?s(t,e):"rgb("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%)"},percentaString:s,hslString:function(t,e){return e<1||t[3]&&t[3]<1?l(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:l,hwbString:function(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return h[t.slice(0,3)]}};var h={};for(var f in c)h[c[f]]=f},{5:5}],2:[function(t,e,n){var i=t(4),a=t(1),r=function(t){if(t instanceof r)return t;if(!(this instanceof r))return new r(t);this.valid=!1,this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1};var e;"string"==typeof t?(e=a.getRgba(t))?this.setValues("rgb",e):(e=a.getHsla(t))?this.setValues("hsl",e):(e=a.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e))};r.prototype={isValid:function(){return this.valid},rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t=(t%=360)<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],n=0;n<t.length;n++){var i=t[n]/255;e[n]=i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),n=t.luminosity();return e>n?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=this,i=t,a=void 0===e?.5:e,r=2*a-1,o=n.alpha()-i.alpha(),s=((r*o==-1?r:(r+o)/(1+r*o))+1)/2,l=1-s;return this.rgb(s*n.red()+l*i.red(),s*n.green()+l*i.green(),s*n.blue()+l*i.blue()).alpha(n.alpha()*a+i.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new r,i=this.values,a=n.values;for(var o in i)i.hasOwnProperty(o)&&(t=i[o],"[object Array]"===(e={}.toString.call(t))?a[o]=t.slice(0):"[object Number]"===e?a[o]=t:console.error("unexpected color value:",t));return n}},r.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},r.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},r.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i<t.length;i++)n[t.charAt(i)]=e[t][i];return 1!==e.alpha&&(n.a=e.alpha),n},r.prototype.setValues=function(t,e){var n,a=this.values,r=this.spaces,o=this.maxes,s=1;if(this.valid=!0,"alpha"===t)s=e;else if(e.length)a[t]=e.slice(0,t.length),s=e[t.length];else if(void 0!==e[t.charAt(0)]){for(n=0;n<t.length;n++)a[t][n]=e[t.charAt(n)];s=e.a}else if(void 0!==e[r[t][0]]){var l=r[t];for(n=0;n<t.length;n++)a[t][n]=e[l[n]];s=e.alpha}if(a.alpha=Math.max(0,Math.min(1,void 0===s?a.alpha:s)),"alpha"===t)return!1;var u;for(n=0;n<t.length;n++)u=Math.max(0,Math.min(o[t][n],a[t][n])),a[t][n]=Math.round(u);for(var d in r)d!==t&&(a[d]=i[t][d](a[t]));return!0},r.prototype.setSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n),this)},r.prototype.setChannel=function(t,e,n){var i=this.values[t];return void 0===n?i[e]:n===i[e]?this:(i[e]=n,this.setValues(t,i),this)},"undefined"!=typeof window&&(window.Color=r),e.exports=r},{1:1,4:4}],3:[function(t,e,n){function i(t){var e,n,i,a=t[0]/255,r=t[1]/255,o=t[2]/255,s=Math.min(a,r,o),l=Math.max(a,r,o),u=l-s;return l==s?e=0:a==l?e=(r-o)/u:r==l?e=2+(o-a)/u:o==l&&(e=4+(a-r)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=(s+l)/2,n=l==s?0:i<=.5?u/(l+s):u/(2-l-s),[e,100*n,100*i]}function a(t){var e,n,i,a=t[0],r=t[1],o=t[2],s=Math.min(a,r,o),l=Math.max(a,r,o),u=l-s;return n=0==l?0:u/l*1e3/10,l==s?e=0:a==l?e=(r-o)/u:r==l?e=2+(o-a)/u:o==l&&(e=4+(a-r)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=l/255*1e3/10,[e,n,i]}function o(t){var e=t[0],n=t[1],a=t[2];return[i(t)[0],100*(1/255*Math.min(e,Math.min(n,a))),100*(a=1-1/255*Math.max(e,Math.max(n,a)))]}function s(t){var e,n,i,a,r=t[0]/255,o=t[1]/255,s=t[2]/255;return a=Math.min(1-r,1-o,1-s),e=(1-r-a)/(1-a)||0,n=(1-o-a)/(1-a)||0,i=(1-s-a)/(1-a)||0,[100*e,100*n,100*i,100*a]}function l(t){return S[JSON.stringify(t)]}function u(t){var e=t[0]/255,n=t[1]/255,i=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]}function d(t){var e,n,i,a=u(t),r=a[0],o=a[1],s=a[2];return r/=95.047,o/=100,s/=108.883,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,s=s>.008856?Math.pow(s,1/3):7.787*s+16/116,e=116*o-16,n=500*(r-o),i=200*(o-s),[e,n,i]}function c(t){var e,n,i,a,r,o=t[0]/360,s=t[1]/100,l=t[2]/100;if(0==s)return r=255*l,[r,r,r];e=2*l-(n=l<.5?l*(1+s):l+s-l*s),a=[0,0,0];for(var u=0;u<3;u++)(i=o+1/3*-(u-1))<0&&i++,i>1&&i--,r=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*r;return a}function h(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,r=e-Math.floor(e),o=255*i*(1-n),s=255*i*(1-n*r),l=255*i*(1-n*(1-r)),i=255*i;switch(a){case 0:return[i,l,o];case 1:return[s,i,o];case 2:return[o,i,l];case 3:return[o,s,i];case 4:return[l,o,i];case 5:return[i,o,s]}}function f(t){var e,n,i,a,o=t[0]/360,s=t[1]/100,l=t[2]/100,u=s+l;switch(u>1&&(s/=u,l/=u),e=Math.floor(6*o),n=1-l,i=6*o-e,0!=(1&e)&&(i=1-i),a=s+i*(n-s),e){default:case 6:case 0:r=n,g=a,b=s;break;case 1:r=a,g=n,b=s;break;case 2:r=s,g=n,b=a;break;case 3:r=s,g=a,b=n;break;case 4:r=a,g=s,b=n;break;case 5:r=n,g=s,b=a}return[255*r,255*g,255*b]}function m(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100,s=t[3]/100;return e=1-Math.min(1,a*(1-s)+s),n=1-Math.min(1,r*(1-s)+s),i=1-Math.min(1,o*(1-s)+s),[255*e,255*n,255*i]}function p(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100;return e=3.2406*a+-1.5372*r+-.4986*o,n=-.9689*a+1.8758*r+.0415*o,i=.0557*a+-.204*r+1.057*o,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,e=Math.min(Math.max(0,e),1),n=Math.min(Math.max(0,n),1),i=Math.min(Math.max(0,i),1),[255*e,255*n,255*i]}function v(t){var e,n,i,a=t[0],r=t[1],o=t[2];return a/=95.047,r/=100,o/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,e=116*r-16,n=500*(a-r),i=200*(r-o),[e,n,i]}function y(t){var e,n,i,a,r=t[0],o=t[1],s=t[2];return r<=8?a=(n=100*r/903.3)/100*7.787+16/116:(n=100*Math.pow((r+16)/116,3),a=Math.pow(n/100,1/3)),e=e/95.047<=.008856?e=95.047*(o/500+a-16/116)/7.787:95.047*Math.pow(o/500+a,3),i=i/108.883<=.008859?i=108.883*(a-s/200-16/116)/7.787:108.883*Math.pow(a-s/200,3),[e,n,i]}function x(t){var e,n,i,a=t[0],r=t[1],o=t[2];return e=Math.atan2(o,r),(n=360*e/2/Math.PI)<0&&(n+=360),i=Math.sqrt(r*r+o*o),[a,i,n]}function _(t){return p(y(t))}function k(t){var e,n,i,a=t[0],r=t[1];return i=t[2]/360*2*Math.PI,e=r*Math.cos(i),n=r*Math.sin(i),[a,e,n]}function w(t){return M[t]}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:s,rgb2keyword:l,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return x(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e,n,i=t[0],a=t[1]/100,r=t[2]/100;return 0===r?[0,0,0]:(r*=2,a*=r<=1?r:2-r,n=(r+a)/2,e=2*a/(r+a),[i,100*e,100*n])},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return s(c(t))},hsl2keyword:function(t){return l(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,n,i=t[0],a=t[1]/100,r=t[2]/100;return n=(2-a)*r,e=a*r,e/=n<=1?n:2-n,e=e||0,n/=2,[i,100*e,100*n]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return s(h(t))},hsv2keyword:function(t){return l(h(t))},hwb2rgb:f,hwb2hsl:function(t){return i(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return s(f(t))},hwb2keyword:function(t){return l(f(t))},cmyk2rgb:m,cmyk2hsl:function(t){return i(m(t))},cmyk2hsv:function(t){return a(m(t))},cmyk2hwb:function(t){return o(m(t))},cmyk2keyword:function(t){return l(m(t))},keyword2rgb:w,keyword2hsl:function(t){return i(w(t))},keyword2hsv:function(t){return a(w(t))},keyword2hwb:function(t){return o(w(t))},keyword2cmyk:function(t){return s(w(t))},keyword2lab:function(t){return d(w(t))},keyword2xyz:function(t){return u(w(t))},xyz2rgb:p,xyz2lab:v,xyz2lch:function(t){return x(v(t))},lab2xyz:y,lab2rgb:_,lab2lch:x,lch2lab:k,lch2xyz:function(t){return y(k(t))},lch2rgb:function(t){return _(k(t))}};var M={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},S={};for(var D in M)S[JSON.stringify(M[D])]=D},{}],4:[function(t,e,n){var i=t(3),a=function(){return new u};for(var r in i){a[r+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(r);var o=/(\w+)2(\w+)/.exec(r),s=o[1],l=o[2];(a[s]=a[s]||{})[l]=a[r]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a<n.length;a++)n[a]=Math.round(n[a]);return n}}(r)}var u=function(){this.convs={}};u.prototype.routeSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n))},u.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},u.prototype.getValues=function(t){var e=this.convs[t];if(!e){var n=this.space,i=this.convs[n];e=a[n][t](i),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){u.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{3:3}],5:[function(t,e,n){"use strict";e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],6:[function(t,e,n){!function(t,i){"object"==typeof n&&void 0!==e?e.exports=i():t.moment=i()}(this,function(){"use strict";function n(){return xe.apply(null,arguments)}function i(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function a(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function r(t){var e;for(e in t)return!1;return!0}function o(t){return void 0===t}function s(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function l(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function u(t,e){var n,i=[];for(n=0;n<t.length;++n)i.push(e(t[n],n));return i}function d(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function c(t,e){for(var n in e)d(e,n)&&(t[n]=e[n]);return d(e,"toString")&&(t.toString=e.toString),d(e,"valueOf")&&(t.valueOf=e.valueOf),t}function h(t,e,n,i){return Yt(t,e,n,i,!0).utc()}function f(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}}function g(t){return null==t._pf&&(t._pf=f()),t._pf}function m(t){if(null==t._isValid){var e=g(t),n=ke.call(e.parsedDateParts,function(t){return null!=t}),i=!isNaN(t._d.getTime())&&e.overflow<0&&!e.empty&&!e.invalidMonth&&!e.invalidWeekday&&!e.nullInput&&!e.invalidFormat&&!e.userInvalidated&&(!e.meridiem||e.meridiem&&n);if(t._strict&&(i=i&&0===e.charsLeftOver&&0===e.unusedTokens.length&&void 0===e.bigHour),null!=Object.isFrozen&&Object.isFrozen(t))return i;t._isValid=i}return t._isValid}function p(t){var e=h(NaN);return null!=t?c(g(e),t):g(e).userInvalidated=!0,e}function v(t,e){var n,i,a;if(o(e._isAMomentObject)||(t._isAMomentObject=e._isAMomentObject),o(e._i)||(t._i=e._i),o(e._f)||(t._f=e._f),o(e._l)||(t._l=e._l),o(e._strict)||(t._strict=e._strict),o(e._tzm)||(t._tzm=e._tzm),o(e._isUTC)||(t._isUTC=e._isUTC),o(e._offset)||(t._offset=e._offset),o(e._pf)||(t._pf=g(e)),o(e._locale)||(t._locale=e._locale),we.length>0)for(n=0;n<we.length;n++)o(a=e[i=we[n]])||(t[i]=a);return t}function y(t){v(this,t),this._d=new Date(null!=t._d?t._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===Me&&(Me=!0,n.updateOffset(this),Me=!1)}function b(t){return t instanceof y||null!=t&&null!=t._isAMomentObject}function x(t){return t<0?Math.ceil(t)||0:Math.floor(t)}function _(t){var e=+t,n=0;return 0!==e&&isFinite(e)&&(n=x(e)),n}function k(t,e,n){var i,a=Math.min(t.length,e.length),r=Math.abs(t.length-e.length),o=0;for(i=0;i<a;i++)(n&&t[i]!==e[i]||!n&&_(t[i])!==_(e[i]))&&o++;return o+r}function w(t){!1===n.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function M(t,e){var i=!0;return c(function(){if(null!=n.deprecationHandler&&n.deprecationHandler(null,t),i){for(var a,r=[],o=0;o<arguments.length;o++){if(a="","object"==typeof arguments[o]){a+="\n["+o+"] ";for(var s in arguments[0])a+=s+": "+arguments[0][s]+", ";a=a.slice(0,-2)}else a=arguments[o];r.push(a)}w(t+"\nArguments: "+Array.prototype.slice.call(r).join("")+"\n"+(new Error).stack),i=!1}return e.apply(this,arguments)},e)}function S(t,e){null!=n.deprecationHandler&&n.deprecationHandler(t,e),Se[t]||(w(e),Se[t]=!0)}function D(t){return t instanceof Function||"[object Function]"===Object.prototype.toString.call(t)}function C(t,e){var n,i=c({},t);for(n in e)d(e,n)&&(a(t[n])&&a(e[n])?(i[n]={},c(i[n],t[n]),c(i[n],e[n])):null!=e[n]?i[n]=e[n]:delete i[n]);for(n in t)d(t,n)&&!d(e,n)&&a(t[n])&&(i[n]=c({},i[n]));return i}function P(t){null!=t&&this.set(t)}function T(t,e){var n=t.toLowerCase();Fe[n]=Fe[n+"s"]=Fe[e]=t}function I(t){return"string"==typeof t?Fe[t]||Fe[t.toLowerCase()]:void 0}function A(t){var e,n,i={};for(n in t)d(t,n)&&(e=I(n))&&(i[e]=t[n]);return i}function O(t,e){Re[t]=e}function F(t){var e=[];for(var n in t)e.push({unit:n,priority:Re[n]});return e.sort(function(t,e){return t.priority-e.priority}),e}function R(t,e){return function(i){return null!=i?(W(this,t,i),n.updateOffset(this,e),this):L(this,t)}}function L(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function W(t,e,n){t.isValid()&&t._d["set"+(t._isUTC?"UTC":"")+e](n)}function Y(t,e,n){var i=""+Math.abs(t),a=e-i.length;return(t>=0?n?"+":"":"-")+Math.pow(10,Math.max(0,a)).toString().substr(1)+i}function N(t,e,n,i){var a=i;"string"==typeof i&&(a=function(){return this[i]()}),t&&(Ne[t]=a),e&&(Ne[e[0]]=function(){return Y(a.apply(this,arguments),e[1],e[2])}),n&&(Ne[n]=function(){return this.localeData().ordinal(a.apply(this,arguments),t)})}function z(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function B(t){var e,n,i=t.match(Le);for(e=0,n=i.length;e<n;e++)Ne[i[e]]?i[e]=Ne[i[e]]:i[e]=z(i[e]);return function(e){var a,r="";for(a=0;a<n;a++)r+=D(i[a])?i[a].call(e,t):i[a];return r}}function V(t,e){return t.isValid()?(e=H(e,t.localeData()),Ye[e]=Ye[e]||B(e),Ye[e](t)):t.localeData().invalidDate()}function H(t,e){var n=5;for(We.lastIndex=0;n>=0&&We.test(t);)t=t.replace(We,function(t){return e.longDateFormat(t)||t}),We.lastIndex=0,n-=1;return t}function E(t,e,n){nn[t]=D(e)?e:function(t,i){return t&&n?n:e}}function j(t,e){return d(nn,t)?nn[t](e._strict,e._locale):new RegExp(U(t))}function U(t){return q(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,n,i,a){return e||n||i||a}))}function q(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function G(t,e){var n,i=e;for("string"==typeof t&&(t=[t]),s(e)&&(i=function(t,n){n[e]=_(t)}),n=0;n<t.length;n++)an[t[n]]=i}function Z(t,e){G(t,function(t,n,i,a){i._w=i._w||{},e(t,i._w,i,a)})}function X(t,e,n){null!=e&&d(an,t)&&an[t](e,n._a,n,t)}function J(t,e){return new Date(Date.UTC(t,e+1,0)).getUTCDate()}function K(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],i=0;i<12;++i)r=h([2e3,i]),this._shortMonthsParse[i]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[i]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===e?-1!==(a=gn.call(this._shortMonthsParse,o))?a:null:-1!==(a=gn.call(this._longMonthsParse,o))?a:null:"MMM"===e?-1!==(a=gn.call(this._shortMonthsParse,o))?a:-1!==(a=gn.call(this._longMonthsParse,o))?a:null:-1!==(a=gn.call(this._longMonthsParse,o))?a:-1!==(a=gn.call(this._shortMonthsParse,o))?a:null}function Q(t,e){var n;if(!t.isValid())return t;if("string"==typeof e)if(/^\d+$/.test(e))e=_(e);else if(e=t.localeData().monthsParse(e),!s(e))return t;return n=Math.min(t.date(),J(t.year(),e)),t._d["set"+(t._isUTC?"UTC":"")+"Month"](e,n),t}function $(t){return null!=t?(Q(this,t),n.updateOffset(this,!0),this):L(this,"Month")}function tt(){function t(t,e){return e.length-t.length}var e,n,i=[],a=[],r=[];for(e=0;e<12;e++)n=h([2e3,e]),i.push(this.monthsShort(n,"")),a.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(i.sort(t),a.sort(t),r.sort(t),e=0;e<12;e++)i[e]=q(i[e]),a[e]=q(a[e]);for(e=0;e<24;e++)r[e]=q(r[e]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+i.join("|")+")","i")}function et(t){return nt(t)?366:365}function nt(t){return t%4==0&&t%100!=0||t%400==0}function it(t,e,n,i,a,r,o){var s=new Date(t,e,n,i,a,r,o);return t<100&&t>=0&&isFinite(s.getFullYear())&&s.setFullYear(t),s}function at(t){var e=new Date(Date.UTC.apply(null,arguments));return t<100&&t>=0&&isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t),e}function rt(t,e,n){var i=7+e-n;return-((7+at(t,0,i).getUTCDay()-e)%7)+i-1}function ot(t,e,n,i,a){var r,o,s=1+7*(e-1)+(7+n-i)%7+rt(t,i,a);return s<=0?o=et(r=t-1)+s:s>et(t)?(r=t+1,o=s-et(t)):(r=t,o=s),{year:r,dayOfYear:o}}function st(t,e,n){var i,a,r=rt(t.year(),e,n),o=Math.floor((t.dayOfYear()-r-1)/7)+1;return o<1?i=o+lt(a=t.year()-1,e,n):o>lt(t.year(),e,n)?(i=o-lt(t.year(),e,n),a=t.year()+1):(a=t.year(),i=o),{week:i,year:a}}function lt(t,e,n){var i=rt(t,e,n),a=rt(t+1,e,n);return(et(t)-i+a)/7}function ut(t,e){return"string"!=typeof t?t:isNaN(t)?"number"==typeof(t=e.weekdaysParse(t))?t:null:parseInt(t,10)}function dt(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}function ct(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],i=0;i<7;++i)r=h([2e3,1]).day(i),this._minWeekdaysParse[i]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[i]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[i]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===e?-1!==(a=gn.call(this._weekdaysParse,o))?a:null:"ddd"===e?-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:null:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:null:"dddd"===e?-1!==(a=gn.call(this._weekdaysParse,o))?a:-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:null:"ddd"===e?-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:-1!==(a=gn.call(this._weekdaysParse,o))?a:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:null:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:-1!==(a=gn.call(this._weekdaysParse,o))?a:-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:null}function ht(){function t(t,e){return e.length-t.length}var e,n,i,a,r,o=[],s=[],l=[],u=[];for(e=0;e<7;e++)n=h([2e3,1]).day(e),i=this.weekdaysMin(n,""),a=this.weekdaysShort(n,""),r=this.weekdays(n,""),o.push(i),s.push(a),l.push(r),u.push(i),u.push(a),u.push(r);for(o.sort(t),s.sort(t),l.sort(t),u.sort(t),e=0;e<7;e++)s[e]=q(s[e]),l[e]=q(l[e]),u[e]=q(u[e]);this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function ft(){return this.hours()%12||12}function gt(t,e){N(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function mt(t,e){return e._meridiemParse}function pt(t){return t?t.toLowerCase().replace("_","-"):t}function vt(t){for(var e,n,i,a,r=0;r<t.length;){for(e=(a=pt(t[r]).split("-")).length,n=(n=pt(t[r+1]))?n.split("-"):null;e>0;){if(i=yt(a.slice(0,e).join("-")))return i;if(n&&n.length>=e&&k(a,n,!0)>=e-1)break;e--}r++}return null}function yt(n){var i=null;if(!On[n]&&void 0!==e&&e&&e.exports)try{i=Pn._abbr,t("./locale/"+n),bt(i)}catch(t){}return On[n]}function bt(t,e){var n;return t&&(n=o(e)?_t(t):xt(t,e))&&(Pn=n),Pn._abbr}function xt(t,e){if(null!==e){var n=An;if(e.abbr=t,null!=On[t])S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),n=On[t]._config;else if(null!=e.parentLocale){if(null==On[e.parentLocale])return Fn[e.parentLocale]||(Fn[e.parentLocale]=[]),Fn[e.parentLocale].push({name:t,config:e}),null;n=On[e.parentLocale]._config}return On[t]=new P(C(n,e)),Fn[t]&&Fn[t].forEach(function(t){xt(t.name,t.config)}),bt(t),On[t]}return delete On[t],null}function _t(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return Pn;if(!i(t)){if(e=yt(t))return e;t=[t]}return vt(t)}function kt(t){var e,n=t._a;return n&&-2===g(t).overflow&&(e=n[on]<0||n[on]>11?on:n[sn]<1||n[sn]>J(n[rn],n[on])?sn:n[ln]<0||n[ln]>24||24===n[ln]&&(0!==n[un]||0!==n[dn]||0!==n[cn])?ln:n[un]<0||n[un]>59?un:n[dn]<0||n[dn]>59?dn:n[cn]<0||n[cn]>999?cn:-1,g(t)._overflowDayOfYear&&(e<rn||e>sn)&&(e=sn),g(t)._overflowWeeks&&-1===e&&(e=hn),g(t)._overflowWeekday&&-1===e&&(e=fn),g(t).overflow=e),t}function wt(t){var e,n,i,a,r,o,s=t._i,l=Rn.exec(s)||Ln.exec(s);if(l){for(g(t).iso=!0,e=0,n=Yn.length;e<n;e++)if(Yn[e][1].exec(l[1])){a=Yn[e][0],i=!1!==Yn[e][2];break}if(null==a)return void(t._isValid=!1);if(l[3]){for(e=0,n=Nn.length;e<n;e++)if(Nn[e][1].exec(l[3])){r=(l[2]||" ")+Nn[e][0];break}if(null==r)return void(t._isValid=!1)}if(!i&&null!=r)return void(t._isValid=!1);if(l[4]){if(!Wn.exec(l[4]))return void(t._isValid=!1);o="Z"}t._f=a+(r||"")+(o||""),It(t)}else t._isValid=!1}function Mt(t){var e,n,i,a,r,o,s,l,u={" GMT":" +0000"," EDT":" -0400"," EST":" -0500"," CDT":" -0500"," CST":" -0600"," MDT":" -0600"," MST":" -0700"," PDT":" -0700"," PST":" -0800"};if(e=t._i.replace(/\([^\)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s|\s$/g,""),n=Bn.exec(e)){if(i=n[1]?"ddd"+(5===n[1].length?", ":" "):"",a="D MMM "+(n[2].length>10?"YYYY ":"YY "),r="HH:mm"+(n[4]?":ss":""),n[1]){var d=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][new Date(n[2]).getDay()];if(n[1].substr(0,3)!==d)return g(t).weekdayMismatch=!0,void(t._isValid=!1)}switch(n[5].length){case 2:s=0===l?" +0000":((l="YXWVUTSRQPONZABCDEFGHIKLM".indexOf(n[5][1].toUpperCase())-12)<0?" -":" +")+(""+l).replace(/^-?/,"0").match(/..$/)[0]+"00";break;case 4:s=u[n[5]];break;default:s=u[" GMT"]}n[5]=s,t._i=n.splice(1).join(""),o=" ZZ",t._f=i+a+r+o,It(t),g(t).rfc2822=!0}else t._isValid=!1}function St(t){var e=zn.exec(t._i);null===e?(wt(t),!1===t._isValid&&(delete t._isValid,Mt(t),!1===t._isValid&&(delete t._isValid,n.createFromInputFallback(t)))):t._d=new Date(+e[1])}function Dt(t,e,n){return null!=t?t:null!=e?e:n}function Ct(t){var e=new Date(n.now());return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function Pt(t){var e,n,i,a,r=[];if(!t._d){for(i=Ct(t),t._w&&null==t._a[sn]&&null==t._a[on]&&Tt(t),null!=t._dayOfYear&&(a=Dt(t._a[rn],i[rn]),(t._dayOfYear>et(a)||0===t._dayOfYear)&&(g(t)._overflowDayOfYear=!0),n=at(a,0,t._dayOfYear),t._a[on]=n.getUTCMonth(),t._a[sn]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=r[e]=i[e];for(;e<7;e++)t._a[e]=r[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[ln]&&0===t._a[un]&&0===t._a[dn]&&0===t._a[cn]&&(t._nextDay=!0,t._a[ln]=0),t._d=(t._useUTC?at:it).apply(null,r),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[ln]=24)}}function Tt(t){var e,n,i,a,r,o,s,l;if(null!=(e=t._w).GG||null!=e.W||null!=e.E)r=1,o=4,n=Dt(e.GG,t._a[rn],st(Nt(),1,4).year),i=Dt(e.W,1),((a=Dt(e.E,1))<1||a>7)&&(l=!0);else{r=t._locale._week.dow,o=t._locale._week.doy;var u=st(Nt(),r,o);n=Dt(e.gg,t._a[rn],u.year),i=Dt(e.w,u.week),null!=e.d?((a=e.d)<0||a>6)&&(l=!0):null!=e.e?(a=e.e+r,(e.e<0||e.e>6)&&(l=!0)):a=r}i<1||i>lt(n,r,o)?g(t)._overflowWeeks=!0:null!=l?g(t)._overflowWeekday=!0:(s=ot(n,i,a,r,o),t._a[rn]=s.year,t._dayOfYear=s.dayOfYear)}function It(t){if(t._f!==n.ISO_8601)if(t._f!==n.RFC_2822){t._a=[],g(t).empty=!0;var e,i,a,r,o,s=""+t._i,l=s.length,u=0;for(a=H(t._f,t._locale).match(Le)||[],e=0;e<a.length;e++)r=a[e],(i=(s.match(j(r,t))||[])[0])&&((o=s.substr(0,s.indexOf(i))).length>0&&g(t).unusedInput.push(o),s=s.slice(s.indexOf(i)+i.length),u+=i.length),Ne[r]?(i?g(t).empty=!1:g(t).unusedTokens.push(r),X(r,i,t)):t._strict&&!i&&g(t).unusedTokens.push(r);g(t).charsLeftOver=l-u,s.length>0&&g(t).unusedInput.push(s),t._a[ln]<=12&&!0===g(t).bigHour&&t._a[ln]>0&&(g(t).bigHour=void 0),g(t).parsedDateParts=t._a.slice(0),g(t).meridiem=t._meridiem,t._a[ln]=At(t._locale,t._a[ln],t._meridiem),Pt(t),kt(t)}else Mt(t);else wt(t)}function At(t,e,n){var i;return null==n?e:null!=t.meridiemHour?t.meridiemHour(e,n):null!=t.isPM?((i=t.isPM(n))&&e<12&&(e+=12),i||12!==e||(e=0),e):e}function Ot(t){var e,n,i,a,r;if(0===t._f.length)return g(t).invalidFormat=!0,void(t._d=new Date(NaN));for(a=0;a<t._f.length;a++)r=0,e=v({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[a],It(e),m(e)&&(r+=g(e).charsLeftOver,r+=10*g(e).unusedTokens.length,g(e).score=r,(null==i||r<i)&&(i=r,n=e));c(t,n||e)}function Ft(t){if(!t._d){var e=A(t._i);t._a=u([e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],function(t){return t&&parseInt(t,10)}),Pt(t)}}function Rt(t){var e=new y(kt(Lt(t)));return e._nextDay&&(e.add(1,"d"),e._nextDay=void 0),e}function Lt(t){var e=t._i,n=t._f;return t._locale=t._locale||_t(t._l),null===e||void 0===n&&""===e?p({nullInput:!0}):("string"==typeof e&&(t._i=e=t._locale.preparse(e)),b(e)?new y(kt(e)):(l(e)?t._d=e:i(n)?Ot(t):n?It(t):Wt(t),m(t)||(t._d=null),t))}function Wt(t){var e=t._i;o(e)?t._d=new Date(n.now()):l(e)?t._d=new Date(e.valueOf()):"string"==typeof e?St(t):i(e)?(t._a=u(e.slice(0),function(t){return parseInt(t,10)}),Pt(t)):a(e)?Ft(t):s(e)?t._d=new Date(e):n.createFromInputFallback(t)}function Yt(t,e,n,o,s){var l={};return!0!==n&&!1!==n||(o=n,n=void 0),(a(t)&&r(t)||i(t)&&0===t.length)&&(t=void 0),l._isAMomentObject=!0,l._useUTC=l._isUTC=s,l._l=n,l._i=t,l._f=e,l._strict=o,Rt(l)}function Nt(t,e,n,i){return Yt(t,e,n,i,!1)}function zt(t,e){var n,a;if(1===e.length&&i(e[0])&&(e=e[0]),!e.length)return Nt();for(n=e[0],a=1;a<e.length;++a)e[a].isValid()&&!e[a][t](n)||(n=e[a]);return n}function Bt(t){for(var e in t)if(-1===En.indexOf(e)||null!=t[e]&&isNaN(t[e]))return!1;for(var n=!1,i=0;i<En.length;++i)if(t[En[i]]){if(n)return!1;parseFloat(t[En[i]])!==_(t[En[i]])&&(n=!0)}return!0}function Vt(t){var e=A(t),n=e.year||0,i=e.quarter||0,a=e.month||0,r=e.week||0,o=e.day||0,s=e.hour||0,l=e.minute||0,u=e.second||0,d=e.millisecond||0;this._isValid=Bt(e),this._milliseconds=+d+1e3*u+6e4*l+1e3*s*60*60,this._days=+o+7*r,this._months=+a+3*i+12*n,this._data={},this._locale=_t(),this._bubble()}function Ht(t){return t instanceof Vt}function Et(t){return t<0?-1*Math.round(-1*t):Math.round(t)}function jt(t,e){N(t,0,0,function(){var t=this.utcOffset(),n="+";return t<0&&(t=-t,n="-"),n+Y(~~(t/60),2)+e+Y(~~t%60,2)})}function Ut(t,e){var n=(e||"").match(t);if(null===n)return null;var i=((n[n.length-1]||[])+"").match(jn)||["-",0,0],a=60*i[1]+_(i[2]);return 0===a?0:"+"===i[0]?a:-a}function qt(t,e){var i,a;return e._isUTC?(i=e.clone(),a=(b(t)||l(t)?t.valueOf():Nt(t).valueOf())-i.valueOf(),i._d.setTime(i._d.valueOf()+a),n.updateOffset(i,!1),i):Nt(t).local()}function Gt(t){return 15*-Math.round(t._d.getTimezoneOffset()/15)}function Zt(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function Xt(t,e){var n,i,a,r=t,o=null;return Ht(t)?r={ms:t._milliseconds,d:t._days,M:t._months}:s(t)?(r={},e?r[e]=t:r.milliseconds=t):(o=Un.exec(t))?(n="-"===o[1]?-1:1,r={y:0,d:_(o[sn])*n,h:_(o[ln])*n,m:_(o[un])*n,s:_(o[dn])*n,ms:_(Et(1e3*o[cn]))*n}):(o=qn.exec(t))?(n="-"===o[1]?-1:1,r={y:Jt(o[2],n),M:Jt(o[3],n),w:Jt(o[4],n),d:Jt(o[5],n),h:Jt(o[6],n),m:Jt(o[7],n),s:Jt(o[8],n)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(a=Qt(Nt(r.from),Nt(r.to)),(r={}).ms=a.milliseconds,r.M=a.months),i=new Vt(r),Ht(t)&&d(t,"_locale")&&(i._locale=t._locale),i}function Jt(t,e){var n=t&&parseFloat(t.replace(",","."));return(isNaN(n)?0:n)*e}function Kt(t,e){var n={milliseconds:0,months:0};return n.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(n.months,"M").isAfter(e)&&--n.months,n.milliseconds=+e-+t.clone().add(n.months,"M"),n}function Qt(t,e){var n;return t.isValid()&&e.isValid()?(e=qt(e,t),t.isBefore(e)?n=Kt(t,e):((n=Kt(e,t)).milliseconds=-n.milliseconds,n.months=-n.months),n):{milliseconds:0,months:0}}function $t(t,e){return function(n,i){var a,r;return null===i||isNaN(+i)||(S(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),r=n,n=i,i=r),n="string"==typeof n?+n:n,a=Xt(n,i),te(this,a,t),this}}function te(t,e,i,a){var r=e._milliseconds,o=Et(e._days),s=Et(e._months);t.isValid()&&(a=null==a||a,r&&t._d.setTime(t._d.valueOf()+r*i),o&&W(t,"Date",L(t,"Date")+o*i),s&&Q(t,L(t,"Month")+s*i),a&&n.updateOffset(t,o||s))}function ee(t,e){var n,i=12*(e.year()-t.year())+(e.month()-t.month()),a=t.clone().add(i,"months");return n=e-a<0?(e-a)/(a-t.clone().add(i-1,"months")):(e-a)/(t.clone().add(i+1,"months")-a),-(i+n)||0}function ne(t){var e;return void 0===t?this._locale._abbr:(null!=(e=_t(t))&&(this._locale=e),this)}function ie(){return this._locale}function ae(t,e){N(0,[t,t.length],0,e)}function re(t,e,n,i,a){var r;return null==t?st(this,i,a).year:(r=lt(t,i,a),e>r&&(e=r),oe.call(this,t,e,n,i,a))}function oe(t,e,n,i,a){var r=ot(t,e,n,i,a),o=at(r.year,0,r.dayOfYear);return this.year(o.getUTCFullYear()),this.month(o.getUTCMonth()),this.date(o.getUTCDate()),this}function se(t){return t}function le(t,e,n,i){var a=_t(),r=h().set(i,e);return a[n](r,t)}function ue(t,e,n){if(s(t)&&(e=t,t=void 0),t=t||"",null!=e)return le(t,e,n,"month");var i,a=[];for(i=0;i<12;i++)a[i]=le(t,i,n,"month");return a}function de(t,e,n,i){"boolean"==typeof t?(s(e)&&(n=e,e=void 0),e=e||""):(n=e=t,t=!1,s(e)&&(n=e,e=void 0),e=e||"");var a=_t(),r=t?a._week.dow:0;if(null!=n)return le(e,(n+r)%7,i,"day");var o,l=[];for(o=0;o<7;o++)l[o]=le(e,(o+r)%7,i,"day");return l}function ce(t,e,n,i){var a=Xt(e,n);return t._milliseconds+=i*a._milliseconds,t._days+=i*a._days,t._months+=i*a._months,t._bubble()}function he(t){return t<0?Math.floor(t):Math.ceil(t)}function fe(t){return 4800*t/146097}function ge(t){return 146097*t/4800}function me(t){return function(){return this.as(t)}}function pe(t){return function(){return this.isValid()?this._data[t]:NaN}}function ve(t,e,n,i,a){return a.relativeTime(e||1,!!n,t,i)}function ye(t,e,n){var i=Xt(t).abs(),a=bi(i.as("s")),r=bi(i.as("m")),o=bi(i.as("h")),s=bi(i.as("d")),l=bi(i.as("M")),u=bi(i.as("y")),d=a<=xi.ss&&["s",a]||a<xi.s&&["ss",a]||r<=1&&["m"]||r<xi.m&&["mm",r]||o<=1&&["h"]||o<xi.h&&["hh",o]||s<=1&&["d"]||s<xi.d&&["dd",s]||l<=1&&["M"]||l<xi.M&&["MM",l]||u<=1&&["y"]||["yy",u];return d[2]=e,d[3]=+t>0,d[4]=n,ve.apply(null,d)}function be(){if(!this.isValid())return this.localeData().invalidDate();var t,e,n,i=_i(this._milliseconds)/1e3,a=_i(this._days),r=_i(this._months);e=x((t=x(i/60))/60),i%=60,t%=60;var o=n=x(r/12),s=r%=12,l=a,u=e,d=t,c=i,h=this.asSeconds();return h?(h<0?"-":"")+"P"+(o?o+"Y":"")+(s?s+"M":"")+(l?l+"D":"")+(u||d||c?"T":"")+(u?u+"H":"")+(d?d+"M":"")+(c?c+"S":""):"P0D"}var xe,_e,ke=_e=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),n=e.length>>>0,i=0;i<n;i++)if(i in e&&t.call(this,e[i],i,e))return!0;return!1},we=n.momentProperties=[],Me=!1,Se={};n.suppressDeprecationWarnings=!1,n.deprecationHandler=null;var De,Ce,Pe=De=Object.keys?Object.keys:function(t){var e,n=[];for(e in t)d(t,e)&&n.push(e);return n},Te={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Ie={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Ae=/\d{1,2}/,Oe={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Fe={},Re={},Le=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,We=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Ye={},Ne={},ze=/\d/,Be=/\d\d/,Ve=/\d{3}/,He=/\d{4}/,Ee=/[+-]?\d{6}/,je=/\d\d?/,Ue=/\d\d\d\d?/,qe=/\d\d\d\d\d\d?/,Ge=/\d{1,3}/,Ze=/\d{1,4}/,Xe=/[+-]?\d{1,6}/,Je=/\d+/,Ke=/[+-]?\d+/,Qe=/Z|[+-]\d\d:?\d\d/gi,$e=/Z|[+-]\d\d(?::?\d\d)?/gi,tn=/[+-]?\d+(\.\d{1,3})?/,en=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,nn={},an={},rn=0,on=1,sn=2,ln=3,un=4,dn=5,cn=6,hn=7,fn=8,gn=Ce=Array.prototype.indexOf?Array.prototype.indexOf:function(t){var e;for(e=0;e<this.length;++e)if(this[e]===t)return e;return-1};N("M",["MM",2],"Mo",function(){return this.month()+1}),N("MMM",0,0,function(t){return this.localeData().monthsShort(this,t)}),N("MMMM",0,0,function(t){return this.localeData().months(this,t)}),T("month","M"),O("month",8),E("M",je),E("MM",je,Be),E("MMM",function(t,e){return e.monthsShortRegex(t)}),E("MMMM",function(t,e){return e.monthsRegex(t)}),G(["M","MM"],function(t,e){e[on]=_(t)-1}),G(["MMM","MMMM"],function(t,e,n,i){var a=n._locale.monthsParse(t,i,n._strict);null!=a?e[on]=a:g(n).invalidMonth=t});var mn=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,pn="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),vn="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),yn=en,bn=en;N("Y",0,0,function(){var t=this.year();return t<=9999?""+t:"+"+t}),N(0,["YY",2],0,function(){return this.year()%100}),N(0,["YYYY",4],0,"year"),N(0,["YYYYY",5],0,"year"),N(0,["YYYYYY",6,!0],0,"year"),T("year","y"),O("year",1),E("Y",Ke),E("YY",je,Be),E("YYYY",Ze,He),E("YYYYY",Xe,Ee),E("YYYYYY",Xe,Ee),G(["YYYYY","YYYYYY"],rn),G("YYYY",function(t,e){e[rn]=2===t.length?n.parseTwoDigitYear(t):_(t)}),G("YY",function(t,e){e[rn]=n.parseTwoDigitYear(t)}),G("Y",function(t,e){e[rn]=parseInt(t,10)}),n.parseTwoDigitYear=function(t){return _(t)+(_(t)>68?1900:2e3)};var xn=R("FullYear",!0);N("w",["ww",2],"wo","week"),N("W",["WW",2],"Wo","isoWeek"),T("week","w"),T("isoWeek","W"),O("week",5),O("isoWeek",5),E("w",je),E("ww",je,Be),E("W",je),E("WW",je,Be),Z(["w","ww","W","WW"],function(t,e,n,i){e[i.substr(0,1)]=_(t)});var _n={dow:0,doy:6};N("d",0,"do","day"),N("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),N("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),N("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),N("e",0,0,"weekday"),N("E",0,0,"isoWeekday"),T("day","d"),T("weekday","e"),T("isoWeekday","E"),O("day",11),O("weekday",11),O("isoWeekday",11),E("d",je),E("e",je),E("E",je),E("dd",function(t,e){return e.weekdaysMinRegex(t)}),E("ddd",function(t,e){return e.weekdaysShortRegex(t)}),E("dddd",function(t,e){return e.weekdaysRegex(t)}),Z(["dd","ddd","dddd"],function(t,e,n,i){var a=n._locale.weekdaysParse(t,i,n._strict);null!=a?e.d=a:g(n).invalidWeekday=t}),Z(["d","e","E"],function(t,e,n,i){e[i]=_(t)});var kn="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),wn="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Mn="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Sn=en,Dn=en,Cn=en;N("H",["HH",2],0,"hour"),N("h",["hh",2],0,ft),N("k",["kk",2],0,function(){return this.hours()||24}),N("hmm",0,0,function(){return""+ft.apply(this)+Y(this.minutes(),2)}),N("hmmss",0,0,function(){return""+ft.apply(this)+Y(this.minutes(),2)+Y(this.seconds(),2)}),N("Hmm",0,0,function(){return""+this.hours()+Y(this.minutes(),2)}),N("Hmmss",0,0,function(){return""+this.hours()+Y(this.minutes(),2)+Y(this.seconds(),2)}),gt("a",!0),gt("A",!1),T("hour","h"),O("hour",13),E("a",mt),E("A",mt),E("H",je),E("h",je),E("k",je),E("HH",je,Be),E("hh",je,Be),E("kk",je,Be),E("hmm",Ue),E("hmmss",qe),E("Hmm",Ue),E("Hmmss",qe),G(["H","HH"],ln),G(["k","kk"],function(t,e,n){var i=_(t);e[ln]=24===i?0:i}),G(["a","A"],function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t}),G(["h","hh"],function(t,e,n){e[ln]=_(t),g(n).bigHour=!0}),G("hmm",function(t,e,n){var i=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i)),g(n).bigHour=!0}),G("hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i,2)),e[dn]=_(t.substr(a)),g(n).bigHour=!0}),G("Hmm",function(t,e,n){var i=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i))}),G("Hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i,2)),e[dn]=_(t.substr(a))});var Pn,Tn=/[ap]\.?m?\.?/i,In=R("Hours",!0),An={calendar:Te,longDateFormat:Ie,invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:Ae,relativeTime:Oe,months:pn,monthsShort:vn,week:_n,weekdays:kn,weekdaysMin:Mn,weekdaysShort:wn,meridiemParse:Tn},On={},Fn={},Rn=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Ln=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Wn=/Z|[+-]\d\d(?::?\d\d)?/,Yn=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Nn=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],zn=/^\/?Date\((\-?\d+)/i,Bn=/^((?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d?\d\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(?:\d\d)?\d\d\s)(\d\d:\d\d)(\:\d\d)?(\s(?:UT|GMT|[ECMP][SD]T|[A-IK-Za-ik-z]|[+-]\d{4}))$/;n.createFromInputFallback=M("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(t){t._d=new Date(t._i+(t._useUTC?" UTC":""))}),n.ISO_8601=function(){},n.RFC_2822=function(){};var Vn=M("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=Nt.apply(null,arguments);return this.isValid()&&t.isValid()?t<this?this:t:p()}),Hn=M("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=Nt.apply(null,arguments);return this.isValid()&&t.isValid()?t>this?this:t:p()}),En=["year","quarter","month","week","day","hour","minute","second","millisecond"];jt("Z",":"),jt("ZZ",""),E("Z",$e),E("ZZ",$e),G(["Z","ZZ"],function(t,e,n){n._useUTC=!0,n._tzm=Ut($e,t)});var jn=/([\+\-]|\d\d)/gi;n.updateOffset=function(){};var Un=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,qn=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;Xt.fn=Vt.prototype,Xt.invalid=function(){return Xt(NaN)};var Gn=$t(1,"add"),Zn=$t(-1,"subtract");n.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",n.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xn=M("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return void 0===t?this.localeData():this.locale(t)});N(0,["gg",2],0,function(){return this.weekYear()%100}),N(0,["GG",2],0,function(){return this.isoWeekYear()%100}),ae("gggg","weekYear"),ae("ggggg","weekYear"),ae("GGGG","isoWeekYear"),ae("GGGGG","isoWeekYear"),T("weekYear","gg"),T("isoWeekYear","GG"),O("weekYear",1),O("isoWeekYear",1),E("G",Ke),E("g",Ke),E("GG",je,Be),E("gg",je,Be),E("GGGG",Ze,He),E("gggg",Ze,He),E("GGGGG",Xe,Ee),E("ggggg",Xe,Ee),Z(["gggg","ggggg","GGGG","GGGGG"],function(t,e,n,i){e[i.substr(0,2)]=_(t)}),Z(["gg","GG"],function(t,e,i,a){e[a]=n.parseTwoDigitYear(t)}),N("Q",0,"Qo","quarter"),T("quarter","Q"),O("quarter",7),E("Q",ze),G("Q",function(t,e){e[on]=3*(_(t)-1)}),N("D",["DD",2],"Do","date"),T("date","D"),O("date",9),E("D",je),E("DD",je,Be),E("Do",function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient}),G(["D","DD"],sn),G("Do",function(t,e){e[sn]=_(t.match(je)[0],10)});var Jn=R("Date",!0);N("DDD",["DDDD",3],"DDDo","dayOfYear"),T("dayOfYear","DDD"),O("dayOfYear",4),E("DDD",Ge),E("DDDD",Ve),G(["DDD","DDDD"],function(t,e,n){n._dayOfYear=_(t)}),N("m",["mm",2],0,"minute"),T("minute","m"),O("minute",14),E("m",je),E("mm",je,Be),G(["m","mm"],un);var Kn=R("Minutes",!1);N("s",["ss",2],0,"second"),T("second","s"),O("second",15),E("s",je),E("ss",je,Be),G(["s","ss"],dn);var Qn=R("Seconds",!1);N("S",0,0,function(){return~~(this.millisecond()/100)}),N(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),N(0,["SSS",3],0,"millisecond"),N(0,["SSSS",4],0,function(){return 10*this.millisecond()}),N(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),N(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),N(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),N(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),N(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),T("millisecond","ms"),O("millisecond",16),E("S",Ge,ze),E("SS",Ge,Be),E("SSS",Ge,Ve);var $n;for($n="SSSS";$n.length<=9;$n+="S")E($n,Je);for($n="S";$n.length<=9;$n+="S")G($n,function(t,e){e[cn]=_(1e3*("0."+t))});var ti=R("Milliseconds",!1);N("z",0,0,"zoneAbbr"),N("zz",0,0,"zoneName");var ei=y.prototype;ei.add=Gn,ei.calendar=function(t,e){var i=t||Nt(),a=qt(i,this).startOf("day"),r=n.calendarFormat(this,a)||"sameElse",o=e&&(D(e[r])?e[r].call(this,i):e[r]);return this.format(o||this.localeData().calendar(r,this,Nt(i)))},ei.clone=function(){return new y(this)},ei.diff=function(t,e,n){var i,a,r,o;return this.isValid()&&(i=qt(t,this)).isValid()?(a=6e4*(i.utcOffset()-this.utcOffset()),"year"===(e=I(e))||"month"===e||"quarter"===e?(o=ee(this,i),"quarter"===e?o/=3:"year"===e&&(o/=12)):(r=this-i,o="second"===e?r/1e3:"minute"===e?r/6e4:"hour"===e?r/36e5:"day"===e?(r-a)/864e5:"week"===e?(r-a)/6048e5:r),n?o:x(o)):NaN},ei.endOf=function(t){return void 0===(t=I(t))||"millisecond"===t?this:("date"===t&&(t="day"),this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms"))},ei.format=function(t){t||(t=this.isUtc()?n.defaultFormatUtc:n.defaultFormat);var e=V(this,t);return this.localeData().postformat(e)},ei.from=function(t,e){return this.isValid()&&(b(t)&&t.isValid()||Nt(t).isValid())?Xt({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},ei.fromNow=function(t){return this.from(Nt(),t)},ei.to=function(t,e){return this.isValid()&&(b(t)&&t.isValid()||Nt(t).isValid())?Xt({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},ei.toNow=function(t){return this.to(Nt(),t)},ei.get=function(t){return t=I(t),D(this[t])?this[t]():this},ei.invalidAt=function(){return g(this).overflow},ei.isAfter=function(t,e){var n=b(t)?t:Nt(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=I(o(e)?"millisecond":e))?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(e).valueOf())},ei.isBefore=function(t,e){var n=b(t)?t:Nt(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=I(o(e)?"millisecond":e))?this.valueOf()<n.valueOf():this.clone().endOf(e).valueOf()<n.valueOf())},ei.isBetween=function(t,e,n,i){return("("===(i=i||"()")[0]?this.isAfter(t,n):!this.isBefore(t,n))&&(")"===i[1]?this.isBefore(e,n):!this.isAfter(e,n))},ei.isSame=function(t,e){var n,i=b(t)?t:Nt(t);return!(!this.isValid()||!i.isValid())&&("millisecond"===(e=I(e||"millisecond"))?this.valueOf()===i.valueOf():(n=i.valueOf(),this.clone().startOf(e).valueOf()<=n&&n<=this.clone().endOf(e).valueOf()))},ei.isSameOrAfter=function(t,e){return this.isSame(t,e)||this.isAfter(t,e)},ei.isSameOrBefore=function(t,e){return this.isSame(t,e)||this.isBefore(t,e)},ei.isValid=function(){return m(this)},ei.lang=Xn,ei.locale=ne,ei.localeData=ie,ei.max=Hn,ei.min=Vn,ei.parsingFlags=function(){return c({},g(this))},ei.set=function(t,e){if("object"==typeof t)for(var n=F(t=A(t)),i=0;i<n.length;i++)this[n[i].unit](t[n[i].unit]);else if(t=I(t),D(this[t]))return this[t](e);return this},ei.startOf=function(t){switch(t=I(t)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===t&&this.weekday(0),"isoWeek"===t&&this.isoWeekday(1),"quarter"===t&&this.month(3*Math.floor(this.month()/3)),this},ei.subtract=Zn,ei.toArray=function(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]},ei.toObject=function(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}},ei.toDate=function(){return new Date(this.valueOf())},ei.toISOString=function(){if(!this.isValid())return null;var t=this.clone().utc();return t.year()<0||t.year()>9999?V(t,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):D(Date.prototype.toISOString)?this.toDate().toISOString():V(t,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},ei.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t="moment",e="";this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",e="Z");var n="["+t+'("]',i=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",a=e+'[")]';return this.format(n+i+"-MM-DD[T]HH:mm:ss.SSS"+a)},ei.toJSON=function(){return this.isValid()?this.toISOString():null},ei.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},ei.unix=function(){return Math.floor(this.valueOf()/1e3)},ei.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},ei.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},ei.year=xn,ei.isLeapYear=function(){return nt(this.year())},ei.weekYear=function(t){return re.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},ei.isoWeekYear=function(t){return re.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)},ei.quarter=ei.quarters=function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},ei.month=$,ei.daysInMonth=function(){return J(this.year(),this.month())},ei.week=ei.weeks=function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},ei.isoWeek=ei.isoWeeks=function(t){var e=st(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},ei.weeksInYear=function(){var t=this.localeData()._week;return lt(this.year(),t.dow,t.doy)},ei.isoWeeksInYear=function(){return lt(this.year(),1,4)},ei.date=Jn,ei.day=ei.days=function(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=ut(t,this.localeData()),this.add(t-e,"d")):e},ei.weekday=function(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},ei.isoWeekday=function(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=dt(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7},ei.dayOfYear=function(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},ei.hour=ei.hours=In,ei.minute=ei.minutes=Kn,ei.second=ei.seconds=Qn,ei.millisecond=ei.milliseconds=ti,ei.utcOffset=function(t,e,i){var a,r=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null!=t){if("string"==typeof t){if(null===(t=Ut($e,t)))return this}else Math.abs(t)<16&&!i&&(t*=60);return!this._isUTC&&e&&(a=Gt(this)),this._offset=t,this._isUTC=!0,null!=a&&this.add(a,"m"),r!==t&&(!e||this._changeInProgress?te(this,Xt(t-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,n.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Gt(this)},ei.utc=function(t){return this.utcOffset(0,t)},ei.local=function(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Gt(this),"m")),this},ei.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var t=Ut(Qe,this._i);null!=t?this.utcOffset(t):this.utcOffset(0,!0)}return this},ei.hasAlignedHourOffset=function(t){return!!this.isValid()&&(t=t?Nt(t).utcOffset():0,(this.utcOffset()-t)%60==0)},ei.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},ei.isLocal=function(){return!!this.isValid()&&!this._isUTC},ei.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},ei.isUtc=Zt,ei.isUTC=Zt,ei.zoneAbbr=function(){return this._isUTC?"UTC":""},ei.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},ei.dates=M("dates accessor is deprecated. Use date instead.",Jn),ei.months=M("months accessor is deprecated. Use month instead",$),ei.years=M("years accessor is deprecated. Use year instead",xn),ei.zone=M("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}),ei.isDSTShifted=M("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!o(this._isDSTShifted))return this._isDSTShifted;var t={};if(v(t,this),(t=Lt(t))._a){var e=t._isUTC?h(t._a):Nt(t._a);this._isDSTShifted=this.isValid()&&k(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var ni=P.prototype;ni.calendar=function(t,e,n){var i=this._calendar[t]||this._calendar.sameElse;return D(i)?i.call(e,n):i},ni.longDateFormat=function(t){var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])},ni.invalidDate=function(){return this._invalidDate},ni.ordinal=function(t){return this._ordinal.replace("%d",t)},ni.preparse=se,ni.postformat=se,ni.relativeTime=function(t,e,n,i){var a=this._relativeTime[n];return D(a)?a(t,e,n,i):a.replace(/%d/i,t)},ni.pastFuture=function(t,e){var n=this._relativeTime[t>0?"future":"past"];return D(n)?n(e):n.replace(/%s/i,e)},ni.set=function(t){var e,n;for(n in t)D(e=t[n])?this[n]=e:this["_"+n]=e;this._config=t,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},ni.months=function(t,e){return t?i(this._months)?this._months[t.month()]:this._months[(this._months.isFormat||mn).test(e)?"format":"standalone"][t.month()]:i(this._months)?this._months:this._months.standalone},ni.monthsShort=function(t,e){return t?i(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[mn.test(e)?"format":"standalone"][t.month()]:i(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},ni.monthsParse=function(t,e,n){var i,a,r;if(this._monthsParseExact)return K.call(this,t,e,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),i=0;i<12;i++){if(a=h([2e3,i]),n&&!this._longMonthsParse[i]&&(this._longMonthsParse[i]=new RegExp("^"+this.months(a,"").replace(".","")+"$","i"),this._shortMonthsParse[i]=new RegExp("^"+this.monthsShort(a,"").replace(".","")+"$","i")),n||this._monthsParse[i]||(r="^"+this.months(a,"")+"|^"+this.monthsShort(a,""),this._monthsParse[i]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[i].test(t))return i;if(n&&"MMM"===e&&this._shortMonthsParse[i].test(t))return i;if(!n&&this._monthsParse[i].test(t))return i}},ni.monthsRegex=function(t){return this._monthsParseExact?(d(this,"_monthsRegex")||tt.call(this),t?this._monthsStrictRegex:this._monthsRegex):(d(this,"_monthsRegex")||(this._monthsRegex=bn),this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex)},ni.monthsShortRegex=function(t){return this._monthsParseExact?(d(this,"_monthsRegex")||tt.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):(d(this,"_monthsShortRegex")||(this._monthsShortRegex=yn),this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex)},ni.week=function(t){return st(t,this._week.dow,this._week.doy).week},ni.firstDayOfYear=function(){return this._week.doy},ni.firstDayOfWeek=function(){return this._week.dow},ni.weekdays=function(t,e){return t?i(this._weekdays)?this._weekdays[t.day()]:this._weekdays[this._weekdays.isFormat.test(e)?"format":"standalone"][t.day()]:i(this._weekdays)?this._weekdays:this._weekdays.standalone},ni.weekdaysMin=function(t){return t?this._weekdaysMin[t.day()]:this._weekdaysMin},ni.weekdaysShort=function(t){return t?this._weekdaysShort[t.day()]:this._weekdaysShort},ni.weekdaysParse=function(t,e,n){var i,a,r;if(this._weekdaysParseExact)return ct.call(this,t,e,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),i=0;i<7;i++){if(a=h([2e3,1]).day(i),n&&!this._fullWeekdaysParse[i]&&(this._fullWeekdaysParse[i]=new RegExp("^"+this.weekdays(a,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[i]=new RegExp("^"+this.weekdaysShort(a,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[i]=new RegExp("^"+this.weekdaysMin(a,"").replace(".",".?")+"$","i")),this._weekdaysParse[i]||(r="^"+this.weekdays(a,"")+"|^"+this.weekdaysShort(a,"")+"|^"+this.weekdaysMin(a,""),this._weekdaysParse[i]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===e&&this._fullWeekdaysParse[i].test(t))return i;if(n&&"ddd"===e&&this._shortWeekdaysParse[i].test(t))return i;if(n&&"dd"===e&&this._minWeekdaysParse[i].test(t))return i;if(!n&&this._weekdaysParse[i].test(t))return i}},ni.weekdaysRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(d(this,"_weekdaysRegex")||(this._weekdaysRegex=Sn),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)},ni.weekdaysShortRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(d(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Dn),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},ni.weekdaysMinRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(d(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Cn),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},ni.isPM=function(t){return"p"===(t+"").toLowerCase().charAt(0)},ni.meridiem=function(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"},bt("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===_(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),n.lang=M("moment.lang is deprecated. Use moment.locale instead.",bt),n.langData=M("moment.langData is deprecated. Use moment.localeData instead.",_t);var ii=Math.abs,ai=me("ms"),ri=me("s"),oi=me("m"),si=me("h"),li=me("d"),ui=me("w"),di=me("M"),ci=me("y"),hi=pe("milliseconds"),fi=pe("seconds"),gi=pe("minutes"),mi=pe("hours"),pi=pe("days"),vi=pe("months"),yi=pe("years"),bi=Math.round,xi={ss:44,s:45,m:45,h:22,d:26,M:11},_i=Math.abs,ki=Vt.prototype;return ki.isValid=function(){return this._isValid},ki.abs=function(){var t=this._data;return this._milliseconds=ii(this._milliseconds),this._days=ii(this._days),this._months=ii(this._months),t.milliseconds=ii(t.milliseconds),t.seconds=ii(t.seconds),t.minutes=ii(t.minutes),t.hours=ii(t.hours),t.months=ii(t.months),t.years=ii(t.years),this},ki.add=function(t,e){return ce(this,t,e,1)},ki.subtract=function(t,e){return ce(this,t,e,-1)},ki.as=function(t){if(!this.isValid())return NaN;var e,n,i=this._milliseconds;if("month"===(t=I(t))||"year"===t)return e=this._days+i/864e5,n=this._months+fe(e),"month"===t?n:n/12;switch(e=this._days+Math.round(ge(this._months)),t){case"week":return e/7+i/6048e5;case"day":return e+i/864e5;case"hour":return 24*e+i/36e5;case"minute":return 1440*e+i/6e4;case"second":return 86400*e+i/1e3;case"millisecond":return Math.floor(864e5*e)+i;default:throw new Error("Unknown unit "+t)}},ki.asMilliseconds=ai,ki.asSeconds=ri,ki.asMinutes=oi,ki.asHours=si,ki.asDays=li,ki.asWeeks=ui,ki.asMonths=di,ki.asYears=ci,ki.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*_(this._months/12):NaN},ki._bubble=function(){var t,e,n,i,a,r=this._milliseconds,o=this._days,s=this._months,l=this._data;return r>=0&&o>=0&&s>=0||r<=0&&o<=0&&s<=0||(r+=864e5*he(ge(s)+o),o=0,s=0),l.milliseconds=r%1e3,t=x(r/1e3),l.seconds=t%60,e=x(t/60),l.minutes=e%60,n=x(e/60),l.hours=n%24,o+=x(n/24),a=x(fe(o)),s+=a,o-=he(ge(a)),i=x(s/12),s%=12,l.days=o,l.months=s,l.years=i,this},ki.get=function(t){return t=I(t),this.isValid()?this[t+"s"]():NaN},ki.milliseconds=hi,ki.seconds=fi,ki.minutes=gi,ki.hours=mi,ki.days=pi,ki.weeks=function(){return x(this.days()/7)},ki.months=vi,ki.years=yi,ki.humanize=function(t){if(!this.isValid())return this.localeData().invalidDate();var e=this.localeData(),n=ye(this,!t,e);return t&&(n=e.pastFuture(+this,n)),e.postformat(n)},ki.toISOString=be,ki.toString=be,ki.toJSON=be,ki.locale=ne,ki.localeData=ie,ki.toIsoString=M("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",be),ki.lang=Xn,N("X",0,0,"unix"),N("x",0,0,"valueOf"),E("x",Ke),E("X",tn),G("X",function(t,e,n){n._d=new Date(1e3*parseFloat(t,10))}),G("x",function(t,e,n){n._d=new Date(_(t))}),n.version="2.18.1",function(t){xe=t}(Nt),n.fn=ei,n.min=function(){return zt("isBefore",[].slice.call(arguments,0))},n.max=function(){return zt("isAfter",[].slice.call(arguments,0))},n.now=function(){return Date.now?Date.now():+new Date},n.utc=h,n.unix=function(t){return Nt(1e3*t)},n.months=function(t,e){return ue(t,e,"months")},n.isDate=l,n.locale=bt,n.invalid=p,n.duration=Xt,n.isMoment=b,n.weekdays=function(t,e,n){return de(t,e,n,"weekdays")},n.parseZone=function(){return Nt.apply(null,arguments).parseZone()},n.localeData=_t,n.isDuration=Ht,n.monthsShort=function(t,e){return ue(t,e,"monthsShort")},n.weekdaysMin=function(t,e,n){return de(t,e,n,"weekdaysMin")},n.defineLocale=xt,n.updateLocale=function(t,e){if(null!=e){var n,i=An;null!=On[t]&&(i=On[t]._config),(n=new P(e=C(i,e))).parentLocale=On[t],On[t]=n,bt(t)}else null!=On[t]&&(null!=On[t].parentLocale?On[t]=On[t].parentLocale:null!=On[t]&&delete On[t]);return On[t]},n.locales=function(){return Pe(On)},n.weekdaysShort=function(t,e,n){return de(t,e,n,"weekdaysShort")},n.normalizeUnits=I,n.relativeTimeRounding=function(t){return void 0===t?bi:"function"==typeof t&&(bi=t,!0)},n.relativeTimeThreshold=function(t,e){return void 0!==xi[t]&&(void 0===e?xi[t]:(xi[t]=e,"s"===t&&(xi.ss=e-1),!0))},n.calendarFormat=function(t,e){var n=t.diff(e,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},n.prototype=ei,n})},{}],7:[function(t,e,n){var i=t(29)();i.helpers=t(45),t(27)(i),i.defaults=t(25),i.Element=t(26),i.elements=t(40),i.Interaction=t(28),i.platform=t(48),t(31)(i),t(22)(i),t(23)(i),t(24)(i),t(30)(i),t(33)(i),t(32)(i),t(35)(i),t(54)(i),t(52)(i),t(53)(i),t(55)(i),t(56)(i),t(57)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(21)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i);var a=[];a.push(t(49)(i),t(50)(i),t(51)(i)),i.plugins.register(a),i.platform.initialize(),e.exports=i,"undefined"!=typeof window&&(window.Chart=i),i.canvasHelpers=i.helpers.canvas},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,35:35,40:40,45:45,48:48,49:49,50:50,51:51,52:52,53:53,54:54,55:55,56:56,57:57,8:8,9:9}],8:[function(t,e,n){"use strict";e.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},{}],9:[function(t,e,n){"use strict";e.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},{}],10:[function(t,e,n){"use strict";e.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},{}],12:[function(t,e,n){"use strict";e.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},{}],13:[function(t,e,n){"use strict";e.exports=function(t){t.Radar=function(e,n){return n.type="radar",new t(e,n)}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t){t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},{}],15:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),i._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(n=e.labels[t[0].index])),n},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": "+t.xLabel}},mode:"index",axis:"y"}}),e.exports=function(t){t.controllers.bar=t.DatasetController.extend({dataElementType:a.Rectangle,initialize:function(){var e,n=this;t.DatasetController.prototype.initialize.apply(n,arguments),(e=n.getMeta()).stack=n.getDataset().stack,e.bar=!0},update:function(t){var e,n,i=this,a=i.getMeta().data;for(i._ruler=i.getRuler(),e=0,n=a.length;e<n;++e)i.updateElement(a[e],e,t)},updateElement:function(t,e,n){var i=this,a=i.chart,o=i.getMeta(),s=i.getDataset(),l=t.custom||{},u=a.options.elements.rectangle;t._xScale=i.getScaleForId(o.xAxisID),t._yScale=i.getScaleForId(o.yAxisID),t._datasetIndex=i.index,t._index=e,t._model={datasetLabel:s.label,label:a.data.labels[e],borderSkipped:l.borderSkipped?l.borderSkipped:u.borderSkipped,backgroundColor:l.backgroundColor?l.backgroundColor:r.valueAtIndexOrDefault(s.backgroundColor,e,u.backgroundColor),borderColor:l.borderColor?l.borderColor:r.valueAtIndexOrDefault(s.borderColor,e,u.borderColor),borderWidth:l.borderWidth?l.borderWidth:r.valueAtIndexOrDefault(s.borderWidth,e,u.borderWidth)},i.updateElementGeometry(t,e,n),t.pivot()},updateElementGeometry:function(t,e,n){var i=this,a=t._model,r=i.getValueScale(),o=r.getBasePixel(),s=r.isHorizontal(),l=i._ruler||i.getRuler(),u=i.calculateBarValuePixels(i.index,e),d=i.calculateBarIndexPixels(i.index,e,l);a.horizontal=s,a.base=n?o:u.base,a.x=s?n?o:u.head:d.center,a.y=s?d.center:n?o:u.head,a.height=s?d.size:void 0,a.width=s?void 0:d.size},getValueScaleId:function(){return this.getMeta().yAxisID},getIndexScaleId:function(){return this.getMeta().xAxisID},getValueScale:function(){return this.getScaleForId(this.getValueScaleId())},getIndexScale:function(){return this.getScaleForId(this.getIndexScaleId())},getStackCount:function(t){var e,n,i=this,a=i.chart,r=i.getIndexScale().options.stacked,o=void 0===t?a.data.datasets.length:t+1,s=[];for(e=0;e<o;++e)(n=a.getDatasetMeta(e)).bar&&a.isDatasetVisible(e)&&(!1===r||!0===r&&-1===s.indexOf(n.stack)||void 0===r&&(void 0===n.stack||-1===s.indexOf(n.stack)))&&s.push(n.stack);return s.length},getStackIndex:function(t){return this.getStackCount(t)-1},getRuler:function(){var t,e,n=this,i=n.getIndexScale(),a=n.getStackCount(),r=n.index,o=[],s=i.isHorizontal(),l=s?i.left:i.top,u=l+(s?i.width:i.height);for(t=0,e=n.getMeta().data.length;t<e;++t)o.push(i.getPixelForValue(null,t,r));return{pixels:o,start:l,end:u,stackCount:a,scale:i}},calculateBarValuePixels:function(t,e){var n,i,a,r,o,s,l=this,u=l.chart,d=l.getMeta(),c=l.getValueScale(),h=u.data.datasets,f=c.getRightValue(h[t].data[e]),g=c.options.stacked,m=d.stack,p=0;if(g||void 0===g&&void 0!==m)for(n=0;n<t;++n)(i=u.getDatasetMeta(n)).bar&&i.stack===m&&i.controller.getValueScaleId()===c.id&&u.isDatasetVisible(n)&&(a=c.getRightValue(h[n].data[e]),(f<0&&a<0||f>=0&&a>0)&&(p+=a));return r=c.getPixelForValue(p),o=c.getPixelForValue(p+f),s=(o-r)/2,{size:s,base:r,head:o,center:o+s/2}},calculateBarIndexPixels:function(t,e,n){var i,a,o,s,l,u,d=this,c=n.scale.options,h=d.getStackIndex(t),f=n.pixels,g=f[e],m=f.length,p=n.start,v=n.end;return 1===m?(i=g>p?g-p:v-g,a=g<v?v-g:g-p):(e>0&&(i=(g-f[e-1])/2,e===m-1&&(a=i)),e<m-1&&(a=(f[e+1]-g)/2,0===e&&(i=a))),o=i*c.categoryPercentage,s=a*c.categoryPercentage,l=(o+s)/n.stackCount,u=l*c.barPercentage,u=Math.min(r.valueOrDefault(c.barThickness,u),r.valueOrDefault(c.maxBarThickness,1/0)),g-=o,g+=l*h,g+=(l-u)/2,{size:u,base:g,head:g+u,center:g+u/2}},draw:function(){var t=this,e=t.chart,n=t.getValueScale(),i=t.getMeta().data,a=t.getDataset(),o=i.length,s=0;for(r.canvas.clipArea(e.ctx,e.chartArea);s<o;++s)isNaN(n.getRightValue(a.data[s]))||i[s].draw();r.canvas.unclipArea(e.ctx)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;a.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:r.valueAtIndexOrDefault(e.hoverBackgroundColor,n,r.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor?i.hoverBorderColor:r.valueAtIndexOrDefault(e.hoverBorderColor,n,r.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:r.valueAtIndexOrDefault(e.hoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model,o=this.chart.options.elements.rectangle;a.backgroundColor=i.backgroundColor?i.backgroundColor:r.valueAtIndexOrDefault(e.backgroundColor,n,o.backgroundColor),a.borderColor=i.borderColor?i.borderColor:r.valueAtIndexOrDefault(e.borderColor,n,o.borderColor),a.borderWidth=i.borderWidth?i.borderWidth:r.valueAtIndexOrDefault(e.borderWidth,n,o.borderWidth)}}),t.controllers.horizontalBar=t.controllers.bar.extend({getValueScaleId:function(){return this.getMeta().xAxisID},getIndexScaleId:function(){return this.getMeta().yAxisID}})}},{25:25,40:40,45:45}],16:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("bubble",{hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.datasets[t.datasetIndex].label||"",i=e.datasets[t.datasetIndex].data[t.index];return n+": ("+t.xLabel+", "+t.yLabel+", "+i.r+")"}}}}),e.exports=function(t){t.controllers.bubble=t.DatasetController.extend({dataElementType:a.Point,update:function(t){var e=this,n=e.getMeta().data;r.each(n,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.getMeta(),r=t.custom||{},o=i.getScaleForId(a.xAxisID),s=i.getScaleForId(a.yAxisID),l=i._resolveElementOptions(t,e),u=i.getDataset().data[e],d=i.index,c=n?o.getPixelForDecimal(.5):o.getPixelForValue("object"==typeof u?u:NaN,e,d),h=n?s.getBasePixel():s.getPixelForValue(u,e,d);t._xScale=o,t._yScale=s,t._options=l,t._datasetIndex=d,t._index=e,t._model={backgroundColor:l.backgroundColor,borderColor:l.borderColor,borderWidth:l.borderWidth,hitRadius:l.hitRadius,pointStyle:l.pointStyle,radius:n?0:l.radius,skip:r.skip||isNaN(c)||isNaN(h),x:c,y:h},t.pivot()},setHoverStyle:function(t){var e=t._model,n=t._options;e.backgroundColor=r.valueOrDefault(n.hoverBackgroundColor,r.getHoverColor(n.backgroundColor)),e.borderColor=r.valueOrDefault(n.hoverBorderColor,r.getHoverColor(n.borderColor)),e.borderWidth=r.valueOrDefault(n.hoverBorderWidth,n.borderWidth),e.radius=n.radius+n.hoverRadius},removeHoverStyle:function(t){var e=t._model,n=t._options;e.backgroundColor=n.backgroundColor,e.borderColor=n.borderColor,e.borderWidth=n.borderWidth,e.radius=n.radius},_resolveElementOptions:function(t,e){var n,i,a,o=this,s=o.chart,l=s.data.datasets[o.index],u=t.custom||{},d=s.options.elements.point,c=r.options.resolve,h=l.data[e],f={},g={chart:s,dataIndex:e,dataset:l,datasetIndex:o.index},m=["backgroundColor","borderColor","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","pointStyle"];for(n=0,i=m.length;n<i;++n)f[a=m[n]]=c([u[a],l[a],d[a]],g,e);return f.radius=c([u.radius,h?h.r:void 0,l.radius,d.radius],g,e),f}})}},{25:25,40:40,45:45}],17:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("doughnut",{animation:{animateRotate:!0,animateScale:!1},hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r<i[0].data.length;++r)e.push('<li><span style="background-color:'+i[0].backgroundColor[r]+'"></span>'),a[r]&&e.push(a[r]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),o=e.datasets[0],s=a.data[i],l=s&&s.custom||{},u=r.valueAtIndexOrDefault,d=t.options.elements.arc;return{text:n,fillStyle:l.backgroundColor?l.backgroundColor:u(o.backgroundColor,i,d.backgroundColor),strokeStyle:l.borderColor?l.borderColor:u(o.borderColor,i,d.borderColor),lineWidth:l.borderWidth?l.borderWidth:u(o.borderWidth,i,d.borderWidth),hidden:isNaN(o.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n<i;++n)(a=o.getDatasetMeta(n)).data[r]&&(a.data[r].hidden=!a.data[r].hidden);o.update()}},cutoutPercentage:50,rotation:-.5*Math.PI,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.labels[t.index],i=": "+e.datasets[t.datasetIndex].data[t.index];return r.isArray(n)?(n=n.slice())[0]+=i:n+=i,n}}}}),i._set("pie",r.clone(i.doughnut)),i._set("pie",{cutoutPercentage:0}),e.exports=function(t){t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:a.Arc,linkScales:r.noop,getRingIndex:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var e=this,n=e.chart,i=n.chartArea,a=n.options,o=a.elements.arc,s=i.right-i.left-o.borderWidth,l=i.bottom-i.top-o.borderWidth,u=Math.min(s,l),d={x:0,y:0},c=e.getMeta(),h=a.cutoutPercentage,f=a.circumference;if(f<2*Math.PI){var g=a.rotation%(2*Math.PI),m=(g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0))+f,p={x:Math.cos(g),y:Math.sin(g)},v={x:Math.cos(m),y:Math.sin(m)},y=g<=0&&m>=0||g<=2*Math.PI&&2*Math.PI<=m,b=g<=.5*Math.PI&&.5*Math.PI<=m||g<=2.5*Math.PI&&2.5*Math.PI<=m,x=g<=-Math.PI&&-Math.PI<=m||g<=Math.PI&&Math.PI<=m,_=g<=.5*-Math.PI&&.5*-Math.PI<=m||g<=1.5*Math.PI&&1.5*Math.PI<=m,k=h/100,w={x:x?-1:Math.min(p.x*(p.x<0?1:k),v.x*(v.x<0?1:k)),y:_?-1:Math.min(p.y*(p.y<0?1:k),v.y*(v.y<0?1:k))},M={x:y?1:Math.max(p.x*(p.x>0?1:k),v.x*(v.x>0?1:k)),y:b?1:Math.max(p.y*(p.y>0?1:k),v.y*(v.y>0?1:k))},S={width:.5*(M.x-w.x),height:.5*(M.y-w.y)};u=Math.min(s/S.width,l/S.height),d={x:-.5*(M.x+w.x),y:-.5*(M.y+w.y)}}n.borderWidth=e.getMaxBorderWidth(c.data),n.outerRadius=Math.max((u-n.borderWidth)/2,0),n.innerRadius=Math.max(h?n.outerRadius/100*h:0,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),n.offsetX=d.x*n.outerRadius,n.offsetY=d.y*n.outerRadius,c.total=e.calculateTotal(),e.outerRadius=n.outerRadius-n.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-n.radiusLength,0),r.each(c.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.chart,o=a.chartArea,s=a.options,l=s.animation,u=(o.left+o.right)/2,d=(o.top+o.bottom)/2,c=s.rotation,h=s.rotation,f=i.getDataset(),g=n&&l.animateRotate?0:t.hidden?0:i.calculateCircumference(f.data[e])*(s.circumference/(2*Math.PI)),m=n&&l.animateScale?0:i.innerRadius,p=n&&l.animateScale?0:i.outerRadius,v=r.valueAtIndexOrDefault;r.extend(t,{_datasetIndex:i.index,_index:e,_model:{x:u+a.offsetX,y:d+a.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:p,innerRadius:m,label:v(f.label,e,a.data.labels[e])}});var y=t._model;this.removeHoverStyle(t),n&&l.animateRotate||(y.startAngle=0===e?s.rotation:i.getMeta().data[e-1]._model.endAngle,y.endAngle=y.startAngle+y.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),i=0;return r.each(n.data,function(n,a){t=e.data[a],isNaN(t)||n.hidden||(i+=Math.abs(t))}),i},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0},getMaxBorderWidth:function(t){for(var e,n,i=0,a=this.index,r=t.length,o=0;o<r;o++)e=t[o]._model?t[o]._model.borderWidth:0,i=(n=t[o]._chart?t[o]._chart.config.data.datasets[a].hoverBorderWidth:0)>(i=e>i?e:i)?n:i;return i}})}},{25:25,40:40,45:45}],18:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),e.exports=function(t){function e(t,e){return r.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,update:function(t){var n,i,a,o=this,s=o.getMeta(),l=s.dataset,u=s.data||[],d=o.chart.options,c=d.elements.line,h=o.getScaleForId(s.yAxisID),f=o.getDataset(),g=e(f,d);for(g&&(a=l.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),l._scale=h,l._datasetIndex=o.index,l._children=u,l._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:a.tension?a.tension:r.valueOrDefault(f.lineTension,c.tension),backgroundColor:a.backgroundColor?a.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:f.borderWidth||c.borderWidth,borderColor:a.borderColor?a.borderColor:f.borderColor||c.borderColor,borderCapStyle:a.borderCapStyle?a.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:a.borderDash?a.borderDash:f.borderDash||c.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:a.fill?a.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:a.steppedLine?a.steppedLine:r.valueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:a.cubicInterpolationMode?a.cubicInterpolationMode:r.valueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},l.pivot()),n=0,i=u.length;n<i;++n)o.updateElement(u[n],n,t);for(g&&0!==l._model.tension&&o.updateBezierControlPoints(),n=0,i=u.length;n<i;++n)u[n].pivot()},getPointBackgroundColor:function(t,e){var n=this.chart.options.elements.point.backgroundColor,i=this.getDataset(),a=t.custom||{};return a.backgroundColor?n=a.backgroundColor:i.pointBackgroundColor?n=r.valueAtIndexOrDefault(i.pointBackgroundColor,e,n):i.backgroundColor&&(n=i.backgroundColor),n},getPointBorderColor:function(t,e){var n=this.chart.options.elements.point.borderColor,i=this.getDataset(),a=t.custom||{};return a.borderColor?n=a.borderColor:i.pointBorderColor?n=r.valueAtIndexOrDefault(i.pointBorderColor,e,n):i.borderColor&&(n=i.borderColor),n},getPointBorderWidth:function(t,e){var n=this.chart.options.elements.point.borderWidth,i=this.getDataset(),a=t.custom||{};return isNaN(a.borderWidth)?!isNaN(i.pointBorderWidth)||r.isArray(i.pointBorderWidth)?n=r.valueAtIndexOrDefault(i.pointBorderWidth,e,n):isNaN(i.borderWidth)||(n=i.borderWidth):n=a.borderWidth,n},updateElement:function(t,e,n){var i,a,o=this,s=o.getMeta(),l=t.custom||{},u=o.getDataset(),d=o.index,c=u.data[e],h=o.getScaleForId(s.yAxisID),f=o.getScaleForId(s.xAxisID),g=o.chart.options.elements.point;void 0!==u.radius&&void 0===u.pointRadius&&(u.pointRadius=u.radius),void 0!==u.hitRadius&&void 0===u.pointHitRadius&&(u.pointHitRadius=u.hitRadius),i=f.getPixelForValue("object"==typeof c?c:NaN,e,d),a=n?h.getBasePixel():o.calculatePointY(c,e,d),t._xScale=f,t._yScale=h,t._datasetIndex=d,t._index=e,t._model={x:i,y:a,skip:l.skip||isNaN(i)||isNaN(a),radius:l.radius||r.valueAtIndexOrDefault(u.pointRadius,e,g.radius),pointStyle:l.pointStyle||r.valueAtIndexOrDefault(u.pointStyle,e,g.pointStyle),backgroundColor:o.getPointBackgroundColor(t,e),borderColor:o.getPointBorderColor(t,e),borderWidth:o.getPointBorderWidth(t,e),tension:s.dataset._model?s.dataset._model.tension:0,steppedLine:!!s.dataset._model&&s.dataset._model.steppedLine,hitRadius:l.hitRadius||r.valueAtIndexOrDefault(u.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,n){var i,a,r,o=this,s=o.chart,l=o.getMeta(),u=o.getScaleForId(l.yAxisID),d=0,c=0;if(u.options.stacked){for(i=0;i<n;i++)if(a=s.data.datasets[i],"line"===(r=s.getDatasetMeta(i)).type&&r.yAxisID===u.id&&s.isDatasetVisible(i)){var h=Number(u.getRightValue(a.data[e]));h<0?c+=h||0:d+=h||0}var f=Number(u.getRightValue(t));return f<0?u.getPixelForValue(c+f):u.getPixelForValue(d+f)}return u.getPixelForValue(t)},updateBezierControlPoints:function(){function t(t,e,n){return Math.max(Math.min(t,n),e)}var e,n,i,a,o=this,s=o.getMeta(),l=o.chart.chartArea,u=s.data||[];if(s.dataset._model.spanGaps&&(u=u.filter(function(t){return!t._model.skip})),"monotone"===s.dataset._model.cubicInterpolationMode)r.splineCurveMonotone(u);else for(e=0,n=u.length;e<n;++e)i=u[e]._model,a=r.splineCurve(r.previousItem(u,e)._model,i,r.nextItem(u,e)._model,s.dataset._model.tension),i.controlPointPreviousX=a.previous.x,i.controlPointPreviousY=a.previous.y,i.controlPointNextX=a.next.x,i.controlPointNextY=a.next.y;if(o.chart.options.elements.line.capBezierPoints)for(e=0,n=u.length;e<n;++e)(i=u[e]._model).controlPointPreviousX=t(i.controlPointPreviousX,l.left,l.right),i.controlPointPreviousY=t(i.controlPointPreviousY,l.top,l.bottom),i.controlPointNextX=t(i.controlPointNextX,l.left,l.right),i.controlPointNextY=t(i.controlPointNextY,l.top,l.bottom)},draw:function(){var t=this,n=t.chart,i=t.getMeta(),a=i.data||[],o=n.chartArea,s=a.length,l=0;for(r.canvas.clipArea(n.ctx,o),e(t.getDataset(),n.options)&&i.dataset.draw(),r.canvas.unclipArea(n.ctx);l<s;++l)a[l].draw(o)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;a.radius=i.hoverRadius||r.valueAtIndexOrDefault(e.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius),a.backgroundColor=i.hoverBackgroundColor||r.valueAtIndexOrDefault(e.pointHoverBackgroundColor,n,r.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor||r.valueAtIndexOrDefault(e.pointHoverBorderColor,n,r.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth||r.valueAtIndexOrDefault(e.pointHoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this,n=e.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},o=t._model;void 0!==n.radius&&void 0===n.pointRadius&&(n.pointRadius=n.radius),o.radius=a.radius||r.valueAtIndexOrDefault(n.pointRadius,i,e.chart.options.elements.point.radius),o.backgroundColor=e.getPointBackgroundColor(t,i),o.borderColor=e.getPointBorderColor(t,i),o.borderWidth=e.getPointBorderWidth(t,i)}})}},{25:25,40:40,45:45}],19:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("polarArea",{scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r<i[0].data.length;++r)e.push('<li><span style="background-color:'+i[0].backgroundColor[r]+'"></span>'),a[r]&&e.push(a[r]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),o=e.datasets[0],s=a.data[i].custom||{},l=r.valueAtIndexOrDefault,u=t.options.elements.arc;return{text:n,fillStyle:s.backgroundColor?s.backgroundColor:l(o.backgroundColor,i,u.backgroundColor),strokeStyle:s.borderColor?s.borderColor:l(o.borderColor,i,u.borderColor),lineWidth:s.borderWidth?s.borderWidth:l(o.borderWidth,i,u.borderWidth),hidden:isNaN(o.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n<i;++n)(a=o.getDatasetMeta(n)).data[r].hidden=!a.data[r].hidden;o.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}}),e.exports=function(t){t.controllers.polarArea=t.DatasetController.extend({dataElementType:a.Arc,linkScales:r.noop,update:function(t){var e=this,n=e.chart,i=n.chartArea,a=e.getMeta(),o=n.options,s=o.elements.arc,l=Math.min(i.right-i.left,i.bottom-i.top);n.outerRadius=Math.max((l-s.borderWidth/2)/2,0),n.innerRadius=Math.max(o.cutoutPercentage?n.outerRadius/100*o.cutoutPercentage:1,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),e.outerRadius=n.outerRadius-n.radiusLength*e.index,e.innerRadius=e.outerRadius-n.radiusLength,a.count=e.countVisibleElements(),r.each(a.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){for(var i=this,a=i.chart,o=i.getDataset(),s=a.options,l=s.animation,u=a.scale,d=a.data.labels,c=i.calculateCircumference(o.data[e]),h=u.xCenter,f=u.yCenter,g=0,m=i.getMeta(),p=0;p<e;++p)isNaN(o.data[p])||m.data[p].hidden||++g;var v=s.startAngle,y=t.hidden?0:u.getDistanceFromCenterForValue(o.data[e]),b=v+c*g,x=b+(t.hidden?0:c),_=l.animateScale?0:u.getDistanceFromCenterForValue(o.data[e]);r.extend(t,{_datasetIndex:i.index,_index:e,_scale:u,_model:{x:h,y:f,innerRadius:0,outerRadius:n?_:y,startAngle:n&&l.animateRotate?v:b,endAngle:n&&l.animateRotate?v:x,label:r.valueAtIndexOrDefault(d,e,d[e])}}),i.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),e=this.getMeta(),n=0;return r.each(e.data,function(e,i){isNaN(t.data[i])||e.hidden||n++}),n},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{25:25,40:40,45:45}],20:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),e.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,linkScales:r.noop,update:function(t){var e=this,n=e.getMeta(),i=n.dataset,a=n.data,o=i.custom||{},s=e.getDataset(),l=e.chart.options.elements.line,u=e.chart.scale;void 0!==s.tension&&void 0===s.lineTension&&(s.lineTension=s.tension),r.extend(n.dataset,{_datasetIndex:e.index,_scale:u,_children:a,_loop:!0,_model:{tension:o.tension?o.tension:r.valueOrDefault(s.lineTension,l.tension),backgroundColor:o.backgroundColor?o.backgroundColor:s.backgroundColor||l.backgroundColor,borderWidth:o.borderWidth?o.borderWidth:s.borderWidth||l.borderWidth,borderColor:o.borderColor?o.borderColor:s.borderColor||l.borderColor,fill:o.fill?o.fill:void 0!==s.fill?s.fill:l.fill,borderCapStyle:o.borderCapStyle?o.borderCapStyle:s.borderCapStyle||l.borderCapStyle,borderDash:o.borderDash?o.borderDash:s.borderDash||l.borderDash,borderDashOffset:o.borderDashOffset?o.borderDashOffset:s.borderDashOffset||l.borderDashOffset,borderJoinStyle:o.borderJoinStyle?o.borderJoinStyle:s.borderJoinStyle||l.borderJoinStyle}}),n.dataset.pivot(),r.each(a,function(n,i){e.updateElement(n,i,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,n){var i=this,a=t.custom||{},o=i.getDataset(),s=i.chart.scale,l=i.chart.options.elements.point,u=s.getPointPositionForValue(e,o.data[e]);void 0!==o.radius&&void 0===o.pointRadius&&(o.pointRadius=o.radius),void 0!==o.hitRadius&&void 0===o.pointHitRadius&&(o.pointHitRadius=o.hitRadius),r.extend(t,{_datasetIndex:i.index,_index:e,_scale:s,_model:{x:n?s.xCenter:u.x,y:n?s.yCenter:u.y,tension:a.tension?a.tension:r.valueOrDefault(o.lineTension,i.chart.options.elements.line.tension),radius:a.radius?a.radius:r.valueAtIndexOrDefault(o.pointRadius,e,l.radius),backgroundColor:a.backgroundColor?a.backgroundColor:r.valueAtIndexOrDefault(o.pointBackgroundColor,e,l.backgroundColor),borderColor:a.borderColor?a.borderColor:r.valueAtIndexOrDefault(o.pointBorderColor,e,l.borderColor),borderWidth:a.borderWidth?a.borderWidth:r.valueAtIndexOrDefault(o.pointBorderWidth,e,l.borderWidth),pointStyle:a.pointStyle?a.pointStyle:r.valueAtIndexOrDefault(o.pointStyle,e,l.pointStyle),hitRadius:a.hitRadius?a.hitRadius:r.valueAtIndexOrDefault(o.pointHitRadius,e,l.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();r.each(e.data,function(n,i){var a=n._model,o=r.splineCurve(r.previousItem(e.data,i,!0)._model,a,r.nextItem(e.data,i,!0)._model,a.tension);a.controlPointPreviousX=Math.max(Math.min(o.previous.x,t.right),t.left),a.controlPointPreviousY=Math.max(Math.min(o.previous.y,t.bottom),t.top),a.controlPointNextX=Math.max(Math.min(o.next.x,t.right),t.left),a.controlPointNextY=Math.max(Math.min(o.next.y,t.bottom),t.top),n.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model;a.radius=n.hoverRadius?n.hoverRadius:r.valueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),a.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:r.valueAtIndexOrDefault(e.pointHoverBackgroundColor,i,r.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor?n.hoverBorderColor:r.valueAtIndexOrDefault(e.pointHoverBorderColor,i,r.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:r.valueAtIndexOrDefault(e.pointHoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model,o=this.chart.options.elements.point;a.radius=n.radius?n.radius:r.valueAtIndexOrDefault(e.pointRadius,i,o.radius),a.backgroundColor=n.backgroundColor?n.backgroundColor:r.valueAtIndexOrDefault(e.pointBackgroundColor,i,o.backgroundColor),a.borderColor=n.borderColor?n.borderColor:r.valueAtIndexOrDefault(e.pointBorderColor,i,o.borderColor),a.borderWidth=n.borderWidth?n.borderWidth:r.valueAtIndexOrDefault(e.pointBorderWidth,i,o.borderWidth)}})}},{25:25,40:40,45:45}],21:[function(t,e,n){"use strict";t(25)._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),e.exports=function(t){t.controllers.scatter=t.controllers.line}},{25:25}],22:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:r.noop,onComplete:r.noop}}),e.exports=function(t){t.Animation=a.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a,r,o=this.animations;for(e.chart=t,i||(t.animating=!0),a=0,r=o.length;a<r;++a)if(o[a].chart===t)return void(o[a]=e);o.push(e),1===o.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var e=r.findIndex(this.animations,function(e){return e.chart===t});-1!==e&&(this.animations.splice(e,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=r.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),n=0;t.dropFrames>1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var i=Date.now();t.dropFrames+=(i-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,n,i=this.animations,a=0;a<i.length;)n=(e=i[a]).chart,e.currentStep=(e.currentStep||0)+t,e.currentStep=Math.min(e.currentStep,e.numSteps),r.callback(e.render,[n,e],n),r.callback(e.onAnimationProgress,[e],n),e.currentStep>=e.numSteps?(r.callback(e.onAnimationComplete,[e],n),n.animating=!1,i.splice(a,1)):++a}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{25:25,26:26,45:45}],23:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(28),o=t(48);e.exports=function(t){function e(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=a.configMerge(i.global,i[t.type],t.options||{}),t}function n(t){var e=t.options;e.scale?t.scale.options=e.scale:e.scales&&e.scales.xAxes.concat(e.scales.yAxes).forEach(function(e){t.scales[e.id].options=e}),t.tooltip._options=e.tooltips}function s(t){return"top"===t||"bottom"===t}var l=t.plugins;t.types={},t.instances={},t.controllers={},a.extend(t.prototype,{construct:function(n,i){var r=this;i=e(i);var s=o.acquireContext(n,i),l=s&&s.canvas,u=l&&l.height,d=l&&l.width;r.id=a.uid(),r.ctx=s,r.canvas=l,r.config=i,r.width=d,r.height=u,r.aspectRatio=u?d/u:null,r.options=i.options,r._bufferedRender=!1,r.chart=r,r.controller=r,t.instances[r.id]=r,Object.defineProperty(r,"data",{get:function(){return r.config.data},set:function(t){r.config.data=t}}),s&&l?(r.initialize(),r.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return l.notify(t,"beforeInit"),a.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildScales(),t.initToolTip(),l.notify(t,"afterInit"),t},clear:function(){return a.canvas.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,r=n.maintainAspectRatio&&e.aspectRatio||null,o=Math.max(0,Math.floor(a.getMaximumWidth(i))),s=Math.max(0,Math.floor(r?o/r:a.getMaximumHeight(i)));if((e.width!==o||e.height!==s)&&(i.width=e.width=o,i.height=e.height=s,i.style.width=o+"px",i.style.height=s+"px",a.retinaScale(e,n.devicePixelRatio),!t)){var u={width:o,height:s};l.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;a.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),a.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildScales:function(){var e=this,n=e.options,i=e.scales={},r=[];n.scales&&(r=r.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&r.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),a.each(r,function(n){var r=n.options,o=a.valueOrDefault(r.type,n.dtype),l=t.scaleService.getScaleConstructor(o);if(l){s(r.position)!==s(n.dposition)&&(r.position=n.dposition);var u=new l({id:r.id,options:r,ctx:e.ctx,chart:e});i[u.id]=u,u.mergeTicksOptions(),n.isDefault&&(e.scale=u)}}),t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,n=[],i=[];return a.each(e.data.datasets,function(a,r){var o=e.getDatasetMeta(r),s=a.type||e.config.type;if(o.type&&o.type!==s&&(e.destroyDatasetMeta(r),o=e.getDatasetMeta(r)),o.type=s,n.push(o.type),o.controller)o.controller.updateIndex(r);else{var l=t.controllers[o.type];if(void 0===l)throw new Error('"'+o.type+'" is not a chart type.');o.controller=new l(e,r),i.push(o.controller)}},e),i},resetElements:function(){var t=this;a.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t){var e=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),n(e),!1!==l.notify(e,"beforeUpdate")){e.tooltip._data=e.data;var i=e.buildOrUpdateControllers();a.each(e.data.datasets,function(t,n){e.getDatasetMeta(n).controller.buildOrUpdateElements()},e),e.updateLayout(),a.each(i,function(t){t.reset()}),e.updateDatasets(),l.notify(e,"afterUpdate"),e._bufferedRender?e._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:e.render(t)}},updateLayout:function(){var e=this;!1!==l.notify(e,"beforeLayout")&&(t.layoutService.update(this,this.width,this.height),l.notify(e,"afterScaleUpdate"),l.notify(e,"afterLayout"))},updateDatasets:function(){var t=this;if(!1!==l.notify(t,"beforeDatasetsUpdate")){for(var e=0,n=t.data.datasets.length;e<n;++e)t.updateDataset(e);l.notify(t,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this,n=e.getDatasetMeta(t),i={meta:n,index:t};!1!==l.notify(e,"beforeDatasetUpdate",[i])&&(n.controller.update(),l.notify(e,"afterDatasetUpdate",[i]))},render:function(e){var n=this;e&&"object"==typeof e||(e={duration:e,lazy:arguments[1]});var i=e.duration,r=e.lazy;if(!1!==l.notify(n,"beforeRender")){var o=n.options.animation,s=function(t){l.notify(n,"afterRender"),a.callback(o&&o.onComplete,[t],n)};if(o&&(void 0!==i&&0!==i||void 0===i&&0!==o.duration)){var u=new t.Animation({numSteps:(i||o.duration)/16.66,easing:e.easing||o.easing,render:function(t,e){var n=a.easing.effects[e.easing],i=e.currentStep,r=i/e.numSteps;t.draw(n(r),r,i)},onAnimationProgress:o.onProgress,onAnimationComplete:s});t.animationService.addAnimation(n,u,i,r)}else n.draw(),s(new t.Animation({numSteps:0,chart:n}));return n}},draw:function(t){var e=this;e.clear(),a.isNullOrUndef(t)&&(t=1),e.transition(t),!1!==l.notify(e,"beforeDraw",[t])&&(a.each(e.boxes,function(t){t.draw(e.chartArea)},e),e.scale&&e.scale.draw(),e.drawDatasets(t),e.tooltip.draw(),l.notify(e,"afterDraw",[t]))},transition:function(t){for(var e=this,n=0,i=(e.data.datasets||[]).length;n<i;++n)e.isDatasetVisible(n)&&e.getDatasetMeta(n).controller.transition(t);e.tooltip.transition(t)},drawDatasets:function(t){var e=this;if(!1!==l.notify(e,"beforeDatasetsDraw",[t])){for(var n=(e.data.datasets||[]).length-1;n>=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);l.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this,i=n.getDatasetMeta(t),a={meta:i,index:t,easingValue:e};!1!==l.notify(n,"beforeDatasetDraw",[a])&&(i.controller.draw(e),l.notify(n,"afterDatasetDraw",[a]))},getElementAtEvent:function(t){return r.modes.single(this,t)},getElementsAtEvent:function(t){return r.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return r.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=r.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return r.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this,n=e.data.datasets[t];n._meta||(n._meta={});var i=n._meta[e.id];return i||(i=n._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e<n;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroyDatasetMeta:function(t){var e=this.id,n=this.data.datasets[t],i=n._meta&&n._meta[e];i&&(i.controller.destroy(),delete n._meta[e])},destroy:function(){var e,n,i=this,r=i.canvas;for(i.stop(),e=0,n=i.data.datasets.length;e<n;++e)i.destroyDatasetMeta(e);r&&(i.unbindEvents(),a.canvas.clear(i),o.releaseContext(i.ctx),i.canvas=null,i.ctx=null),l.notify(i,"destroy"),delete t.instances[i.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var e=this;e.tooltip=new t.Tooltip({_chart:e,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e)},bindEvents:function(){var t=this,e=t._listeners={},n=function(){t.eventHandler.apply(t,arguments)};a.each(t.options.events,function(i){o.addEventListener(t,i,n),e[i]=n}),t.options.responsive&&(n=function(){t.resize()},o.addEventListener(t,"resize",n),e.resize=n)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,a.each(e,function(e,n){o.removeEventListener(t,n,e)}))},updateHoverStyle:function(t,e,n){var i,a,r,o=n?"setHoverStyle":"removeHoverStyle";for(a=0,r=t.length;a<r;++a)(i=t[a])&&this.getDatasetMeta(i._datasetIndex).controller[o](i)},eventHandler:function(t){var e=this,n=e.tooltip;if(!1!==l.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var i=e.handleEvent(t);i|=n&&n.handleEvent(t),l.notify(e,"afterEvent",[t]);var a=e._bufferedRequest;return a?e.render(a):i&&!e.animating&&(e.stop(),e.render(e.options.hover.animationDuration,!0)),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e=this,n=e.options||{},i=n.hover,r=!1;return e.lastActive=e.lastActive||[],"mouseout"===t.type?e.active=[]:e.active=e.getElementsAtEventForMode(t,i.mode,i),a.callback(n.onHover||n.hover.onHover,[t.native,e.active],e),"mouseup"!==t.type&&"click"!==t.type||n.onClick&&n.onClick.call(e,t.native,e.active),e.lastActive.length&&e.updateHoverStyle(e.lastActive,i.mode,!1),e.active.length&&i.mode&&e.updateHoverStyle(e.active,i.mode,!0),r=!a.arrayEquals(e.active,e.lastActive),e.lastActive=e.active,r}}),t.Controller=t}},{25:25,28:28,45:45,48:48}],24:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),a.forEach(function(e){var n="onData"+e.charAt(0).toUpperCase()+e.slice(1),a=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),r=a.apply(this,e);return i.each(t._chartjs.listeners,function(t){"function"==typeof t[n]&&t[n].apply(t,e)}),r}})}))}function n(t,e){var n=t._chartjs;if(n){var i=n.listeners,r=i.indexOf(e);-1!==r&&i.splice(r,1),i.length>0||(a.forEach(function(e){delete t[e]}),delete t._chartjs)}}var a=["push","pop","shift","splice","unshift"];t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null===e.xAxisID&&(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=n.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,n=e.dataElementType;return n&&new n({_chart:e.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,n=this,i=n.getMeta(),a=n.getDataset().data||[],r=i.data;for(t=0,e=a.length;t<e;++t)r[t]=r[t]||n.createMetaData(t);i.dataset=i.dataset||n.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t=this,i=t.getDataset(),a=i.data||(i.data=[]);t._data!==a&&(t._data&&n(t._data,t),e(a,t),t._data=a),t.resyncElements()},update:i.noop,transition:function(t){for(var e=this.getMeta(),n=e.data||[],i=n.length,a=0;a<i;++a)n[a].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],n=e.length,i=0;for(t.dataset&&t.dataset.draw();i<n;++i)e[i].draw()},removeHoverStyle:function(t,e){var n=this.chart.data.datasets[t._datasetIndex],a=t._index,r=t.custom||{},o=i.valueAtIndexOrDefault,s=t._model;s.backgroundColor=r.backgroundColor?r.backgroundColor:o(n.backgroundColor,a,e.backgroundColor),s.borderColor=r.borderColor?r.borderColor:o(n.borderColor,a,e.borderColor),s.borderWidth=r.borderWidth?r.borderWidth:o(n.borderWidth,a,e.borderWidth)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},r=i.valueAtIndexOrDefault,o=i.getHoverColor,s=t._model;s.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:r(e.hoverBackgroundColor,n,o(s.backgroundColor)),s.borderColor=a.hoverBorderColor?a.hoverBorderColor:r(e.hoverBorderColor,n,o(s.borderColor)),s.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:r(e.hoverBorderWidth,n,s.borderWidth)},resyncElements:function(){var t=this,e=t.getMeta(),n=t.getDataset().data,i=e.data.length,a=n.length;a<i?e.data.splice(a,i-a):a>i&&t.insertElements(i,a-i)},insertElements:function(t,e){for(var n=0;n<e;++n)this.addElementAndReset(t+n)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=i.inherits}},{45:45}],25:[function(t,e,n){"use strict";var i=t(45);e.exports={_set:function(t,e){return i.merge(this[t]||(this[t]={}),e)}}},{45:45}],26:[function(t,e,n){"use strict";function i(t,e,n,i){var r,o,s,l,u,d,c,h,f,g=Object.keys(n);for(r=0,o=g.length;r<o;++r)if(s=g[r],d=n[s],e.hasOwnProperty(s)||(e[s]=d),(l=e[s])!==d&&"_"!==s[0]){if(t.hasOwnProperty(s)||(t[s]=l),u=t[s],(c=typeof d)===typeof u)if("string"===c){if((h=a(u)).valid&&(f=a(d)).valid){e[s]=f.mix(h,i).rgbString();continue}}else if("number"===c&&isFinite(u)&&isFinite(d)){e[s]=u+(d-u)*i;continue}e[s]=d}}var a=t(2),r=t(45),o=function(t){r.extend(this,t),this.initialize.apply(this,arguments)};r.extend(o.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=r.clone(t._model)),t._start={},t},transition:function(t){var e=this,n=e._model,a=e._start,r=e._view;return n&&1!==t?(r||(r=e._view={}),a||(a=e._start={}),i(a,r,n,t),e):(e._view=n,e._start=null,e)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return r.isNumber(this._model.x)&&r.isNumber(this._model.y)}}),o.extend=r.inherits,e.exports=o},{2:2,45:45}],27:[function(t,e,n){"use strict";var i=t(2),a=t(25),r=t(45);e.exports=function(t){function e(t,e,n){var i;return"string"==typeof t?(i=parseInt(t,10),-1!==t.indexOf("%")&&(i=i/100*e.parentNode[n])):i=t,i}function n(t){return void 0!==t&&null!==t&&"none"!==t}function o(t,i,a){var r=document.defaultView,o=t.parentNode,s=r.getComputedStyle(t)[i],l=r.getComputedStyle(o)[i],u=n(s),d=n(l),c=Number.POSITIVE_INFINITY;return u||d?Math.min(u?e(s,t,a):c,d?e(l,o,a):c):"none"}r.extend=function(t){for(var e=1,n=arguments.length;e<n;e++)r.each(arguments[e],function(e,n){t[n]=e});return t},r.configMerge=function(){return r.merge(r.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,n,i,a){var o=n[e]||{},s=i[e];"scales"===e?n[e]=r.scaleMerge(o,s):"scale"===e?n[e]=r.merge(o,[t.scaleService.getScaleDefaults(s.type),s]):r._merger(e,n,i,a)}})},r.scaleMerge=function(){return r.merge(r.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,n,i,a){if("xAxes"===e||"yAxes"===e){var o,s,l,u=i[e].length;for(n[e]||(n[e]=[]),o=0;o<u;++o)l=i[e][o],s=r.valueOrDefault(l.type,"xAxes"===e?"category":"linear"),o>=n[e].length&&n[e].push({}),!n[e][o].type||l.type&&l.type!==n[e][o].type?r.merge(n[e][o],[t.scaleService.getScaleDefaults(s),l]):r.merge(n[e][o],l)}else r._merger(e,n,i,a)}})},r.where=function(t,e){if(r.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return r.each(t,function(t){e(t)&&n.push(t)}),n},r.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i<a;++i)if(e.call(n,t[i],i,t))return i;return-1},r.findNextWhere=function(t,e,n){r.isNullOrUndef(n)&&(n=-1);for(var i=n+1;i<t.length;i++){var a=t[i];if(e(a))return a}},r.findPreviousWhere=function(t,e,n){r.isNullOrUndef(n)&&(n=t.length);for(var i=n-1;i>=0;i--){var a=t[i];if(e(a))return a}},r.inherits=function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=n};return i.prototype=e.prototype,n.prototype=new i,n.extend=r.inherits,t&&r.extend(n.prototype,t),n.__super__=e.prototype,n},r.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},r.almostEquals=function(t,e,n){return Math.abs(t-e)<n},r.almostWhole=function(t,e){var n=Math.round(t);return n-e<t&&n+e>t},r.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},r.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},r.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},r.log10=Math.log10?function(t){return Math.log10(t)}:function(t){return Math.log(t)/Math.LN10},r.toRadians=function(t){return t*(Math.PI/180)},r.toDegrees=function(t){return t*(180/Math.PI)},r.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),r=Math.atan2(i,n);return r<-.5*Math.PI&&(r+=2*Math.PI),{angle:r,distance:a}},r.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},r.aliasPixel=function(t){return t%2==0?0:.5},r.splineCurve=function(t,e,n,i){var a=t.skip?e:t,r=e,o=n.skip?e:n,s=Math.sqrt(Math.pow(r.x-a.x,2)+Math.pow(r.y-a.y,2)),l=Math.sqrt(Math.pow(o.x-r.x,2)+Math.pow(o.y-r.y,2)),u=s/(s+l),d=l/(s+l),c=i*(u=isNaN(u)?0:u),h=i*(d=isNaN(d)?0:d);return{previous:{x:r.x-c*(o.x-a.x),y:r.y-c*(o.y-a.y)},next:{x:r.x+h*(o.x-a.x),y:r.y+h*(o.y-a.y)}}},r.EPSILON=Number.EPSILON||1e-14,r.splineCurveMonotone=function(t){var e,n,i,a,o=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),s=o.length;for(e=0;e<s;++e)if(!(i=o[e]).model.skip){if(n=e>0?o[e-1]:null,(a=e<s-1?o[e+1]:null)&&!a.model.skip){var l=a.model.x-i.model.x;i.deltaK=0!==l?(a.model.y-i.model.y)/l:0}!n||n.model.skip?i.mK=i.deltaK:!a||a.model.skip?i.mK=n.deltaK:this.sign(n.deltaK)!==this.sign(i.deltaK)?i.mK=0:i.mK=(n.deltaK+i.deltaK)/2}var u,d,c,h;for(e=0;e<s-1;++e)i=o[e],a=o[e+1],i.model.skip||a.model.skip||(r.almostEquals(i.deltaK,0,this.EPSILON)?i.mK=a.mK=0:(u=i.mK/i.deltaK,d=a.mK/i.deltaK,(h=Math.pow(u,2)+Math.pow(d,2))<=9||(c=3/Math.sqrt(h),i.mK=u*c*i.deltaK,a.mK=d*c*i.deltaK)));var f;for(e=0;e<s;++e)(i=o[e]).model.skip||(n=e>0?o[e-1]:null,a=e<s-1?o[e+1]:null,n&&!n.model.skip&&(f=(i.model.x-n.model.x)/3,i.model.controlPointPreviousX=i.model.x-f,i.model.controlPointPreviousY=i.model.y-f*i.mK),a&&!a.model.skip&&(f=(a.model.x-i.model.x)/3,i.model.controlPointNextX=i.model.x+f,i.model.controlPointNextY=i.model.y+f*i.mK))},r.nextItem=function(t,e,n){return n?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},r.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},r.niceNum=function(t,e){var n=Math.floor(r.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},r.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},r.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,o=t.currentTarget||t.srcElement,s=o.getBoundingClientRect(),l=a.touches;l&&l.length>0?(n=l[0].clientX,i=l[0].clientY):(n=a.clientX,i=a.clientY);var u=parseFloat(r.getStyle(o,"padding-left")),d=parseFloat(r.getStyle(o,"padding-top")),c=parseFloat(r.getStyle(o,"padding-right")),h=parseFloat(r.getStyle(o,"padding-bottom")),f=s.right-s.left-u-c,g=s.bottom-s.top-d-h;return n=Math.round((n-s.left-u)/f*o.width/e.currentDevicePixelRatio),i=Math.round((i-s.top-d)/g*o.height/e.currentDevicePixelRatio),{x:n,y:i}},r.getConstraintWidth=function(t){return o(t,"max-width","clientWidth")},r.getConstraintHeight=function(t){return o(t,"max-height","clientHeight")},r.getMaximumWidth=function(t){var e=t.parentNode;if(!e)return t.clientWidth;var n=parseInt(r.getStyle(e,"padding-left"),10),i=parseInt(r.getStyle(e,"padding-right"),10),a=e.clientWidth-n-i,o=r.getConstraintWidth(t);return isNaN(o)?a:Math.min(a,o)},r.getMaximumHeight=function(t){var e=t.parentNode;if(!e)return t.clientHeight;var n=parseInt(r.getStyle(e,"padding-top"),10),i=parseInt(r.getStyle(e,"padding-bottom"),10),a=e.clientHeight-n-i,o=r.getConstraintHeight(t);return isNaN(o)?a:Math.min(a,o)},r.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},r.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||window.devicePixelRatio||1;if(1!==n){var i=t.canvas,a=t.height,r=t.width;i.height=a*n,i.width=r*n,t.ctx.scale(n,n),i.style.height=a+"px",i.style.width=r+"px"}},r.fontString=function(t,e,n){return e+" "+t+"px "+n},r.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},o=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},o=i.garbageCollect=[],i.font=e),t.font=e;var s=0;r.each(n,function(e){void 0!==e&&null!==e&&!0!==r.isArray(e)?s=r.measureText(t,a,o,s,e):r.isArray(e)&&r.each(e,function(e){void 0===e||null===e||r.isArray(e)||(s=r.measureText(t,a,o,s,e))})});var l=o.length/2;if(l>n.length){for(var u=0;u<l;u++)delete a[o[u]];o.splice(0,l)}return s},r.measureText=function(t,e,n,i,a){var r=e[a];return r||(r=e[a]=t.measureText(a).width,n.push(a)),r>i&&(i=r),i},r.numberOfLabelLines=function(t){var e=1;return r.each(t,function(t){r.isArray(t)&&t.length>e&&(e=t.length)}),e},r.color=i?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),i(t)}:function(t){return console.error("Color.js not found!"),t},r.getHoverColor=function(t){return t instanceof CanvasPattern?t:r.color(t).saturate(.5).darken(.1).rgbString()}}},{2:2,25:25,45:45}],28:[function(t,e,n){"use strict";function i(t,e){return t.native?{x:t.x,y:t.y}:u.getRelativePosition(t,e)}function a(t,e){var n,i,a,r,o;for(i=0,r=t.data.datasets.length;i<r;++i)if(t.isDatasetVisible(i))for(a=0,o=(n=t.getDatasetMeta(i)).data.length;a<o;++a){var s=n.data[a];s._view.skip||e(s)}}function r(t,e){var n=[];return a(t,function(t){t.inRange(e.x,e.y)&&n.push(t)}),n}function o(t,e,n,i){var r=Number.POSITIVE_INFINITY,o=[];return a(t,function(t){if(!n||t.inRange(e.x,e.y)){var a=t.getCenterPoint(),s=i(e,a);s<r?(o=[t],r=s):s===r&&o.push(t)}}),o}function s(t){var e=-1!==t.indexOf("x"),n=-1!==t.indexOf("y");return function(t,i){var a=e?Math.abs(t.x-i.x):0,r=n?Math.abs(t.y-i.y):0;return Math.sqrt(Math.pow(a,2)+Math.pow(r,2))}}function l(t,e,n){var a=i(e,t);n.axis=n.axis||"x";var l=s(n.axis),u=n.intersect?r(t,a):o(t,a,!1,l),d=[];return u.length?(t.data.datasets.forEach(function(e,n){if(t.isDatasetVisible(n)){var i=t.getDatasetMeta(n).data[u[0]._index];i&&!i._view.skip&&d.push(i)}}),d):[]}var u=t(45);e.exports={modes:{single:function(t,e){var n=i(e,t),r=[];return a(t,function(t){if(t.inRange(n.x,n.y))return r.push(t),r}),r.slice(0,1)},label:l,index:l,dataset:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var l=s(n.axis),u=n.intersect?r(t,a):o(t,a,!1,l);return u.length>0&&(u=t.getDatasetMeta(u[0]._datasetIndex).data),u},"x-axis":function(t,e){return l(t,e,{intersect:!0})},point:function(t,e){return r(t,i(e,t))},nearest:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var r=s(n.axis),l=o(t,a,n.intersect,r);return l.length>1&&l.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),l.slice(0,1)},x:function(t,e,n){var r=i(e,t),o=[],s=!1;return a(t,function(t){t.inXRange(r.x)&&o.push(t),t.inRange(r.x,r.y)&&(s=!0)}),n.intersect&&!s&&(o=[]),o},y:function(t,e,n){var r=i(e,t),o=[],s=!1;return a(t,function(t){t.inYRange(r.y)&&o.push(t),t.inRange(r.x,r.y)&&(s=!0)}),n.intersect&&!s&&(o=[]),o}}}},{45:45}],29:[function(t,e,n){"use strict";t(25)._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},{25:25}],30:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){return i.where(t,function(t){return t.position===e})}function n(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i._tmpIndex_-a._tmpIndex_:i.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],r=a.length,o=0;o<r;++o)i=a[o],n.hasOwnProperty(i)&&(e[i]=n[i])},update:function(t,a,r){function o(t){var e=i.findNextWhere(D,function(e){return e.box===t});if(e)if(t.isHorizontal()){var n={left:Math.max(A,C),right:Math.max(O,P),top:0,bottom:0};t.update(t.fullWidth?b:M,x/2,n)}else t.update(e.minSize.width,S)}function s(t){t.isHorizontal()?(t.left=t.fullWidth?d:A,t.right=t.fullWidth?a-c:A+M,t.top=B,t.bottom=B+t.height,B=t.bottom):(t.left=z,t.right=z+t.width,t.top=F,t.bottom=F+S,z=t.right)}if(t){var l=t.options.layout||{},u=i.options.toPadding(l.padding),d=u.left,c=u.right,h=u.top,f=u.bottom,g=e(t.boxes,"left"),m=e(t.boxes,"right"),p=e(t.boxes,"top"),v=e(t.boxes,"bottom"),y=e(t.boxes,"chartArea");n(g,!0),n(m,!1),n(p,!0),n(v,!1);var b=a-d-c,x=r-h-f,_=x/2,k=(a-b/2)/(g.length+m.length),w=(r-_)/(p.length+v.length),M=b,S=x,D=[];i.each(g.concat(m,p,v),function(t){var e,n=t.isHorizontal();n?(e=t.update(t.fullWidth?b:M,w),S-=e.height):(e=t.update(k,_),M-=e.width),D.push({horizontal:n,minSize:e,box:t})});var C=0,P=0,T=0,I=0;i.each(p.concat(v),function(t){if(t.getPadding){var e=t.getPadding();C=Math.max(C,e.left),P=Math.max(P,e.right)}}),i.each(g.concat(m),function(t){if(t.getPadding){var e=t.getPadding();T=Math.max(T,e.top),I=Math.max(I,e.bottom)}});var A=d,O=c,F=h,R=f;i.each(g.concat(m),o),i.each(g,function(t){A+=t.width}),i.each(m,function(t){O+=t.width}),i.each(p.concat(v),o),i.each(p,function(t){F+=t.height}),i.each(v,function(t){R+=t.height}),i.each(g.concat(m),function(t){var e=i.findNextWhere(D,function(e){return e.box===t}),n={left:0,right:0,top:F,bottom:R};e&&t.update(e.minSize.width,S,n)}),A=d,O=c,F=h,R=f,i.each(g,function(t){A+=t.width}),i.each(m,function(t){O+=t.width}),i.each(p,function(t){F+=t.height}),i.each(v,function(t){R+=t.height});var L=Math.max(C-A,0);A+=L,O+=Math.max(P-O,0);var W=Math.max(T-F,0);F+=W,R+=Math.max(I-R,0);var Y=r-F-R,N=a-A-O;N===M&&Y===S||(i.each(g,function(t){t.height=Y}),i.each(m,function(t){t.height=Y}),i.each(p,function(t){t.fullWidth||(t.width=N)}),i.each(v,function(t){t.fullWidth||(t.width=N)}),S=Y,M=N);var z=d+L,B=h+W;i.each(g.concat(p),s),z+=M,B+=S,i.each(m,s),i.each(v,s),t.chartArea={left:A,top:F,right:A+M,bottom:F+S},i.each(y,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(M,S)})}}}}},{45:45}],31:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{plugins:{}}),e.exports=function(t){t.plugins={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&&e.push(t)}),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var n=e.indexOf(t);-1!==n&&e.splice(n,1)}),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,n){var i,a,r,o,s,l=this.descriptors(t),u=l.length;for(i=0;i<u;++i)if(a=l[i],r=a.plugin,"function"==typeof(s=r[e])&&((o=[t].concat(n||[])).push(a.options),!1===s.apply(r,o)))return!1;return!0},descriptors:function(t){var e=t._plugins||(t._plugins={});if(e.id===this._cacheId)return e.descriptors;var n=[],a=[],o=t&&t.config||{},s=o.options&&o.options.plugins||{};return this._plugins.concat(o.plugins||[]).forEach(function(t){if(-1===n.indexOf(t)){var e=t.id,o=s[e];!1!==o&&(!0===o&&(o=r.clone(i.global.plugins[e])),n.push(t),a.push({plugin:t,options:o||{}}))}}),e.descriptors=a,e.id=this._cacheId,a}},t.pluginService=t.plugins,t.PluginBase=a.extend({})}},{25:25,26:26,45:45}],32:[function(t,e,n){"use strict";function i(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(t[e].label);return i}function a(t,e,n){var i=t.getPixelForTick(e);return n&&(i-=0===e?(t.getPixelForTick(1)-i)/2:(i-t.getPixelForTick(e-1))/2),i}var r=t(25),o=t(26),s=t(45),l=t(34);r._set("scale",{display:!0,position:"left",offset:!1,gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{display:!1,labelString:"",lineHeight:1.2,padding:{top:4,bottom:4}},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:l.formatters.values,minor:{},major:{}}}),e.exports=function(t){function e(t,e,n){return s.isArray(e)?s.longestText(t,n,e):t.measureText(e).width}function n(t){var e=s.valueOrDefault,n=r.global,i=e(t.fontSize,n.defaultFontSize),a=e(t.fontStyle,n.defaultFontStyle),o=e(t.fontFamily,n.defaultFontFamily);return{size:i,style:a,family:o,font:s.fontString(i,a,o)}}function l(t){return s.options.toLineHeight(s.valueOrDefault(t.lineHeight,1.2),s.valueOrDefault(t.fontSize,r.global.defaultFontSize))}t.Scale=o.extend({getPadding:function(){var t=this;return{left:t.paddingLeft||0,top:t.paddingTop||0,right:t.paddingRight||0,bottom:t.paddingBottom||0}},getTicks:function(){return this._ticks},mergeTicksOptions:function(){var t=this.options.ticks;!1===t.minor&&(t.minor={display:!1}),!1===t.major&&(t.major={display:!1});for(var e in t)"major"!==e&&"minor"!==e&&(void 0===t.minor[e]&&(t.minor[e]=t[e]),void 0===t.major[e]&&(t.major[e]=t[e]))},beforeUpdate:function(){s.callback(this.options.beforeUpdate,[this])},update:function(t,e,n){var i,a,r,o,l,u,d=this;for(d.beforeUpdate(),d.maxWidth=t,d.maxHeight=e,d.margins=s.extend({left:0,right:0,top:0,bottom:0},n),d.longestTextCache=d.longestTextCache||{},d.beforeSetDimensions(),d.setDimensions(),d.afterSetDimensions(),d.beforeDataLimits(),d.determineDataLimits(),d.afterDataLimits(),d.beforeBuildTicks(),l=d.buildTicks()||[],d.afterBuildTicks(),d.beforeTickToLabelConversion(),r=d.convertTicksToLabels(l)||d.ticks,d.afterTickToLabelConversion(),d.ticks=r,i=0,a=r.length;i<a;++i)o=r[i],(u=l[i])?u.label=o:l.push(u={label:o,major:!1});return d._ticks=l,d.beforeCalculateTickRotation(),d.calculateTickRotation(),d.afterCalculateTickRotation(),d.beforeFit(),d.fit(),d.afterFit(),d.afterUpdate(),d.minSize},afterUpdate:function(){s.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){s.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){s.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){s.callback(this.options.beforeDataLimits,[this])},determineDataLimits:s.noop,afterDataLimits:function(){s.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){s.callback(this.options.beforeBuildTicks,[this])},buildTicks:s.noop,afterBuildTicks:function(){s.callback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){s.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this,e=t.options.ticks;t.ticks=t.ticks.map(e.userCallback||e.callback,this)},afterTickToLabelConversion:function(){s.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){s.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t=this,e=t.ctx,a=t.options.ticks,r=i(t._ticks),o=n(a);e.font=o.font;var l=a.minRotation||0;if(r.length&&t.options.display&&t.isHorizontal())for(var u,d=s.longestText(e,o.font,r,t.longestTextCache),c=d,h=t.getPixelForTick(1)-t.getPixelForTick(0)-6;c>h&&l<a.maxRotation;){var f=s.toRadians(l);if(u=Math.cos(f),Math.sin(f)*d>t.maxHeight){l--;break}l++,c=u*d}t.labelRotation=l},afterCalculateTickRotation:function(){s.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){s.callback(this.options.beforeFit,[this])},fit:function(){var t=this,a=t.minSize={width:0,height:0},r=i(t._ticks),o=t.options,u=o.ticks,d=o.scaleLabel,c=o.gridLines,h=o.display,f=t.isHorizontal(),g=n(u),m=o.gridLines.tickMarkLength;if(a.width=f?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:h&&c.drawTicks?m:0,a.height=f?h&&c.drawTicks?m:0:t.maxHeight,d.display&&h){var p=l(d)+s.options.toPadding(d.padding).height;f?a.height+=p:a.width+=p}if(u.display&&h){var v=s.longestText(t.ctx,g.font,r,t.longestTextCache),y=s.numberOfLabelLines(r),b=.5*g.size,x=t.options.ticks.padding;if(f){t.longestLabelWidth=v;var _=s.toRadians(t.labelRotation),k=Math.cos(_),w=Math.sin(_)*v+g.size*y+b*(y-1)+b;a.height=Math.min(t.maxHeight,a.height+w+x),t.ctx.font=g.font;var M=e(t.ctx,r[0],g.font),S=e(t.ctx,r[r.length-1],g.font);0!==t.labelRotation?(t.paddingLeft="bottom"===o.position?k*M+3:k*b+3,t.paddingRight="bottom"===o.position?k*b+3:k*S+3):(t.paddingLeft=M/2+3,t.paddingRight=S/2+3)}else u.mirror?v=0:v+=x+b,a.width=Math.min(t.maxWidth,a.width+v),t.paddingTop=g.size/2,t.paddingBottom=g.size/2}t.handleMargins(),t.width=a.width,t.height=a.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){s.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(s.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:s.noop,getPixelForValue:s.noop,getValueForPixel:s.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),a=i*t+e.paddingLeft;n&&(a+=i/2);var r=e.left+Math.round(a);return r+=e.isFullWidth()?e.margins.left:0}var o=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(o/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this,e=t.min,n=t.max;return t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0},_autoSkip:function(t){var e,n,i,a,r=this,o=r.isHorizontal(),l=r.options.ticks.minor,u=t.length,d=s.toRadians(r.labelRotation),c=Math.cos(d),h=r.longestLabelWidth*c,f=[];for(l.maxTicksLimit&&(a=l.maxTicksLimit),o&&(e=!1,(h+l.autoSkipPadding)*u>r.width-(r.paddingLeft+r.paddingRight)&&(e=1+Math.floor((h+l.autoSkipPadding)*u/(r.width-(r.paddingLeft+r.paddingRight)))),a&&u>a&&(e=Math.max(e,Math.floor(u/a)))),n=0;n<u;n++)i=t[n],((e>1&&n%e>0||n%e==0&&n+e>=u)&&n!==u-1||s.isNullOrUndef(i.label))&&delete i.label,f.push(i);return f},draw:function(t){var e=this,i=e.options;if(i.display){var o=e.ctx,u=r.global,d=i.ticks.minor,c=i.ticks.major||d,h=i.gridLines,f=i.scaleLabel,g=0!==e.labelRotation,m=e.isHorizontal(),p=d.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),v=s.valueOrDefault(d.fontColor,u.defaultFontColor),y=n(d),b=s.valueOrDefault(c.fontColor,u.defaultFontColor),x=n(c),_=h.drawTicks?h.tickMarkLength:0,k=s.valueOrDefault(f.fontColor,u.defaultFontColor),w=n(f),M=s.options.toPadding(f.padding),S=s.toRadians(e.labelRotation),D=[],C="right"===i.position?e.left:e.right-_,P="right"===i.position?e.left+_:e.right,T="bottom"===i.position?e.top:e.bottom-_,I="bottom"===i.position?e.top+_:e.bottom;if(s.each(p,function(n,r){if(void 0!==n.label){var o,l,c,f,v=n.label;r===e.zeroLineIndex&&i.offset===h.offsetGridLines?(o=h.zeroLineWidth,l=h.zeroLineColor,c=h.zeroLineBorderDash,f=h.zeroLineBorderDashOffset):(o=s.valueAtIndexOrDefault(h.lineWidth,r),l=s.valueAtIndexOrDefault(h.color,r),c=s.valueOrDefault(h.borderDash,u.borderDash),f=s.valueOrDefault(h.borderDashOffset,u.borderDashOffset));var y,b,x,k,w,M,A,O,F,R,L="middle",W="middle",Y=d.padding;if(m){var N=_+Y;"bottom"===i.position?(W=g?"middle":"top",L=g?"right":"center",R=e.top+N):(W=g?"middle":"bottom",L=g?"left":"center",R=e.bottom-N);var z=a(e,r,h.offsetGridLines&&p.length>1);z<e.left&&(l="rgba(0,0,0,0)"),z+=s.aliasPixel(o),F=e.getPixelForTick(r)+d.labelOffset,y=x=w=A=z,b=T,k=I,M=t.top,O=t.bottom}else{var B,V="left"===i.position;d.mirror?(L=V?"left":"right",B=Y):(L=V?"right":"left",B=_+Y),F=V?e.right-B:e.left+B;var H=a(e,r,h.offsetGridLines&&p.length>1);H<e.top&&(l="rgba(0,0,0,0)"),H+=s.aliasPixel(o),R=e.getPixelForTick(r)+d.labelOffset,y=C,x=P,w=t.left,A=t.right,b=k=M=O=H}D.push({tx1:y,ty1:b,tx2:x,ty2:k,x1:w,y1:M,x2:A,y2:O,labelX:F,labelY:R,glWidth:o,glColor:l,glBorderDash:c,glBorderDashOffset:f,rotation:-1*S,label:v,major:n.major,textBaseline:W,textAlign:L})}}),s.each(D,function(t){if(h.display&&(o.save(),o.lineWidth=t.glWidth,o.strokeStyle=t.glColor,o.setLineDash&&(o.setLineDash(t.glBorderDash),o.lineDashOffset=t.glBorderDashOffset),o.beginPath(),h.drawTicks&&(o.moveTo(t.tx1,t.ty1),o.lineTo(t.tx2,t.ty2)),h.drawOnChartArea&&(o.moveTo(t.x1,t.y1),o.lineTo(t.x2,t.y2)),o.stroke(),o.restore()),d.display){o.save(),o.translate(t.labelX,t.labelY),o.rotate(t.rotation),o.font=t.major?x.font:y.font,o.fillStyle=t.major?b:v,o.textBaseline=t.textBaseline,o.textAlign=t.textAlign;var e=t.label;if(s.isArray(e))for(var n=0,i=0;n<e.length;++n)o.fillText(""+e[n],0,i),i+=1.5*y.size;else o.fillText(e,0,0);o.restore()}}),f.display){var A,O,F=0,R=l(f)/2;if(m)A=e.left+(e.right-e.left)/2,O="bottom"===i.position?e.bottom-R-M.bottom:e.top+R+M.top;else{var L="left"===i.position;A=L?e.left+R+M.top:e.right-R-M.top,O=e.top+(e.bottom-e.top)/2,F=L?-.5*Math.PI:.5*Math.PI}o.save(),o.translate(A,O),o.rotate(F),o.textAlign="center",o.textBaseline="middle",o.fillStyle=k,o.font=w.font,o.fillText(f.labelString,0,0),o.restore()}if(h.drawBorder){o.lineWidth=s.valueAtIndexOrDefault(h.lineWidth,0),o.strokeStyle=s.valueAtIndexOrDefault(h.color,0);var W=e.left,Y=e.right,N=e.top,z=e.bottom,B=s.aliasPixel(o.lineWidth);m?(N=z="top"===i.position?e.bottom:e.top,N+=B,z+=B):(W=Y="left"===i.position?e.right:e.left,W+=B,Y+=B),o.beginPath(),o.moveTo(W,N),o.lineTo(Y,z),o.stroke()}}}})}},{25:25,26:26,34:34,45:45}],33:[function(t,e,n){"use strict";var i=t(25),a=t(45);e.exports=function(t){t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,e,n){this.constructors[t]=e,this.defaults[t]=a.clone(n)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(t){return this.defaults.hasOwnProperty(t)?a.merge({},[i.scale,this.defaults[t]]):{}},updateScaleDefaults:function(t,e){var n=this;n.defaults.hasOwnProperty(t)&&(n.defaults[t]=a.extend(n.defaults[t],e))},addScalesToLayout:function(e){a.each(e.scales,function(n){n.fullWidth=n.options.fullWidth,n.position=n.options.position,n.weight=n.options.weight,t.layoutService.addBox(e,n)})}}}},{25:25,45:45}],34:[function(t,e,n){"use strict";var i=t(45);e.exports={generators:{linear:function(t,e){var n,a=[];if(t.stepSize&&t.stepSize>0)n=t.stepSize;else{var r=i.niceNum(e.max-e.min,!1);n=i.niceNum(r/(t.maxTicks-1),!0)}var o=Math.floor(e.min/n)*n,s=Math.ceil(e.max/n)*n;t.min&&t.max&&t.stepSize&&i.almostWhole((t.max-t.min)/t.stepSize,n/1e3)&&(o=t.min,s=t.max);var l=(s-o)/n;l=i.almostEquals(l,Math.round(l),n/1e3)?Math.round(l):Math.ceil(l),a.push(void 0!==t.min?t.min:o);for(var u=1;u<l;++u)a.push(o+u*n);return a.push(void 0!==t.max?t.max:s),a},logarithmic:function(t,e){var n,a,r=[],o=i.valueOrDefault,s=o(t.min,Math.pow(10,Math.floor(i.log10(e.min)))),l=Math.floor(i.log10(e.max)),u=Math.ceil(e.max/Math.pow(10,l));0===s?(n=Math.floor(i.log10(e.minNotZero)),a=Math.floor(e.minNotZero/Math.pow(10,n)),r.push(s),s=a*Math.pow(10,n)):(n=Math.floor(i.log10(s)),a=Math.floor(s/Math.pow(10,n)));do{r.push(s),10===++a&&(a=1,++n),s=a*Math.pow(10,n)}while(n<l||n===l&&a<u);var d=o(t.max,s);return r.push(d),r}},formatters:{values:function(t){return i.isArray(t)?t:""+t},linear:function(t,e,n){var a=n.length>3?n[2]-n[1]:n[1]-n[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var r=i.log10(Math.abs(a)),o="";if(0!==t){var s=-1*Math.floor(r);s=Math.max(Math.min(s,20),0),o=t.toFixed(s)}else o="0";return o},logarithmic:function(t,e,n){var a=t/Math.pow(10,Math.floor(i.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===e||e===n.length-1?t.toExponential():""}}}},{45:45}],35:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:r.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var r=t[0];r.xLabel?n=r.xLabel:a>0&&r.index<a&&(n=i[r.index])}return n},afterTitle:r.noop,beforeBody:r.noop,beforeLabel:r.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n&&(n+=": "),n+=t.yLabel},labelColor:function(t,e){var n=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},labelTextColor:function(){return this._options.bodyFontColor},afterLabel:r.noop,afterBody:r.noop,beforeFooter:r.noop,footer:r.noop,afterFooter:r.noop}}}),e.exports=function(t){function e(t,e){var n=r.color(t);return n.alpha(e*n.alpha()).rgbaString()}function n(t,e){return e&&(r.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function o(t){var e=t._xScale,n=t._yScale||t._scale,i=t._index,a=t._datasetIndex;return{xLabel:e?e.getLabelForIndex(i,a):"",yLabel:n?n.getLabelForIndex(i,a):"",index:i,datasetIndex:a,x:t._model.x,y:t._model.y}}function s(t){var e=i.global,n=r.valueOrDefault;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,bodyFontColor:t.bodyFontColor,_bodyFontFamily:n(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:n(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:n(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:n(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:n(t.titleFontStyle,e.defaultFontStyle),titleFontSize:n(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:n(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:n(t.footerFontStyle,e.defaultFontStyle),footerFontSize:n(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}function l(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,o=e.body,s=o.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);s+=e.beforeBody.length+e.afterBody.length;var l=e.title.length,u=e.footer.length,d=e.titleFontSize,c=e.bodyFontSize,h=e.footerFontSize;i+=l*d,i+=l?(l-1)*e.titleSpacing:0,i+=l?e.titleMarginBottom:0,i+=s*c,i+=s?(s-1)*e.bodySpacing:0,i+=u?e.footerMarginTop:0,i+=u*h,i+=u?(u-1)*e.footerSpacing:0;var f=0,g=function(t){a=Math.max(a,n.measureText(t).width+f)};return n.font=r.fontString(d,e._titleFontStyle,e._titleFontFamily),r.each(e.title,g),n.font=r.fontString(c,e._bodyFontStyle,e._bodyFontFamily),r.each(e.beforeBody.concat(e.afterBody),g),f=e.displayColors?c+2:0,r.each(o,function(t){r.each(t.before,g),r.each(t.lines,g),r.each(t.after,g)}),f=0,n.font=r.fontString(h,e._footerFontStyle,e._footerFontFamily),r.each(e.footer,g),a+=2*e.xPadding,{width:a,height:i}}function u(t,e){var n=t._model,i=t._chart,a=t._chart.chartArea,r="center",o="center";n.y<e.height?o="top":n.y>i.height-e.height&&(o="bottom");var s,l,u,d,c,h=(a.left+a.right)/2,f=(a.top+a.bottom)/2;"center"===o?(s=function(t){return t<=h},l=function(t){return t>h}):(s=function(t){return t<=e.width/2},l=function(t){return t>=i.width-e.width/2}),u=function(t){return t+e.width>i.width},d=function(t){return t-e.width<0},c=function(t){return t<=f?"top":"bottom"},s(n.x)?(r="left",u(n.x)&&(r="center",o=c(n.y))):l(n.x)&&(r="right",d(n.x)&&(r="center",o=c(n.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:r,yAlign:g.yAlign?g.yAlign:o}}function d(t,e,n){var i=t.x,a=t.y,r=t.caretSize,o=t.caretPadding,s=t.cornerRadius,l=n.xAlign,u=n.yAlign,d=r+o,c=s+o;return"right"===l?i-=e.width:"center"===l&&(i-=e.width/2),"top"===u?a+=d:a-="bottom"===u?e.height+d:e.height/2,"center"===u?"left"===l?i+=d:"right"===l&&(i-=d):"left"===l?i-=c:"right"===l&&(i+=c),{x:i,y:a}}t.Tooltip=a.extend({initialize:function(){this._model=s(this._options)},getTitle:function(){var t=this,e=t._options.callbacks,i=e.beforeTitle.apply(t,arguments),a=e.title.apply(t,arguments),r=e.afterTitle.apply(t,arguments),o=[];return o=n(o,i),o=n(o,a),o=n(o,r)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return r.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var i=this,a=i._options.callbacks,o=[];return r.each(t,function(t){var r={before:[],lines:[],after:[]};n(r.before,a.beforeLabel.call(i,t,e)),n(r.lines,a.label.call(i,t,e)),n(r.after,a.afterLabel.call(i,t,e)),o.push(r)}),o},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return r.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,e=t._options.callbacks,i=e.beforeFooter.apply(t,arguments),a=e.footer.apply(t,arguments),r=e.afterFooter.apply(t,arguments),o=[];return o=n(o,i),o=n(o,a),o=n(o,r)},update:function(e){var n,i,a=this,c=a._options,h=a._model,f=a._model=s(c),g=a._active,m=a._data,p={xAlign:h.xAlign,yAlign:h.yAlign},v={x:h.x,y:h.y},y={width:h.width,height:h.height},b={x:h.caretX,y:h.caretY};if(g.length){f.opacity=1;var x=[],_=[];b=t.Tooltip.positioners[c.position](g,a._eventPosition);var k=[];for(n=0,i=g.length;n<i;++n)k.push(o(g[n]));c.filter&&(k=k.filter(function(t){return c.filter(t,m)})),c.itemSort&&(k=k.sort(function(t,e){return c.itemSort(t,e,m)})),r.each(k,function(t){x.push(c.callbacks.labelColor.call(a,t,a._chart)),_.push(c.callbacks.labelTextColor.call(a,t,a._chart))}),f.title=a.getTitle(k,m),f.beforeBody=a.getBeforeBody(k,m),f.body=a.getBody(k,m),f.afterBody=a.getAfterBody(k,m),f.footer=a.getFooter(k,m),f.x=Math.round(b.x),f.y=Math.round(b.y),f.caretPadding=c.caretPadding,f.labelColors=x,f.labelTextColors=_,f.dataPoints=k,v=d(f,y=l(this,f),p=u(this,y))}else f.opacity=0;return f.xAlign=p.xAlign,f.yAlign=p.yAlign,f.x=v.x,f.y=v.y,f.width=y.width,f.height=y.height,f.caretX=b.x,f.caretY=b.y,a._model=f,e&&c.custom&&c.custom.call(a,f),a},drawCaret:function(t,e){var n=this._chart.ctx,i=this._view,a=this.getCaretPosition(t,e,i);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var i,a,r,o,s,l,u=n.caretSize,d=n.cornerRadius,c=n.xAlign,h=n.yAlign,f=t.x,g=t.y,m=e.width,p=e.height;if("center"===h)s=g+p/2,"left"===c?(a=(i=f)-u,r=i,o=s+u,l=s-u):(a=(i=f+m)+u,r=i,o=s-u,l=s+u);else if("left"===c?(i=(a=f+d+u)-u,r=a+u):"right"===c?(i=(a=f+m-d-u)-u,r=a+u):(i=(a=f+m/2)-u,r=a+u),"top"===h)s=(o=g)-u,l=o;else{s=(o=g+p)+u,l=o;var v=r;r=i,i=v}return{x1:i,x2:a,x3:r,y1:o,y2:s,y3:l}},drawTitle:function(t,n,i,a){var o=n.title;if(o.length){i.textAlign=n._titleAlign,i.textBaseline="top";var s=n.titleFontSize,l=n.titleSpacing;i.fillStyle=e(n.titleFontColor,a),i.font=r.fontString(s,n._titleFontStyle,n._titleFontFamily);var u,d;for(u=0,d=o.length;u<d;++u)i.fillText(o[u],t.x,t.y),t.y+=s+l,u+1===o.length&&(t.y+=n.titleMarginBottom-l)}},drawBody:function(t,n,i,a){var o=n.bodyFontSize,s=n.bodySpacing,l=n.body;i.textAlign=n._bodyAlign,i.textBaseline="top",i.font=r.fontString(o,n._bodyFontStyle,n._bodyFontFamily);var u=0,d=function(e){i.fillText(e,t.x+u,t.y),t.y+=o+s};r.each(n.beforeBody,d);var c=n.displayColors;u=c?o+2:0,r.each(l,function(s,l){r.each(s.before,d),r.each(s.lines,function(r){if(c){i.fillStyle=e(n.legendColorBackground,a),i.fillRect(t.x,t.y,o,o),i.lineWidth=1,i.strokeStyle=e(n.labelColors[l].borderColor,a),i.strokeRect(t.x,t.y,o,o),i.fillStyle=e(n.labelColors[l].backgroundColor,a),i.fillRect(t.x+1,t.y+1,o-2,o-2);var s=e(n.labelTextColors[l],a);i.fillStyle=s}d(r)}),r.each(s.after,d)}),u=0,r.each(n.afterBody,d),t.y-=s},drawFooter:function(t,n,i,a){var o=n.footer;o.length&&(t.y+=n.footerMarginTop,i.textAlign=n._footerAlign,i.textBaseline="top",i.fillStyle=e(n.footerFontColor,a),i.font=r.fontString(n.footerFontSize,n._footerFontStyle,n._footerFontFamily),r.each(o,function(e){i.fillText(e,t.x,t.y),t.y+=n.footerFontSize+n.footerSpacing}))},drawBackground:function(t,n,i,a,r){i.fillStyle=e(n.backgroundColor,r),i.strokeStyle=e(n.borderColor,r),i.lineWidth=n.borderWidth;var o=n.xAlign,s=n.yAlign,l=t.x,u=t.y,d=a.width,c=a.height,h=n.cornerRadius;i.beginPath(),i.moveTo(l+h,u),"top"===s&&this.drawCaret(t,a),i.lineTo(l+d-h,u),i.quadraticCurveTo(l+d,u,l+d,u+h),"center"===s&&"right"===o&&this.drawCaret(t,a),i.lineTo(l+d,u+c-h),i.quadraticCurveTo(l+d,u+c,l+d-h,u+c),"bottom"===s&&this.drawCaret(t,a),i.lineTo(l+h,u+c),i.quadraticCurveTo(l,u+c,l,u+c-h),"center"===s&&"left"===o&&this.drawCaret(t,a),i.lineTo(l,u+h),i.quadraticCurveTo(l,u,l+h,u),i.closePath(),i.fill(),n.borderWidth>0&&i.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,r=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&r&&(this.drawBackground(i,e,t,n,a),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,a),this.drawBody(i,e,t,a),this.drawFooter(i,e,t,a))}},handleEvent:function(t){var e=this,n=e._options,i=!1;if(e._lastActive=e._lastActive||[],"mouseout"===t.type?e._active=[]:e._active=e._chart.getElementsAtEventForMode(t,n.mode,n),!(i=!r.arrayEquals(e._active,e._lastActive)))return!1;if(e._lastActive=e._active,n.enabled||n.custom){e._eventPosition={x:t.x,y:t.y};var a=e._model;e.update(!0),e.pivot(),i|=a.x!==e._model.x||a.y!==e._model.y}return i}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,r=0;for(e=0,n=t.length;e<n;++e){var o=t[e];if(o&&o.hasValue()){var s=o.tooltipPosition();i+=s.x,a+=s.y,++r}}return{x:Math.round(i/r),y:Math.round(a/r)}},nearest:function(t,e){var n,i,a,o=e.x,s=e.y,l=Number.POSITIVE_INFINITY;for(n=0,i=t.length;n<i;++n){var u=t[n];if(u&&u.hasValue()){var d=u.getCenterPoint(),c=r.distanceBetweenPoints(e,d);c<l&&(l=c,a=u)}}if(a){var h=a.tooltipPosition();o=h.x,s=h.y}return{x:o,y:s}}}}},{25:25,26:26,45:45}],36:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{elements:{arc:{backgroundColor:i.global.defaultColor,borderColor:"#fff",borderWidth:2}}}),e.exports=a.extend({inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,e){var n=this._view;if(n){for(var i=r.getAngleFromPoint(n,{x:t,y:e}),a=i.angle,o=i.distance,s=n.startAngle,l=n.endAngle;l<s;)l+=2*Math.PI;for(;a>l;)a-=2*Math.PI;for(;a<s;)a+=2*Math.PI;var u=a>=s&&a<=l,d=o>=n.innerRadius&&o<=n.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{25:25,26:26,45:45}],37:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45),o=i.global;i._set("global",{elements:{line:{tension:.4,backgroundColor:o.defaultColor,borderWidth:3,borderColor:o.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a=this,s=a._view,l=a._chart.ctx,u=s.spanGaps,d=a._children.slice(),c=o.elements.line,h=-1;for(a._loop&&d.length&&d.push(d[0]),l.save(),l.lineCap=s.borderCapStyle||c.borderCapStyle,l.setLineDash&&l.setLineDash(s.borderDash||c.borderDash),l.lineDashOffset=s.borderDashOffset||c.borderDashOffset,l.lineJoin=s.borderJoinStyle||c.borderJoinStyle,l.lineWidth=s.borderWidth||c.borderWidth,l.strokeStyle=s.borderColor||o.defaultColor,l.beginPath(),h=-1,t=0;t<d.length;++t)e=d[t],n=r.previousItem(d,t),i=e._view,0===t?i.skip||(l.moveTo(i.x,i.y),h=t):(n=-1===h?n:d[h],i.skip||(h!==t-1&&!u||-1===h?l.moveTo(i.x,i.y):r.canvas.lineTo(l,n._view,e._view),h=t));l.stroke(),l.restore()}})},{25:25,26:26,45:45}],38:[function(t,e,n){"use strict";function i(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hitRadius,2)}var a=t(25),r=t(26),o=t(45),s=a.global.defaultColor;a._set("global",{elements:{point:{radius:3,pointStyle:"circle",backgroundColor:s,borderColor:s,borderWidth:1,hitRadius:1,hoverRadius:4,hoverBorderWidth:1}}}),e.exports=r.extend({inRange:function(t,e){var n=this._view;return!!n&&Math.pow(t-n.x,2)+Math.pow(e-n.y,2)<Math.pow(n.hitRadius+n.radius,2)},inLabelRange:i,inXRange:i,inYRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.y,2)<Math.pow(e.radius+e.hitRadius,2)},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(t){var e=this._view,n=this._model,i=this._chart.ctx,r=e.pointStyle,l=e.radius,u=e.x,d=e.y,c=o.color,h=0;e.skip||(i.strokeStyle=e.borderColor||s,i.lineWidth=o.valueOrDefault(e.borderWidth,a.global.elements.point.borderWidth),i.fillStyle=e.backgroundColor||s,void 0!==t&&(n.x<t.left||1.01*t.right<n.x||n.y<t.top||1.01*t.bottom<n.y)&&(n.x<t.left?h=(u-n.x)/(t.left-n.x):1.01*t.right<n.x?h=(n.x-u)/(n.x-t.right):n.y<t.top?h=(d-n.y)/(t.top-n.y):1.01*t.bottom<n.y&&(h=(n.y-d)/(n.y-t.bottom)),h=Math.round(100*h)/100,i.strokeStyle=c(i.strokeStyle).alpha(h).rgbString(),i.fillStyle=c(i.fillStyle).alpha(h).rgbString()),o.canvas.drawPoint(i,r,l,u,d))}})},{25:25,26:26,45:45}],39:[function(t,e,n){"use strict";function i(t){return void 0!==t._view.width}function a(t){var e,n,a,r,o=t._view;if(i(t)){var s=o.width/2;e=o.x-s,n=o.x+s,a=Math.min(o.y,o.base),r=Math.max(o.y,o.base)}else{var l=o.height/2;e=Math.min(o.x,o.base),n=Math.max(o.x,o.base),a=o.y-l,r=o.y+l}return{left:e,top:a,right:n,bottom:r}}var r=t(25),o=t(26);r._set("global",{elements:{rectangle:{backgroundColor:r.global.defaultColor,borderColor:r.global.defaultColor,borderSkipped:"bottom",borderWidth:0}}}),e.exports=o.extend({draw:function(){function t(t){return v[(y+t)%4]}var e,n,i,a,r,o,s,l=this._chart.ctx,u=this._view,d=u.borderWidth;if(u.horizontal?(e=u.base,n=u.x,i=u.y-u.height/2,a=u.y+u.height/2,r=n>e?1:-1,o=1,s=u.borderSkipped||"left"):(e=u.x-u.width/2,n=u.x+u.width/2,i=u.y,r=1,o=(a=u.base)>i?1:-1,s=u.borderSkipped||"bottom"),d){var c=Math.min(Math.abs(e-n),Math.abs(i-a)),h=(d=d>c?c:d)/2,f=e+("left"!==s?h*r:0),g=n+("right"!==s?-h*r:0),m=i+("top"!==s?h*o:0),p=a+("bottom"!==s?-h*o:0);f!==g&&(i=m,a=p),m!==p&&(e=f,n=g)}l.beginPath(),l.fillStyle=u.backgroundColor,l.strokeStyle=u.borderColor,l.lineWidth=d;var v=[[e,a],[e,i],[n,i],[n,a]],y=["bottom","left","top","right"].indexOf(s,0);-1===y&&(y=0);var b=t(0);l.moveTo(b[0],b[1]);for(var x=1;x<4;x++)b=t(x),l.lineTo(b[0],b[1]);l.fill(),d&&l.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var n=!1;if(this._view){var i=a(this);n=t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}return n},inLabelRange:function(t,e){var n=this;if(!n._view)return!1;var r=a(n);return i(n)?t>=r.left&&t<=r.right:e>=r.top&&e<=r.bottom},inXRange:function(t){var e=a(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=a(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return i(this)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{25:25,26:26}],40:[function(t,e,n){"use strict";e.exports={},e.exports.Arc=t(36),e.exports.Line=t(37),e.exports.Point=t(38),e.exports.Rectangle=t(39)},{36:36,37:37,38:38,39:39}],41:[function(t,e,n){"use strict";var i=t(42),n=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,r){if(r){var o=Math.min(r,i/2),s=Math.min(r,a/2);t.moveTo(e+o,n),t.lineTo(e+i-o,n),t.quadraticCurveTo(e+i,n,e+i,n+s),t.lineTo(e+i,n+a-s),t.quadraticCurveTo(e+i,n+a,e+i-o,n+a),t.lineTo(e+o,n+a),t.quadraticCurveTo(e,n+a,e,n+a-s),t.lineTo(e,n+s),t.quadraticCurveTo(e,n,e+o,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a){var r,o,s,l,u,d;if("object"!=typeof e||"[object HTMLImageElement]"!==(r=e.toString())&&"[object HTMLCanvasElement]"!==r){if(!(isNaN(n)||n<=0)){switch(e){default:t.beginPath(),t.arc(i,a,n,0,2*Math.PI),t.closePath(),t.fill();break;case"triangle":t.beginPath(),u=(o=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(i-o/2,a+u/3),t.lineTo(i+o/2,a+u/3),t.lineTo(i,a-2*u/3),t.closePath(),t.fill();break;case"rect":d=1/Math.SQRT2*n,t.beginPath(),t.fillRect(i-d,a-d,2*d,2*d),t.strokeRect(i-d,a-d,2*d,2*d);break;case"rectRounded":var c=n/Math.SQRT2,h=i-c,f=a-c,g=Math.SQRT2*n;t.beginPath(),this.roundedRect(t,h,f,g,g,n/2),t.closePath(),t.fill();break;case"rectRot":d=1/Math.SQRT2*n,t.beginPath(),t.moveTo(i-d,a),t.lineTo(i,a+d),t.lineTo(i+d,a),t.lineTo(i,a-d),t.closePath(),t.fill();break;case"cross":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"crossRot":t.beginPath(),s=Math.cos(Math.PI/4)*n,l=Math.sin(Math.PI/4)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i-s,a+l),t.lineTo(i+s,a-l),t.closePath();break;case"star":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),s=Math.cos(Math.PI/4)*n,l=Math.sin(Math.PI/4)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i-s,a+l),t.lineTo(i+s,a-l),t.closePath();break;case"line":t.beginPath(),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"dash":t.beginPath(),t.moveTo(i,a),t.lineTo(i+n,a),t.closePath()}t.stroke()}}else t.drawImage(e,i-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){if(n.steppedLine)return"after"===n.steppedLine&&!i||"after"!==n.steppedLine&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}};i.clear=n.clear,i.drawRoundedRectangle=function(t){t.beginPath(),n.roundedRect.apply(n,arguments),t.closePath()}},{42:42}],42:[function(t,e,n){"use strict";var i={noop:function(){},uid:function(){var t=0;return function(){return t++}}(),isNullOrUndef:function(t){return null===t||void 0===t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return i.valueOrDefault(i.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,a){var r,o,s;if(i.isArray(t))if(o=t.length,a)for(r=o-1;r>=0;r--)e.call(n,t[r],r);else for(r=0;r<o;r++)e.call(n,t[r],r);else if(i.isObject(t))for(o=(s=Object.keys(t)).length,r=0;r<o;r++)e.call(n,t[s[r]],s[r])},arrayEquals:function(t,e){var n,a,r,o;if(!t||!e||t.length!==e.length)return!1;for(n=0,a=t.length;n<a;++n)if(r=t[n],o=e[n],r instanceof Array&&o instanceof Array){if(!i.arrayEquals(r,o))return!1}else if(r!==o)return!1;return!0},clone:function(t){if(i.isArray(t))return t.map(i.clone);if(i.isObject(t)){for(var e={},n=Object.keys(t),a=n.length,r=0;r<a;++r)e[n[r]]=i.clone(t[n[r]]);return e}return t},_merger:function(t,e,n,a){var r=e[t],o=n[t];i.isObject(r)&&i.isObject(o)?i.merge(r,o,a):e[t]=i.clone(o)},_mergerIf:function(t,e,n){var a=e[t],r=n[t];i.isObject(a)&&i.isObject(r)?i.mergeIf(a,r):e.hasOwnProperty(t)||(e[t]=i.clone(r))},merge:function(t,e,n){var a,r,o,s,l,u=i.isArray(e)?e:[e],d=u.length;if(!i.isObject(t))return t;for(a=(n=n||{}).merger||i._merger,r=0;r<d;++r)if(e=u[r],i.isObject(e))for(l=0,s=(o=Object.keys(e)).length;l<s;++l)a(o[l],t,e,n);return t},mergeIf:function(t,e){return i.merge(t,e,{merger:i._mergerIf})}};e.exports=i,i.callCallback=i.callback,i.indexOf=function(t,e,n){return Array.prototype.indexOf.call(t,e,n)},i.getValueOrDefault=i.valueOrDefault,i.getValueAtIndexOrDefault=i.valueAtIndexOrDefault},{}],43:[function(t,e,n){"use strict";var i=t(42),a={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return(t-=1)*t*t+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-((t-=1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return(t-=1)*t*t*t*t+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-a.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*a.easeInBounce(2*t):.5*a.easeOutBounce(2*t-1)+.5}};e.exports={effects:a},i.easingEffects=a},{42:42}],44:[function(t,e,n){"use strict";var i=t(42);e.exports={toLineHeight:function(t,e){var n=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!n||"normal"===n[1])return 1.2*e;switch(t=+n[2],n[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,n,a,r;return i.isObject(t)?(e=+t.top||0,n=+t.right||0,a=+t.bottom||0,r=+t.left||0):e=n=a=r=+t||0,{top:e,right:n,bottom:a,left:r,height:e+a,width:r+n}},resolve:function(t,e,n){var a,r,o;for(a=0,r=t.length;a<r;++a)if(void 0!==(o=t[a])&&(void 0!==e&&"function"==typeof o&&(o=o(e)),void 0!==n&&i.isArray(o)&&(o=o[n]),void 0!==o))return o}}},{42:42}],45:[function(t,e,n){"use strict";e.exports=t(42),e.exports.easing=t(43),e.exports.canvas=t(41),e.exports.options=t(44)},{41:41,42:42,43:43,44:44}],46:[function(t,e,n){e.exports={acquireContext:function(t){return t&&t.canvas&&(t=t.canvas),t&&t.getContext("2d")||null}}},{}],47:[function(t,e,n){"use strict";function i(t,e){var n=p.getStyle(t,e),i=n&&n.match(/^(\d+)(\.\d+)?px$/);return i?Number(i[1]):void 0}function a(t,e){var n=t.style,a=t.getAttribute("height"),r=t.getAttribute("width");if(t[v]={initial:{height:a,width:r,style:{display:n.display,height:n.height,width:n.width}}},n.display=n.display||"block",null===r||""===r){var o=i(t,"width");void 0!==o&&(t.width=o)}if(null===a||""===a)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var s=i(t,"height");void 0!==o&&(t.height=s)}return t}function r(t,e,n){t.addEventListener(e,n,w)}function o(t,e,n){t.removeEventListener(e,n,w)}function s(t,e,n,i,a){return{type:t,chart:e,native:a||null,x:void 0!==n?n:null,y:void 0!==i?i:null}}function l(t,e){var n=k[t.type]||t.type,i=p.getRelativePosition(t,e);return s(n,e,i.x,i.y,t)}function u(t,e){var n=!1,i=[];return function(){i=Array.prototype.slice.call(arguments),e=e||this,n||(n=!0,p.requestAnimFrame.call(window,function(){n=!1,t.apply(e,i)}))}}function d(t){var e=document.createElement("div"),n=y+"size-monitor",i="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;";e.style.cssText=i,e.className=n,e.innerHTML='<div class="'+n+'-expand" style="'+i+'"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="'+n+'-shrink" style="'+i+'"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div>';var a=e.childNodes[0],o=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,o.scrollLeft=1e6,o.scrollTop=1e6};var s=function(){e._reset(),t()};return r(a,"scroll",s.bind(a,"expand")),r(o,"scroll",s.bind(o,"shrink")),e}function c(t,e){var n=(t[v]||(t[v]={})).renderProxy=function(t){t.animationName===x&&e()};p.each(_,function(e){r(t,e,n)}),t.classList.add(b)}function h(t){var e=t[v]||{},n=e.renderProxy;n&&(p.each(_,function(e){o(t,e,n)}),delete e.renderProxy),t.classList.remove(b)}function f(t,e,n){var i=t[v]||(t[v]={}),a=i.resizer=d(u(function(){if(i.resizer)return e(s("resize",n))}));c(t,function(){if(i.resizer){var e=t.parentNode;e&&e!==a.parentNode&&e.insertBefore(a,e.firstChild),a._reset()}})}function g(t){var e=t[v]||{},n=e.resizer;delete e.resizer,h(t),n&&n.parentNode&&n.parentNode.removeChild(n)}function m(t,e){var n=t._style||document.createElement("style");t._style||(t._style=n,e="/* Chart.js */\n"+e,n.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(n)),n.appendChild(document.createTextNode(e))}var p=t(45),v="$chartjs",y="chartjs-",b=y+"render-monitor",x=y+"render-animation",_=["animationstart","webkitAnimationStart"],k={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},w=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t="from{opacity:0.99}to{opacity:1}";m(this,"@-webkit-keyframes "+x+"{"+t+"}@keyframes "+x+"{"+t+"}."+b+"{-webkit-animation:"+x+" 0.001s;animation:"+x+" 0.001s;}")},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(a(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e[v]){var n=e[v].initial;["height","width"].forEach(function(t){var i=n[t];p.isNullOrUndef(i)?e.removeAttribute(t):e.setAttribute(t,i)}),p.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e[v]}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=n[v]||(n[v]={});r(i,e,(a.proxies||(a.proxies={}))[t.id+"_"+e]=function(e){n(l(e,t))})}else f(i,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[v]||{}).proxies||{})[t.id+"_"+e];a&&o(i,e,a)}else g(i)}},p.addEvent=r,p.removeEvent=o},{45:45}],48:[function(t,e,n){"use strict";var i=t(45),a=t(46),r=t(47),o=r._enabled?r:a;e.exports=i.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},o)},{45:45,46:46,47:47}],49:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("global",{plugins:{filler:{propagate:!0}}}),e.exports=function(){function t(t,e,n){var i,a=t._model||{},r=a.fill;if(void 0===r&&(r=!!a.backgroundColor),!1===r||null===r)return!1;if(!0===r)return"origin";if(i=parseFloat(r,10),isFinite(i)&&Math.floor(i)===i)return"-"!==r[0]&&"+"!==r[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(r){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return r;default:return!1}}function e(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,r=null;if(isFinite(a))return null;if("start"===a?r=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?r=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?r=n.scaleZero:i.getBasePosition?r=i.getBasePosition():i.getBasePixel&&(r=i.getBasePixel()),void 0!==r&&null!==r){if(void 0!==r.x&&void 0!==r.y)return r;if("number"==typeof r&&isFinite(r))return e=i.isHorizontal(),{x:e?r:null,y:e?null:r}}return null}function n(t,e,n){var i,a=t[e].fill,r=[e];if(!n)return a;for(;!1!==a&&-1===r.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;r.push(a),a=i.fill}return!1}function o(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),d[n](t))}function s(t){return t&&!t.skip}function l(t,e,n,i,a){var o;if(i&&a){for(t.moveTo(e[0].x,e[0].y),o=1;o<i;++o)r.canvas.lineTo(t,e[o-1],e[o]);for(t.lineTo(n[a-1].x,n[a-1].y),o=a-1;o>0;--o)r.canvas.lineTo(t,n[o],n[o-1],!0)}}function u(t,e,n,i,a,r){var o,u,d,c,h,f,g,m=e.length,p=i.spanGaps,v=[],y=[],b=0,x=0;for(t.beginPath(),o=0,u=m+!!r;o<u;++o)h=n(c=e[d=o%m]._view,d,i),f=s(c),g=s(h),f&&g?(b=v.push(c),x=y.push(h)):b&&x&&(p?(f&&v.push(c),g&&y.push(h)):(l(t,v,y,b,x),b=x=0,v=[],y=[]));l(t,v,y,b,x),t.closePath(),t.fillStyle=a,t.fill()}var d={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[],r=a.length||0;return r?function(t,e){return e<r&&a[e]._view||null}:null},boundary:function(t){var e=t.boundary,n=e?e.x:null,i=e?e.y:null;return function(t){return{x:null===n?t.x:n,y:null===i?t.y:i}}}};return{id:"filler",afterDatasetsUpdate:function(i,r){var s,l,u,d,c=(i.data.datasets||[]).length,h=r.propagate,f=[];for(l=0;l<c;++l)d=null,(u=(s=i.getDatasetMeta(l)).dataset)&&u._model&&u instanceof a.Line&&(d={visible:i.isDatasetVisible(l),fill:t(u,l,c),chart:i,el:u}),s.$filler=d,f.push(d);for(l=0;l<c;++l)(d=f[l])&&(d.fill=n(f,l,h),d.boundary=e(d),d.mapper=o(d))},beforeDatasetDraw:function(t,e){var n=e.meta.$filler;if(n){var a=t.ctx,o=n.el,s=o._view,l=o._children||[],d=n.mapper,c=s.backgroundColor||i.global.defaultColor;d&&c&&l.length&&(r.canvas.clipArea(a,t.chartArea),u(a,l,d,s,c,o._loop),r.canvas.unclipArea(a))}}}}},{25:25,40:40,45:45}],50:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{legend:{display:!0,position:"top",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var n=e.datasetIndex,i=this.chart,a=i.getDatasetMeta(n);a.hidden=null===a.hidden?!i.data.datasets[n].hidden:null,i.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return r.isArray(e.datasets)?e.datasets.map(function(e,n){return{text:e.label,fillStyle:r.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hidden:!t.isDatasetVisible(n),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:n}},this):[]}}},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var n=0;n<t.data.datasets.length;n++)e.push('<li><span style="background-color:'+t.data.datasets[n].backgroundColor+'"></span>'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("</li>");return e.push("</ul>"),e.join("")}}),e.exports=function(t){function e(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}function n(e,n){var i=new t.Legend({ctx:e.ctx,options:n,chart:e});o.configure(e,i,n),o.addBox(e,i),e.legend=i}var o=t.layoutService,s=r.noop;return t.Legend=a.extend({initialize:function(t){r.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:s,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:s,beforeSetDimensions:s,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:s,beforeBuildLabels:s,buildLabels:function(){var t=this,e=t.options.labels||{},n=r.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:s,beforeFit:s,fit:function(){var t=this,n=t.options,a=n.labels,o=n.display,s=t.ctx,l=i.global,u=r.valueOrDefault,d=u(a.fontSize,l.defaultFontSize),c=u(a.fontStyle,l.defaultFontStyle),h=u(a.fontFamily,l.defaultFontFamily),f=r.fontString(d,c,h),g=t.legendHitBoxes=[],m=t.minSize,p=t.isHorizontal();if(p?(m.width=t.maxWidth,m.height=o?10:0):(m.width=o?10:0,m.height=t.maxHeight),o)if(s.font=f,p){var v=t.lineWidths=[0],y=t.legendItems.length?d+a.padding:0;s.textAlign="left",s.textBaseline="top",r.each(t.legendItems,function(n,i){var r=e(a,d)+d/2+s.measureText(n.text).width;v[v.length-1]+r+a.padding>=t.width&&(y+=d+a.padding,v[v.length]=t.left),g[i]={left:0,top:0,width:r,height:d},v[v.length-1]+=r+a.padding}),m.height+=y}else{var b=a.padding,x=t.columnWidths=[],_=a.padding,k=0,w=0,M=d+b;r.each(t.legendItems,function(t,n){var i=e(a,d)+d/2+s.measureText(t.text).width;w+M>m.height&&(_+=k+a.padding,x.push(k),k=0,w=0),k=Math.max(k,i),w+=M,g[n]={left:0,top:0,width:i,height:d}}),_+=k,x.push(k),m.width+=_}t.width=m.width,t.height=m.height},afterFit:s,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,n=t.options,a=n.labels,o=i.global,s=o.elements.line,l=t.width,u=t.lineWidths;if(n.display){var d,c=t.ctx,h=r.valueOrDefault,f=h(a.fontColor,o.defaultFontColor),g=h(a.fontSize,o.defaultFontSize),m=h(a.fontStyle,o.defaultFontStyle),p=h(a.fontFamily,o.defaultFontFamily),v=r.fontString(g,m,p);c.textAlign="left",c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=v;var y=e(a,g),b=t.legendHitBoxes,x=function(t,e,i){if(!(isNaN(y)||y<=0)){c.save(),c.fillStyle=h(i.fillStyle,o.defaultColor),c.lineCap=h(i.lineCap,s.borderCapStyle),c.lineDashOffset=h(i.lineDashOffset,s.borderDashOffset),c.lineJoin=h(i.lineJoin,s.borderJoinStyle),c.lineWidth=h(i.lineWidth,s.borderWidth),c.strokeStyle=h(i.strokeStyle,o.defaultColor);var a=0===h(i.lineWidth,s.borderWidth);if(c.setLineDash&&c.setLineDash(h(i.lineDash,s.borderDash)),n.labels&&n.labels.usePointStyle){var l=g*Math.SQRT2/2,u=l/Math.SQRT2,d=t+u,f=e+u;r.canvas.drawPoint(c,i.pointStyle,l,d,f)}else a||c.strokeRect(t,e,y,g),c.fillRect(t,e,y,g);c.restore()}},_=function(t,e,n,i){var a=g/2,r=y+a+t,o=e+a;c.fillText(n.text,r,o),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(r,o),c.lineTo(r+i,o),c.stroke())},k=t.isHorizontal();d=k?{x:t.left+(l-u[0])/2,y:t.top+a.padding,line:0}:{x:t.left+a.padding,y:t.top+a.padding,line:0};var w=g+a.padding;r.each(t.legendItems,function(e,n){var i=c.measureText(e.text).width,r=y+g/2+i,o=d.x,s=d.y;k?o+r>=l&&(s=d.y+=w,d.line++,o=d.x=t.left+(l-u[d.line])/2):s+w>t.bottom&&(o=d.x=o+t.columnWidths[d.line]+a.padding,s=d.y=t.top+a.padding,d.line++),x(o,s,e),b[n].left=o,b[n].top=s,_(o,s,e,i),k?d.x+=r+a.padding:d.y+=w})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var r=t.x,o=t.y;if(r>=e.left&&r<=e.right&&o>=e.top&&o<=e.bottom)for(var s=e.legendHitBoxes,l=0;l<s.length;++l){var u=s[l];if(r>=u.left&&r<=u.left+u.width&&o>=u.top&&o<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[l]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[l]),a=!0;break}}}return a}}),{id:"legend",beforeInit:function(t){var e=t.options.legend;e&&n(t,e)},beforeUpdate:function(t){var e=t.options.legend,a=t.legend;e?(r.mergeIf(e,i.global.legend),a?(o.configure(t,a,e),a.options=e):n(t,e)):a&&(o.removeBox(t,a),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}}},{25:25,26:26,45:45}],51:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}}),e.exports=function(t){function e(e,i){var a=new t.Title({ctx:e.ctx,options:i,chart:e});n.configure(e,a,i),n.addBox(e,a),e.titleBlock=a}var n=t.layoutService,o=r.noop;return t.Title=a.extend({initialize:function(t){var e=this;r.extend(e,t),e.legendHitBoxes=[]},beforeUpdate:o,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:o,beforeSetDimensions:o,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:o,beforeBuildLabels:o,buildLabels:o,afterBuildLabels:o,beforeFit:o,fit:function(){var t=this,e=r.valueOrDefault,n=t.options,a=n.display,o=e(n.fontSize,i.global.defaultFontSize),s=t.minSize,l=r.isArray(n.text)?n.text.length:1,u=r.options.toLineHeight(n.lineHeight,o),d=a?l*u+2*n.padding:0;t.isHorizontal()?(s.width=t.maxWidth,s.height=d):(s.width=d,s.height=t.maxHeight),t.width=s.width,t.height=s.height},afterFit:o,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=r.valueOrDefault,a=t.options,o=i.global;if(a.display){var s,l,u,d=n(a.fontSize,o.defaultFontSize),c=n(a.fontStyle,o.defaultFontStyle),h=n(a.fontFamily,o.defaultFontFamily),f=r.fontString(d,c,h),g=r.options.toLineHeight(a.lineHeight,d),m=g/2+a.padding,p=0,v=t.top,y=t.left,b=t.bottom,x=t.right;e.fillStyle=n(a.fontColor,o.defaultFontColor),e.font=f,t.isHorizontal()?(l=y+(x-y)/2,u=v+m,s=x-y):(l="left"===a.position?y+m:x-m,u=v+(b-v)/2,s=b-v,p=Math.PI*("left"===a.position?-.5:.5)),e.save(),e.translate(l,u),e.rotate(p),e.textAlign="center",e.textBaseline="middle";var _=a.text;if(r.isArray(_))for(var k=0,w=0;w<_.length;++w)e.fillText(_[w],0,k,s),k+=g;else e.fillText(_,0,0,s);e.restore()}}}),{id:"title",beforeInit:function(t){var n=t.options.title;n&&e(t,n)},beforeUpdate:function(a){var o=a.options.title,s=a.titleBlock;o?(r.mergeIf(o,i.global.title),s?(n.configure(a,s,o),s.options=o):e(a,o)):s&&(t.layoutService.removeBox(a,s),delete a.titleBlock)}}}},{25:25,26:26,45:45}],52:[function(t,e,n){"use strict";e.exports=function(t){var e={position:"bottom"},n=t.Scale.extend({getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t=this,e=t.getLabels();t.minIndex=0,t.maxIndex=e.length-1;var n;void 0!==t.options.ticks.min&&(n=e.indexOf(t.options.ticks.min),t.minIndex=-1!==n?n:t.minIndex),void 0!==t.options.ticks.max&&(n=e.indexOf(t.options.ticks.max),t.maxIndex=-1!==n?n:t.maxIndex),t.min=e[t.minIndex],t.max=e[t.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.isHorizontal();return i.yLabels&&!a?n.getRightValue(i.datasets[e].data[t]):n.ticks[t-n.minIndex]},getPixelForValue:function(t,e){var n,i=this,a=i.options.offset,r=Math.max(i.maxIndex+1-i.minIndex-(a?0:1),1);if(void 0!==t&&null!==t&&(n=i.isHorizontal()?t.x:t.y),void 0!==n||void 0!==t&&isNaN(e)){var o=i.getLabels();t=n||t;var s=o.indexOf(t);e=-1!==s?s:e}if(i.isHorizontal()){var l=i.width/r,u=l*(e-i.minIndex);return a&&(u+=l/2),i.left+Math.round(u)}var d=i.height/r,c=d*(e-i.minIndex);return a&&(c+=d/2),i.top+Math.round(c)},getPixelForTick:function(t){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null)},getValueForPixel:function(t){var e=this,n=e.options.offset,i=Math.max(e._ticks.length-(n?0:1),1),a=e.isHorizontal(),r=(a?e.width:e.height)/i;return t-=a?e.left:e.top,n&&(t-=r/2),(t<=0?0:Math.round(t/r))+e.minIndex},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType("category",n,e)}},{}],53:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:r.formatters.linear}},n=t.LinearScaleBase.extend({determineDataLimits:function(){function t(t){return o?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,i=e.chart,r=i.data.datasets,o=e.isHorizontal();e.min=null,e.max=null;var s=n.stacked;if(void 0===s&&a.each(r,function(e,n){if(!s){var a=i.getDatasetMeta(n);i.isDatasetVisible(n)&&t(a)&&void 0!==a.stack&&(s=!0)}}),n.stacked||s){var l={};a.each(r,function(r,o){var s=i.getDatasetMeta(o),u=[s.type,void 0===n.stacked&&void 0===s.stack?o:"",s.stack].join(".");void 0===l[u]&&(l[u]={positiveValues:[],negativeValues:[]});var d=l[u].positiveValues,c=l[u].negativeValues;i.isDatasetVisible(o)&&t(s)&&a.each(r.data,function(t,i){var a=+e.getRightValue(t);isNaN(a)||s.data[i].hidden||(d[i]=d[i]||0,c[i]=c[i]||0,n.relativePoints?d[i]=100:a<0?c[i]+=a:d[i]+=a)})}),a.each(l,function(t){var n=t.positiveValues.concat(t.negativeValues),i=a.min(n),r=a.max(n);e.min=null===e.min?i:Math.min(e.min,i),e.max=null===e.max?r:Math.max(e.max,r)})}else a.each(r,function(n,r){var o=i.getDatasetMeta(r);i.isDatasetVisible(r)&&t(o)&&a.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||o.data[n].hidden||(null===e.min?e.min=i:i<e.min&&(e.min=i),null===e.max?e.max=i:i>e.max&&(e.max=i))})});e.min=isFinite(e.min)&&!isNaN(e.min)?e.min:0,e.max=isFinite(e.max)&&!isNaN(e.max)?e.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this,n=e.options.ticks;if(e.isHorizontal())t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.width/50));else{var r=a.valueOrDefault(n.fontSize,i.global.defaultFontSize);t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.height/(2*r)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e,n=this,i=n.start,a=+n.getRightValue(t),r=n.end-i;return n.isHorizontal()?(e=n.left+n.width/r*(a-i),Math.round(e)):(e=n.bottom-n.height/r*(a-i),Math.round(e))},getValueForPixel:function(t){var e=this,n=e.isHorizontal(),i=n?e.width:e.height,a=(n?t-e.left:e.bottom-t)/i;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",n,e)}},{25:25,34:34,45:45}],54:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e=i.noop;t.LinearScaleBase=t.Scale.extend({getRightValue:function(e){return"string"==typeof e?+e:t.Scale.prototype.getRightValue.call(this,e)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=i.sign(t.min),a=i.sign(t.max);n<0&&a<0?t.max=0:n>0&&a>0&&(t.min=0)}var r=void 0!==e.min||void 0!==e.suggestedMin,o=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),r!==o&&t.min>=t.max&&(r?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),r={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,stepSize:i.valueOrDefault(e.fixedStepSize,e.stepSize)},o=t.ticks=a.generators.linear(r,t);t.handleDirectionalChanges(),t.max=i.max(o),t.min=i.min(o),e.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{34:34,45:45}],55:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:a.formatters.logarithmic}},n=t.Scale.extend({determineDataLimits:function(){function t(t){return l?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,a=n.ticks,r=e.chart,o=r.data.datasets,s=i.valueOrDefault,l=e.isHorizontal();e.min=null,e.max=null,e.minNotZero=null;var u=n.stacked;if(void 0===u&&i.each(o,function(e,n){if(!u){var i=r.getDatasetMeta(n);r.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(u=!0)}}),n.stacked||u){var d={};i.each(o,function(a,o){var s=r.getDatasetMeta(o),l=[s.type,void 0===n.stacked&&void 0===s.stack?o:"",s.stack].join(".");r.isDatasetVisible(o)&&t(s)&&(void 0===d[l]&&(d[l]=[]),i.each(a.data,function(t,i){var a=d[l],r=+e.getRightValue(t);isNaN(r)||s.data[i].hidden||(a[i]=a[i]||0,n.relativePoints?a[i]=100:a[i]+=r)}))}),i.each(d,function(t){var n=i.min(t),a=i.max(t);e.min=null===e.min?n:Math.min(e.min,n),e.max=null===e.max?a:Math.max(e.max,a)})}else i.each(o,function(n,a){var o=r.getDatasetMeta(a);r.isDatasetVisible(a)&&t(o)&&i.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||o.data[n].hidden||(null===e.min?e.min=i:i<e.min&&(e.min=i),null===e.max?e.max=i:i>e.max&&(e.max=i),0!==i&&(null===e.minNotZero||i<e.minNotZero)&&(e.minNotZero=i))})});e.min=s(a.min,e.min),e.max=s(a.max,e.max),e.min===e.max&&(0!==e.min&&null!==e.min?(e.min=Math.pow(10,Math.floor(i.log10(e.min))-1),e.max=Math.pow(10,Math.floor(i.log10(e.max))+1)):(e.min=1,e.max=10))},buildTicks:function(){var t=this,e=t.options.ticks,n={min:e.min,max:e.max},r=t.ticks=a.generators.logarithmic(n,t);t.isHorizontal()||r.reverse(),t.max=i.max(r),t.min=i.min(r),e.reverse?(r.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},getPixelForValue:function(t){var e,n,a,r=this,o=r.start,s=+r.getRightValue(t),l=r.options.ticks;return r.isHorizontal()?(a=i.log10(r.end)-i.log10(o),0===s?n=r.left:(e=r.width,n=r.left+e/a*(i.log10(s)-i.log10(o)))):(e=r.height,0!==o||l.reverse?0===r.end&&l.reverse?(a=i.log10(r.start)-i.log10(r.minNotZero),n=s===r.end?r.top:s===r.minNotZero?r.top+.02*e:r.top+.02*e+.98*e/a*(i.log10(s)-i.log10(r.minNotZero))):0===s?n=l.reverse?r.top:r.bottom:(a=i.log10(r.end)-i.log10(o),e=r.height,n=r.bottom-e/a*(i.log10(s)-i.log10(o))):(a=i.log10(r.end)-i.log10(r.minNotZero),n=s===o?r.bottom:s===r.minNotZero?r.bottom-.02*e:r.bottom-.02*e-.98*e/a*(i.log10(s)-i.log10(r.minNotZero)))),n},getValueForPixel:function(t){var e,n,a=this,r=i.log10(a.end)-i.log10(a.start);return a.isHorizontal()?(n=a.width,e=a.start*Math.pow(10,(t-a.left)*r/n)):(n=a.height,e=Math.pow(10,(a.bottom-t)*r/n)/a.start),e}});t.scaleService.registerScaleType("logarithmic",n,e)}},{34:34,45:45}],56:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(34);e.exports=function(t){function e(t){var e=t.options;return e.angleLines.display||e.pointLabels.display?t.chart.data.labels.length:0}function n(t){var e=t.options.pointLabels,n=a.valueOrDefault(e.fontSize,p.defaultFontSize),i=a.valueOrDefault(e.fontStyle,p.defaultFontStyle),r=a.valueOrDefault(e.fontFamily,p.defaultFontFamily);return{size:n,style:i,family:r,font:a.fontString(n,i,r)}}function o(t,e,n){return a.isArray(n)?{w:a.longestText(t,t.font,n),h:n.length*e+1.5*(n.length-1)*e}:{w:t.measureText(n).width,h:e}}function s(t,e,n,i,a){return t===i||t===a?{start:e-n/2,end:e+n/2}:t<i||t>a?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function l(t){var i,r,l,u=n(t),d=Math.min(t.height/2,t.width/2),c={r:t.width,l:0,t:t.height,b:0},h={};t.ctx.font=u.font,t._pointLabelSizes=[];var f=e(t);for(i=0;i<f;i++){l=t.getPointPosition(i,d),r=o(t.ctx,u.size,t.pointLabels[i]||""),t._pointLabelSizes[i]=r;var g=t.getIndexAngle(i),m=a.toDegrees(g)%360,p=s(m,l.x,r.w,0,180),v=s(m,l.y,r.h,90,270);p.start<c.l&&(c.l=p.start,h.l=g),p.end>c.r&&(c.r=p.end,h.r=g),v.start<c.t&&(c.t=v.start,h.t=g),v.end>c.b&&(c.b=v.end,h.b=g)}t.setReductions(d,c,h)}function u(t){var e=Math.min(t.height/2,t.width/2);t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0)}function d(t){return 0===t||180===t?"center":t<180?"left":"right"}function c(t,e,n,i){if(a.isArray(e))for(var r=n.y,o=1.5*i,s=0;s<e.length;++s)t.fillText(e[s],n.x,r),r+=o;else t.fillText(e,n.x,n.y)}function h(t,e,n){90===t||270===t?n.y-=e.h/2:(t>270||t<90)&&(n.y-=e.h)}function f(t){var i=t.ctx,r=a.valueOrDefault,o=t.options,s=o.angleLines,l=o.pointLabels;i.lineWidth=s.lineWidth,i.strokeStyle=s.color;var u=t.getDistanceFromCenterForValue(o.ticks.reverse?t.min:t.max),f=n(t);i.textBaseline="top";for(var g=e(t)-1;g>=0;g--){if(s.display){var m=t.getPointPosition(g,u);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(m.x,m.y),i.stroke(),i.closePath()}if(l.display){var v=t.getPointPosition(g,u+5),y=r(l.fontColor,p.defaultFontColor);i.font=f.font,i.fillStyle=y;var b=t.getIndexAngle(g),x=a.toDegrees(b);i.textAlign=d(x),h(x,t._pointLabelSizes[g],v),c(i,t.pointLabels[g]||"",v,f.size)}}}function g(t,n,i,r){var o=t.ctx;if(o.strokeStyle=a.valueAtIndexOrDefault(n.color,r-1),o.lineWidth=a.valueAtIndexOrDefault(n.lineWidth,r-1),t.options.gridLines.circular)o.beginPath(),o.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),o.closePath(),o.stroke();else{var s=e(t);if(0===s)return;o.beginPath();var l=t.getPointPosition(0,i);o.moveTo(l.x,l.y);for(var u=1;u<s;u++)l=t.getPointPosition(u,i),o.lineTo(l.x,l.y);o.closePath(),o.stroke()}}function m(t){return a.isNumber(t)?t:0}var p=i.global,v={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:r.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}},y=t.LinearScaleBase.extend({setDimensions:function(){var t=this,e=t.options,n=e.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var i=a.min([t.height,t.width]),r=a.valueOrDefault(n.fontSize,p.defaultFontSize);t.drawingArea=e.display?i/2-(r/2+n.backdropPaddingY):i/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;a.each(e.data.datasets,function(r,o){if(e.isDatasetVisible(o)){var s=e.getDatasetMeta(o);a.each(r.data,function(e,a){var r=+t.getRightValue(e);isNaN(r)||s.data[a].hidden||(n=Math.min(r,n),i=Math.max(r,i))})}}),t.min=n===Number.POSITIVE_INFINITY?0:n,t.max=i===Number.NEGATIVE_INFINITY?0:i,t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,e=a.valueOrDefault(t.fontSize,p.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*e)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){this.options.pointLabels.display?l(this):u(this)},setReductions:function(t,e,n){var i=this,a=e.l/Math.sin(n.l),r=Math.max(e.r-i.width,0)/Math.sin(n.r),o=-e.t/Math.cos(n.t),s=-Math.max(e.b-i.height,0)/Math.cos(n.b);a=m(a),r=m(r),o=m(o),s=m(s),i.drawingArea=Math.min(Math.round(t-(a+r)/2),Math.round(t-(o+s)/2)),i.setCenterPoint(a,r,o,s)},setCenterPoint:function(t,e,n,i){var a=this,r=a.width-e-a.drawingArea,o=t+a.drawingArea,s=n+a.drawingArea,l=a.height-i-a.drawingArea;a.xCenter=Math.round((o+r)/2+a.left),a.yCenter=Math.round((s+l)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/e(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var n=e.drawingArea/(e.max-e.min);return e.options.ticks.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this,i=n.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(i)*e)+n.xCenter,y:Math.round(Math.sin(i)*e)+n.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,n=t.max;return t.getPointPositionForValue(0,t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0)},draw:function(){var t=this,e=t.options,n=e.gridLines,i=e.ticks,r=a.valueOrDefault;if(e.display){var o=t.ctx,s=this.getIndexAngle(0),l=r(i.fontSize,p.defaultFontSize),u=r(i.fontStyle,p.defaultFontStyle),d=r(i.fontFamily,p.defaultFontFamily),c=a.fontString(l,u,d);a.each(t.ticks,function(e,a){if(a>0||i.reverse){var u=t.getDistanceFromCenterForValue(t.ticksAsNumbers[a]);if(n.display&&0!==a&&g(t,n,u,a),i.display){var d=r(i.fontColor,p.defaultFontColor);if(o.font=c,o.save(),o.translate(t.xCenter,t.yCenter),o.rotate(s),i.showLabelBackdrop){var h=o.measureText(e).width;o.fillStyle=i.backdropColor,o.fillRect(-h/2-i.backdropPaddingX,-u-l/2-i.backdropPaddingY,h+2*i.backdropPaddingX,l+2*i.backdropPaddingY)}o.textAlign="center",o.textBaseline="middle",o.fillStyle=d,o.fillText(e,0,-u),o.restore()}}}),(e.angleLines.display||e.pointLabels.display)&&f(t)}}});t.scaleService.registerScaleType("radialLinear",y,v)}},{25:25,34:34,45:45}],57:[function(t,e,n){"use strict";function i(t,e){return t-e}function a(t){var e,n,i,a={},r=[];for(e=0,n=t.length;e<n;++e)a[i=t[e]]||(a[i]=!0,r.push(i));return r}function r(t,e,n,i){if("linear"===i||!t.length)return[{time:e,pos:0},{time:n,pos:1}];var a,r,o,s,l,u=[],d=[e];for(a=0,r=t.length;a<r;++a)(s=t[a])>e&&s<n&&d.push(s);for(d.push(n),a=0,r=d.length;a<r;++a)l=d[a+1],o=d[a-1],s=d[a],void 0!==o&&void 0!==l&&Math.round((l+o)/2)===s||u.push({time:s,pos:a/(r-1)});return u}function o(t,e,n){for(var i,a,r,o=0,s=t.length-1;o>=0&&o<=s;){if(i=o+s>>1,a=t[i-1]||null,r=t[i],!a)return{lo:null,hi:r};if(r[e]<n)o=i+1;else{if(!(a[e]>n))return{lo:a,hi:r};s=i-1}}return{lo:r,hi:null}}function s(t,e,n,i){var a=o(t,e,n),r=a.lo?a.hi?a.lo:t[t.length-2]:t[0],s=a.lo?a.hi?a.hi:t[t.length-1]:t[1],l=s[e]-r[e],u=l?(n-r[e])/l:0,d=(s[i]-r[i])*u;return r[i]+d}function l(t,e){var n=e.parser,i=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof i?p(t,i):(t instanceof p||(t=p(t)),t.isValid()?t:"function"==typeof i?i(t):t)}function u(t,e){if(y.isNullOrUndef(t))return null;var n=e.options.time,i=l(e.getRightValue(t),n);return i.isValid()?(n.round&&i.startOf(n.round),i.valueOf()):null}function d(t,e,n,i){var a,r,o,s=e-t,l=_[n],u=l.size,d=l.steps;if(!d)return Math.ceil(s/((i||1)*u));for(a=0,r=d.length;a<r&&(o=d[a],!(Math.ceil(s/(u*o))<=i));++a);return o}function c(t,e,n,i){var a,r,o,s=k.length;for(a=k.indexOf(t);a<s-1;++a)if(r=_[k[a]],o=r.steps?r.steps[r.steps.length-1]:x,Math.ceil((n-e)/(o*r.size))<=i)return k[a];return k[s-1]}function h(t){for(var e=k.indexOf(t)+1,n=k.length;e<n;++e)if(_[k[e]].major)return k[e]}function f(t,e,n,i,a,r){var o,s=r.time,l=y.valueOrDefault(s.stepSize,s.unitStepSize),u="week"===n&&s.isoWeekday,c=r.ticks.major.enabled,h=_[n],f=p(t),g=p(e),m=[];for(l||(l=d(t,e,n,a)),u&&(f=f.isoWeekday(u),g=g.isoWeekday(u)),f=f.startOf(u?"day":n),(g=g.startOf(u?"day":n))<e&&g.add(1,n),o=p(f),c&&i&&!u&&!s.round&&(o.startOf(i),o.add(~~((f-o)/(h.size*l))*l,n));o<g;o.add(l,n))m.push(+o);return m.push(+o),m}function g(t,e,n,i,a){var r,o,l=0,u=0;return a.offset&&e.length&&(a.time.min||(r=e.length>1?e[1]:i,o=e[0],l=(s(t,"time",r,"pos")-s(t,"time",o,"pos"))/2),a.time.max||(r=e[e.length-1],o=e.length>1?e[e.length-2]:n,u=(s(t,"time",r,"pos")-s(t,"time",o,"pos"))/2)),{left:l,right:u}}function m(t,e){var n,i,a,r,o=[];for(n=0,i=t.length;n<i;++n)a=t[n],r=!!e&&a===+p(a).startOf(e),o.push({value:a,major:r});return o}var p=t(6);p="function"==typeof p?p:window.moment;var v=t(25),y=t(45),b=Number.MIN_SAFE_INTEGER||-9007199254740991,x=Number.MAX_SAFE_INTEGER||9007199254740991,_={millisecond:{major:!0,size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{major:!0,size:1e3,steps:[1,2,5,10,30]},minute:{major:!0,size:6e4,steps:[1,2,5,10,30]},hour:{major:!0,size:36e5,steps:[1,2,3,6,12]},day:{major:!0,size:864e5,steps:[1,2,5]},week:{major:!1,size:6048e5,steps:[1,2,3,4]},month:{major:!0,size:2628e6,steps:[1,2,3]},quarter:{major:!1,size:7884e6,steps:[1,2,3,4]},year:{major:!0,size:3154e7}},k=Object.keys(_);e.exports=function(t){var e={position:"bottom",distribution:"linear",bounds:"data",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}},n=t.Scale.extend({initialize:function(){if(!p)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");this.mergeTicksOptions(),t.Scale.prototype.initialize.call(this)},update:function(){var e=this,n=e.options;return n.time&&n.time.format&&console.warn("options.time.format is deprecated and replaced by options.time.parser."),t.Scale.prototype.update.apply(e,arguments)},getRightValue:function(e){return e&&void 0!==e.t&&(e=e.t),t.Scale.prototype.getRightValue.call(this,e)},determineDataLimits:function(){var t,e,n,r,o,s,l=this,d=l.chart,c=l.options.time,h=u(c.min,l)||x,f=u(c.max,l)||b,g=[],m=[],v=[];for(t=0,n=d.data.labels.length;t<n;++t)v.push(u(d.data.labels[t],l));for(t=0,n=(d.data.datasets||[]).length;t<n;++t)if(d.isDatasetVisible(t))if(o=d.data.datasets[t].data,y.isObject(o[0]))for(m[t]=[],e=0,r=o.length;e<r;++e)s=u(o[e],l),g.push(s),m[t][e]=s;else g.push.apply(g,v),m[t]=v.slice(0);else m[t]=[];v.length&&(v=a(v).sort(i),h=Math.min(h,v[0]),f=Math.max(f,v[v.length-1])),g.length&&(g=a(g).sort(i),h=Math.min(h,g[0]),f=Math.max(f,g[g.length-1])),h=h===x?+p().startOf("day"):h,f=f===b?+p().endOf("day")+1:f,l.min=Math.min(h,f),l.max=Math.max(h+1,f),l._horizontal=l.isHorizontal(),l._table=[],l._timestamps={data:g,datasets:m,labels:v}},buildTicks:function(){var t,e,n,i=this,a=i.min,o=i.max,s=i.options,l=s.time,d=l.displayFormats,p=i.getLabelCapacity(a),v=l.unit||c(l.minUnit,a,o,p),y=h(v),b=[],x=[];switch(s.ticks.source){case"data":b=i._timestamps.data;break;case"labels":b=i._timestamps.labels;break;case"auto":default:b=f(a,o,v,y,p,s)}for("ticks"===s.bounds&&b.length&&(a=b[0],o=b[b.length-1]),a=u(l.min,i)||a,o=u(l.max,i)||o,t=0,e=b.length;t<e;++t)(n=b[t])>=a&&n<=o&&x.push(n);return i.min=a,i.max=o,i._unit=v,i._majorUnit=y,i._minorFormat=d[v],i._majorFormat=d[y],i._table=r(i._timestamps.data,a,o,s.distribution),i._offsets=g(i._table,x,a,o,s),m(x,y)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.options.time,r=i.labels&&t<i.labels.length?i.labels[t]:"",o=i.datasets[e].data[t];return y.isObject(o)&&(r=n.getRightValue(o)),a.tooltipFormat&&(r=l(r,a).format(a.tooltipFormat)),r},tickFormatFunction:function(t,e,n){var i=this,a=i.options,r=t.valueOf(),o=i._majorUnit,s=i._majorFormat,l=t.clone().startOf(i._majorUnit).valueOf(),u=a.ticks.major,d=u.enabled&&o&&s&&r===l,c=t.format(d?s:i._minorFormat),h=d?u:a.ticks.minor,f=y.valueOrDefault(h.callback,h.userCallback);return f?f(c,e,n):c},convertTicksToLabels:function(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(this.tickFormatFunction(p(t[e].value),e,t));return i},getPixelForOffset:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=s(e._table,"time",t,"pos");return i+n*(e._offsets.left+a)/(e._offsets.left+1+e._offsets.right)},getPixelForValue:function(t,e,n){var i=this,a=null;if(void 0!==e&&void 0!==n&&(a=i._timestamps.datasets[n][e]),null===a&&(a=u(t,i)),null!==a)return i.getPixelForOffset(a)},getPixelForTick:function(t){var e=this.getTicks();return t>=0&&t<e.length?this.getPixelForOffset(e[t].value):null},getValueForPixel:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=(n?(t-i)/n:0)*(e._offsets.left+1+e._offsets.left)-e._offsets.right,r=s(e._table,"pos",a,"time");return p(r)},getLabelWidth:function(t){var e=this,n=e.options.ticks,i=e.ctx.measureText(t).width,a=y.toRadians(n.maxRotation),r=Math.cos(a),o=Math.sin(a);return i*r+y.valueOrDefault(n.fontSize,v.global.defaultFontSize)*o},getLabelCapacity:function(t){var e=this;e._minorFormat=e.options.time.displayFormats.millisecond;var n=e.tickFormatFunction(p(t),0,[]),i=e.getLabelWidth(n),a=e.isHorizontal()?e.width:e.height;return Math.floor(a/i)}});t.scaleService.registerScaleType("time",n,e)}},{25:25,45:45,6:6}]},{},[7])(7)});
includes/assets/js/uncompressed/jQuery-Chart/Chart.bundle.js ADDED
@@ -0,0 +1,18494 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Chart.js
3
+ * http://chartjs.org/
4
+ * Version: 2.7.0
5
+ *
6
+ * Copyright 2017 Nick Downie
7
+ * Released under the MIT license
8
+ * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
9
+ */
10
+ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Chart = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
11
+ /* MIT license */
12
+ var colorNames = require(5);
13
+
14
+ module.exports = {
15
+ getRgba: getRgba,
16
+ getHsla: getHsla,
17
+ getRgb: getRgb,
18
+ getHsl: getHsl,
19
+ getHwb: getHwb,
20
+ getAlpha: getAlpha,
21
+
22
+ hexString: hexString,
23
+ rgbString: rgbString,
24
+ rgbaString: rgbaString,
25
+ percentString: percentString,
26
+ percentaString: percentaString,
27
+ hslString: hslString,
28
+ hslaString: hslaString,
29
+ hwbString: hwbString,
30
+ keyword: keyword
31
+ }
32
+
33
+ function getRgba(string) {
34
+ if (!string) {
35
+ return;
36
+ }
37
+ var abbr = /^#([a-fA-F0-9]{3})$/i,
38
+ hex = /^#([a-fA-F0-9]{6})$/i,
39
+ rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,
40
+ per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,
41
+ keyword = /(\w+)/;
42
+
43
+ var rgb = [0, 0, 0],
44
+ a = 1,
45
+ match = string.match(abbr);
46
+ if (match) {
47
+ match = match[1];
48
+ for (var i = 0; i < rgb.length; i++) {
49
+ rgb[i] = parseInt(match[i] + match[i], 16);
50
+ }
51
+ }
52
+ else if (match = string.match(hex)) {
53
+ match = match[1];
54
+ for (var i = 0; i < rgb.length; i++) {
55
+ rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16);
56
+ }
57
+ }
58
+ else if (match = string.match(rgba)) {
59
+ for (var i = 0; i < rgb.length; i++) {
60
+ rgb[i] = parseInt(match[i + 1]);
61
+ }
62
+ a = parseFloat(match[4]);
63
+ }
64
+ else if (match = string.match(per)) {
65
+ for (var i = 0; i < rgb.length; i++) {
66
+ rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55);
67
+ }
68
+ a = parseFloat(match[4]);
69
+ }
70
+ else if (match = string.match(keyword)) {
71
+ if (match[1] == "transparent") {
72
+ return [0, 0, 0, 0];
73
+ }
74
+ rgb = colorNames[match[1]];
75
+ if (!rgb) {
76
+ return;
77
+ }
78
+ }
79
+
80
+ for (var i = 0; i < rgb.length; i++) {
81
+ rgb[i] = scale(rgb[i], 0, 255);
82
+ }
83
+ if (!a && a != 0) {
84
+ a = 1;
85
+ }
86
+ else {
87
+ a = scale(a, 0, 1);
88
+ }
89
+ rgb[3] = a;
90
+ return rgb;
91
+ }
92
+
93
+ function getHsla(string) {
94
+ if (!string) {
95
+ return;
96
+ }
97
+ var hsl = /^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/;
98
+ var match = string.match(hsl);
99
+ if (match) {
100
+ var alpha = parseFloat(match[4]);
101
+ var h = scale(parseInt(match[1]), 0, 360),
102
+ s = scale(parseFloat(match[2]), 0, 100),
103
+ l = scale(parseFloat(match[3]), 0, 100),
104
+ a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);
105
+ return [h, s, l, a];
106
+ }
107
+ }
108
+
109
+ function getHwb(string) {
110
+ if (!string) {
111
+ return;
112
+ }
113
+ var hwb = /^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/;
114
+ var match = string.match(hwb);
115
+ if (match) {
116
+ var alpha = parseFloat(match[4]);
117
+ var h = scale(parseInt(match[1]), 0, 360),
118
+ w = scale(parseFloat(match[2]), 0, 100),
119
+ b = scale(parseFloat(match[3]), 0, 100),
120
+ a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);
121
+ return [h, w, b, a];
122
+ }
123
+ }
124
+
125
+ function getRgb(string) {
126
+ var rgba = getRgba(string);
127
+ return rgba && rgba.slice(0, 3);
128
+ }
129
+
130
+ function getHsl(string) {
131
+ var hsla = getHsla(string);
132
+ return hsla && hsla.slice(0, 3);
133
+ }
134
+
135
+ function getAlpha(string) {
136
+ var vals = getRgba(string);
137
+ if (vals) {
138
+ return vals[3];
139
+ }
140
+ else if (vals = getHsla(string)) {
141
+ return vals[3];
142
+ }
143
+ else if (vals = getHwb(string)) {
144
+ return vals[3];
145
+ }
146
+ }
147
+
148
+ // generators
149
+ function hexString(rgb) {
150
+ return "#" + hexDouble(rgb[0]) + hexDouble(rgb[1])
151
+ + hexDouble(rgb[2]);
152
+ }
153
+
154
+ function rgbString(rgba, alpha) {
155
+ if (alpha < 1 || (rgba[3] && rgba[3] < 1)) {
156
+ return rgbaString(rgba, alpha);
157
+ }
158
+ return "rgb(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ")";
159
+ }
160
+
161
+ function rgbaString(rgba, alpha) {
162
+ if (alpha === undefined) {
163
+ alpha = (rgba[3] !== undefined ? rgba[3] : 1);
164
+ }
165
+ return "rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2]
166
+ + ", " + alpha + ")";
167
+ }
168
+
169
+ function percentString(rgba, alpha) {
170
+ if (alpha < 1 || (rgba[3] && rgba[3] < 1)) {
171
+ return percentaString(rgba, alpha);
172
+ }
173
+ var r = Math.round(rgba[0]/255 * 100),
174
+ g = Math.round(rgba[1]/255 * 100),
175
+ b = Math.round(rgba[2]/255 * 100);
176
+
177
+ return "rgb(" + r + "%, " + g + "%, " + b + "%)";
178
+ }
179
+
180
+ function percentaString(rgba, alpha) {
181
+ var r = Math.round(rgba[0]/255 * 100),
182
+ g = Math.round(rgba[1]/255 * 100),
183
+ b = Math.round(rgba[2]/255 * 100);
184
+ return "rgba(" + r + "%, " + g + "%, " + b + "%, " + (alpha || rgba[3] || 1) + ")";
185
+ }
186
+
187
+ function hslString(hsla, alpha) {
188
+ if (alpha < 1 || (hsla[3] && hsla[3] < 1)) {
189
+ return hslaString(hsla, alpha);
190
+ }
191
+ return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)";
192
+ }
193
+
194
+ function hslaString(hsla, alpha) {
195
+ if (alpha === undefined) {
196
+ alpha = (hsla[3] !== undefined ? hsla[3] : 1);
197
+ }
198
+ return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, "
199
+ + alpha + ")";
200
+ }
201
+
202
+ // hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax
203
+ // (hwb have alpha optional & 1 is default value)
204
+ function hwbString(hwb, alpha) {
205
+ if (alpha === undefined) {
206
+ alpha = (hwb[3] !== undefined ? hwb[3] : 1);
207
+ }
208
+ return "hwb(" + hwb[0] + ", " + hwb[1] + "%, " + hwb[2] + "%"
209
+ + (alpha !== undefined && alpha !== 1 ? ", " + alpha : "") + ")";
210
+ }
211
+
212
+ function keyword(rgb) {
213
+ return reverseNames[rgb.slice(0, 3)];
214
+ }
215
+
216
+ // helpers
217
+ function scale(num, min, max) {
218
+ return Math.min(Math.max(min, num), max);
219
+ }
220
+
221
+ function hexDouble(num) {
222
+ var str = num.toString(16).toUpperCase();
223
+ return (str.length < 2) ? "0" + str : str;
224
+ }
225
+
226
+
227
+ //create a list of reverse color names
228
+ var reverseNames = {};
229
+ for (var name in colorNames) {
230
+ reverseNames[colorNames[name]] = name;
231
+ }
232
+
233
+ },{"5":5}],2:[function(require,module,exports){
234
+ /* MIT license */
235
+ var convert = require(4);
236
+ var string = require(1);
237
+
238
+ var Color = function (obj) {
239
+ if (obj instanceof Color) {
240
+ return obj;
241
+ }
242
+ if (!(this instanceof Color)) {
243
+ return new Color(obj);
244
+ }
245
+
246
+ this.valid = false;
247
+ this.values = {
248
+ rgb: [0, 0, 0],
249
+ hsl: [0, 0, 0],
250
+ hsv: [0, 0, 0],
251
+ hwb: [0, 0, 0],
252
+ cmyk: [0, 0, 0, 0],
253
+ alpha: 1
254
+ };
255
+
256
+ // parse Color() argument
257
+ var vals;
258
+ if (typeof obj === 'string') {
259
+ vals = string.getRgba(obj);
260
+ if (vals) {
261
+ this.setValues('rgb', vals);
262
+ } else if (vals = string.getHsla(obj)) {
263
+ this.setValues('hsl', vals);
264
+ } else if (vals = string.getHwb(obj)) {
265
+ this.setValues('hwb', vals);
266
+ }
267
+ } else if (typeof obj === 'object') {
268
+ vals = obj;
269
+ if (vals.r !== undefined || vals.red !== undefined) {
270
+ this.setValues('rgb', vals);
271
+ } else if (vals.l !== undefined || vals.lightness !== undefined) {
272
+ this.setValues('hsl', vals);
273
+ } else if (vals.v !== undefined || vals.value !== undefined) {
274
+ this.setValues('hsv', vals);
275
+ } else if (vals.w !== undefined || vals.whiteness !== undefined) {
276
+ this.setValues('hwb', vals);
277
+ } else if (vals.c !== undefined || vals.cyan !== undefined) {
278
+ this.setValues('cmyk', vals);
279
+ }
280
+ }
281
+ };
282
+
283
+ Color.prototype = {
284
+ isValid: function () {
285
+ return this.valid;
286
+ },
287
+ rgb: function () {
288
+ return this.setSpace('rgb', arguments);
289
+ },
290
+ hsl: function () {
291
+ return this.setSpace('hsl', arguments);
292
+ },
293
+ hsv: function () {
294
+ return this.setSpace('hsv', arguments);
295
+ },
296
+ hwb: function () {
297
+ return this.setSpace('hwb', arguments);
298
+ },
299
+ cmyk: function () {
300
+ return this.setSpace('cmyk', arguments);
301
+ },
302
+
303
+ rgbArray: function () {
304
+ return this.values.rgb;
305
+ },
306
+ hslArray: function () {
307
+ return this.values.hsl;
308
+ },
309
+ hsvArray: function () {
310
+ return this.values.hsv;
311
+ },
312
+ hwbArray: function () {
313
+ var values = this.values;
314
+ if (values.alpha !== 1) {
315
+ return values.hwb.concat([values.alpha]);
316
+ }
317
+ return values.hwb;
318
+ },
319
+ cmykArray: function () {
320
+ return this.values.cmyk;
321
+ },
322
+ rgbaArray: function () {
323
+ var values = this.values;
324
+ return values.rgb.concat([values.alpha]);
325
+ },
326
+ hslaArray: function () {
327
+ var values = this.values;
328
+ return values.hsl.concat([values.alpha]);
329
+ },
330
+ alpha: function (val) {
331
+ if (val === undefined) {
332
+ return this.values.alpha;
333
+ }
334
+ this.setValues('alpha', val);
335
+ return this;
336
+ },
337
+
338
+ red: function (val) {
339
+ return this.setChannel('rgb', 0, val);
340
+ },
341
+ green: function (val) {
342
+ return this.setChannel('rgb', 1, val);
343
+ },
344
+ blue: function (val) {
345
+ return this.setChannel('rgb', 2, val);
346
+ },
347
+ hue: function (val) {
348
+ if (val) {
349
+ val %= 360;
350
+ val = val < 0 ? 360 + val : val;
351
+ }
352
+ return this.setChannel('hsl', 0, val);
353
+ },
354
+ saturation: function (val) {
355
+ return this.setChannel('hsl', 1, val);
356
+ },
357
+ lightness: function (val) {
358
+ return this.setChannel('hsl', 2, val);
359
+ },
360
+ saturationv: function (val) {
361
+ return this.setChannel('hsv', 1, val);
362
+ },
363
+ whiteness: function (val) {
364
+ return this.setChannel('hwb', 1, val);
365
+ },
366
+ blackness: function (val) {
367
+ return this.setChannel('hwb', 2, val);
368
+ },
369
+ value: function (val) {
370
+ return this.setChannel('hsv', 2, val);
371
+ },
372
+ cyan: function (val) {
373
+ return this.setChannel('cmyk', 0, val);
374
+ },
375
+ magenta: function (val) {
376
+ return this.setChannel('cmyk', 1, val);
377
+ },
378
+ yellow: function (val) {
379
+ return this.setChannel('cmyk', 2, val);
380
+ },
381
+ black: function (val) {
382
+ return this.setChannel('cmyk', 3, val);
383
+ },
384
+
385
+ hexString: function () {
386
+ return string.hexString(this.values.rgb);
387
+ },
388
+ rgbString: function () {
389
+ return string.rgbString(this.values.rgb, this.values.alpha);
390
+ },
391
+ rgbaString: function () {
392
+ return string.rgbaString(this.values.rgb, this.values.alpha);
393
+ },
394
+ percentString: function () {
395
+ return string.percentString(this.values.rgb, this.values.alpha);
396
+ },
397
+ hslString: function () {
398
+ return string.hslString(this.values.hsl, this.values.alpha);
399
+ },
400
+ hslaString: function () {
401
+ return string.hslaString(this.values.hsl, this.values.alpha);
402
+ },
403
+ hwbString: function () {
404
+ return string.hwbString(this.values.hwb, this.values.alpha);
405
+ },
406
+ keyword: function () {
407
+ return string.keyword(this.values.rgb, this.values.alpha);
408
+ },
409
+
410
+ rgbNumber: function () {
411
+ var rgb = this.values.rgb;
412
+ return (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
413
+ },
414
+
415
+ luminosity: function () {
416
+ // http://www.w3.org/TR/WCAG20/#relativeluminancedef
417
+ var rgb = this.values.rgb;
418
+ var lum = [];
419
+ for (var i = 0; i < rgb.length; i++) {
420
+ var chan = rgb[i] / 255;
421
+ lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4);
422
+ }
423
+ return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2];
424
+ },
425
+
426
+ contrast: function (color2) {
427
+ // http://www.w3.org/TR/WCAG20/#contrast-ratiodef
428
+ var lum1 = this.luminosity();
429
+ var lum2 = color2.luminosity();
430
+ if (lum1 > lum2) {
431
+ return (lum1 + 0.05) / (lum2 + 0.05);
432
+ }
433
+ return (lum2 + 0.05) / (lum1 + 0.05);
434
+ },
435
+
436
+ level: function (color2) {
437
+ var contrastRatio = this.contrast(color2);
438
+ if (contrastRatio >= 7.1) {
439
+ return 'AAA';
440
+ }
441
+
442
+ return (contrastRatio >= 4.5) ? 'AA' : '';
443
+ },
444
+
445
+ dark: function () {
446
+ // YIQ equation from http://24ways.org/2010/calculating-color-contrast
447
+ var rgb = this.values.rgb;
448
+ var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;
449
+ return yiq < 128;
450
+ },
451
+
452
+ light: function () {
453
+ return !this.dark();
454
+ },
455
+
456
+ negate: function () {
457
+ var rgb = [];
458
+ for (var i = 0; i < 3; i++) {
459
+ rgb[i] = 255 - this.values.rgb[i];
460
+ }
461
+ this.setValues('rgb', rgb);
462
+ return this;
463
+ },
464
+
465
+ lighten: function (ratio) {
466
+ var hsl = this.values.hsl;
467
+ hsl[2] += hsl[2] * ratio;
468
+ this.setValues('hsl', hsl);
469
+ return this;
470
+ },
471
+
472
+ darken: function (ratio) {
473
+ var hsl = this.values.hsl;
474
+ hsl[2] -= hsl[2] * ratio;
475
+ this.setValues('hsl', hsl);
476
+ return this;
477
+ },
478
+
479
+ saturate: function (ratio) {
480
+ var hsl = this.values.hsl;
481
+ hsl[1] += hsl[1] * ratio;
482
+ this.setValues('hsl', hsl);
483
+ return this;
484
+ },
485
+
486
+ desaturate: function (ratio) {
487
+ var hsl = this.values.hsl;
488
+ hsl[1] -= hsl[1] * ratio;
489
+ this.setValues('hsl', hsl);
490
+ return this;
491
+ },
492
+
493
+ whiten: function (ratio) {
494
+ var hwb = this.values.hwb;
495
+ hwb[1] += hwb[1] * ratio;
496
+ this.setValues('hwb', hwb);
497
+ return this;
498
+ },
499
+
500
+ blacken: function (ratio) {
501
+ var hwb = this.values.hwb;
502
+ hwb[2] += hwb[2] * ratio;
503
+ this.setValues('hwb', hwb);
504
+ return this;
505
+ },
506
+
507
+ greyscale: function () {
508
+ var rgb = this.values.rgb;
509
+ // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
510
+ var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11;
511
+ this.setValues('rgb', [val, val, val]);
512
+ return this;
513
+ },
514
+
515
+ clearer: function (ratio) {
516
+ var alpha = this.values.alpha;
517
+ this.setValues('alpha', alpha - (alpha * ratio));
518
+ return this;
519
+ },
520
+
521
+ opaquer: function (ratio) {
522
+ var alpha = this.values.alpha;
523
+ this.setValues('alpha', alpha + (alpha * ratio));
524
+ return this;
525
+ },
526
+
527
+ rotate: function (degrees) {
528
+ var hsl = this.values.hsl;
529
+ var hue = (hsl[0] + degrees) % 360;
530
+ hsl[0] = hue < 0 ? 360 + hue : hue;
531
+ this.setValues('hsl', hsl);
532
+ return this;
533
+ },
534
+
535
+ /**
536
+ * Ported from sass implementation in C
537
+ * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209
538
+ */
539
+ mix: function (mixinColor, weight) {
540
+ var color1 = this;
541
+ var color2 = mixinColor;
542
+ var p = weight === undefined ? 0.5 : weight;
543
+
544
+ var w = 2 * p - 1;
545
+ var a = color1.alpha() - color2.alpha();
546
+
547
+ var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
548
+ var w2 = 1 - w1;
549
+
550
+ return this
551
+ .rgb(
552
+ w1 * color1.red() + w2 * color2.red(),
553
+ w1 * color1.green() + w2 * color2.green(),
554
+ w1 * color1.blue() + w2 * color2.blue()
555
+ )
556
+ .alpha(color1.alpha() * p + color2.alpha() * (1 - p));
557
+ },
558
+
559
+ toJSON: function () {
560
+ return this.rgb();
561
+ },
562
+
563
+ clone: function () {
564
+ // NOTE(SB): using node-clone creates a dependency to Buffer when using browserify,
565
+ // making the final build way to big to embed in Chart.js. So let's do it manually,
566
+ // assuming that values to clone are 1 dimension arrays containing only numbers,
567
+ // except 'alpha' which is a number.
568
+ var result = new Color();
569
+ var source = this.values;
570
+ var target = result.values;
571
+ var value, type;
572
+
573
+ for (var prop in source) {
574
+ if (source.hasOwnProperty(prop)) {
575
+ value = source[prop];
576
+ type = ({}).toString.call(value);
577
+ if (type === '[object Array]') {
578
+ target[prop] = value.slice(0);
579
+ } else if (type === '[object Number]') {
580
+ target[prop] = value;
581
+ } else {
582
+ console.error('unexpected color value:', value);
583
+ }
584
+ }
585
+ }
586
+
587
+ return result;
588
+ }
589
+ };
590
+
591
+ Color.prototype.spaces = {
592
+ rgb: ['red', 'green', 'blue'],
593
+ hsl: ['hue', 'saturation', 'lightness'],
594
+ hsv: ['hue', 'saturation', 'value'],
595
+ hwb: ['hue', 'whiteness', 'blackness'],
596
+ cmyk: ['cyan', 'magenta', 'yellow', 'black']
597
+ };
598
+
599
+ Color.prototype.maxes = {
600
+ rgb: [255, 255, 255],
601
+ hsl: [360, 100, 100],
602
+ hsv: [360, 100, 100],
603
+ hwb: [360, 100, 100],
604
+ cmyk: [100, 100, 100, 100]
605
+ };
606
+
607
+ Color.prototype.getValues = function (space) {
608
+ var values = this.values;
609
+ var vals = {};
610
+
611
+ for (var i = 0; i < space.length; i++) {
612
+ vals[space.charAt(i)] = values[space][i];
613
+ }
614
+
615
+ if (values.alpha !== 1) {
616
+ vals.a = values.alpha;
617
+ }
618
+
619
+ // {r: 255, g: 255, b: 255, a: 0.4}
620
+ return vals;
621
+ };
622
+
623
+ Color.prototype.setValues = function (space, vals) {
624
+ var values = this.values;
625
+ var spaces = this.spaces;
626
+ var maxes = this.maxes;
627
+ var alpha = 1;
628
+ var i;
629
+
630
+ this.valid = true;
631
+
632
+ if (space === 'alpha') {
633
+ alpha = vals;
634
+ } else if (vals.length) {
635
+ // [10, 10, 10]
636
+ values[space] = vals.slice(0, space.length);
637
+ alpha = vals[space.length];
638
+ } else if (vals[space.charAt(0)] !== undefined) {
639
+ // {r: 10, g: 10, b: 10}
640
+ for (i = 0; i < space.length; i++) {
641
+ values[space][i] = vals[space.charAt(i)];
642
+ }
643
+
644
+ alpha = vals.a;
645
+ } else if (vals[spaces[space][0]] !== undefined) {
646
+ // {red: 10, green: 10, blue: 10}
647
+ var chans = spaces[space];
648
+
649
+ for (i = 0; i < space.length; i++) {
650
+ values[space][i] = vals[chans[i]];
651
+ }
652
+
653
+ alpha = vals.alpha;
654
+ }
655
+
656
+ values.alpha = Math.max(0, Math.min(1, (alpha === undefined ? values.alpha : alpha)));
657
+
658
+ if (space === 'alpha') {
659
+ return false;
660
+ }
661
+
662
+ var capped;
663
+
664
+ // cap values of the space prior converting all values
665
+ for (i = 0; i < space.length; i++) {
666
+ capped = Math.max(0, Math.min(maxes[space][i], values[space][i]));
667
+ values[space][i] = Math.round(capped);
668
+ }
669
+
670
+ // convert to all the other color spaces
671
+ for (var sname in spaces) {
672
+ if (sname !== space) {
673
+ values[sname] = convert[space][sname](values[space]);
674
+ }
675
+ }
676
+
677
+ return true;
678
+ };
679
+
680
+ Color.prototype.setSpace = function (space, args) {
681
+ var vals = args[0];
682
+
683
+ if (vals === undefined) {
684
+ // color.rgb()
685
+ return this.getValues(space);
686
+ }
687
+
688
+ // color.rgb(10, 10, 10)
689
+ if (typeof vals === 'number') {
690
+ vals = Array.prototype.slice.call(args);
691
+ }
692
+
693
+ this.setValues(space, vals);
694
+ return this;
695
+ };
696
+
697
+ Color.prototype.setChannel = function (space, index, val) {
698
+ var svalues = this.values[space];
699
+ if (val === undefined) {
700
+ // color.red()
701
+ return svalues[index];
702
+ } else if (val === svalues[index]) {
703
+ // color.red(color.red())
704
+ return this;
705
+ }
706
+
707
+ // color.red(100)
708
+ svalues[index] = val;
709
+ this.setValues(space, svalues);
710
+
711
+ return this;
712
+ };
713
+
714
+ if (typeof window !== 'undefined') {
715
+ window.Color = Color;
716
+ }
717
+
718
+ module.exports = Color;
719
+
720
+ },{"1":1,"4":4}],3:[function(require,module,exports){
721
+ /* MIT license */
722
+
723
+ module.exports = {
724
+ rgb2hsl: rgb2hsl,
725
+ rgb2hsv: rgb2hsv,
726
+ rgb2hwb: rgb2hwb,
727
+ rgb2cmyk: rgb2cmyk,
728
+ rgb2keyword: rgb2keyword,
729
+ rgb2xyz: rgb2xyz,
730
+ rgb2lab: rgb2lab,
731
+ rgb2lch: rgb2lch,
732
+
733
+ hsl2rgb: hsl2rgb,
734
+ hsl2hsv: hsl2hsv,
735
+ hsl2hwb: hsl2hwb,
736
+ hsl2cmyk: hsl2cmyk,
737
+ hsl2keyword: hsl2keyword,
738
+
739
+ hsv2rgb: hsv2rgb,
740
+ hsv2hsl: hsv2hsl,
741
+ hsv2hwb: hsv2hwb,
742
+ hsv2cmyk: hsv2cmyk,
743
+ hsv2keyword: hsv2keyword,
744
+
745
+ hwb2rgb: hwb2rgb,
746
+ hwb2hsl: hwb2hsl,
747
+ hwb2hsv: hwb2hsv,
748
+ hwb2cmyk: hwb2cmyk,
749
+ hwb2keyword: hwb2keyword,
750
+
751
+ cmyk2rgb: cmyk2rgb,
752
+ cmyk2hsl: cmyk2hsl,
753
+ cmyk2hsv: cmyk2hsv,
754
+ cmyk2hwb: cmyk2hwb,
755
+ cmyk2keyword: cmyk2keyword,
756
+
757
+ keyword2rgb: keyword2rgb,
758
+ keyword2hsl: keyword2hsl,
759
+ keyword2hsv: keyword2hsv,
760
+ keyword2hwb: keyword2hwb,
761
+ keyword2cmyk: keyword2cmyk,
762
+ keyword2lab: keyword2lab,
763
+ keyword2xyz: keyword2xyz,
764
+
765
+ xyz2rgb: xyz2rgb,
766
+ xyz2lab: xyz2lab,
767
+ xyz2lch: xyz2lch,
768
+
769
+ lab2xyz: lab2xyz,
770
+ lab2rgb: lab2rgb,
771
+ lab2lch: lab2lch,
772
+
773
+ lch2lab: lch2lab,
774
+ lch2xyz: lch2xyz,
775
+ lch2rgb: lch2rgb
776
+ }
777
+
778
+
779
+ function rgb2hsl(rgb) {
780
+ var r = rgb[0]/255,
781
+ g = rgb[1]/255,
782
+ b = rgb[2]/255,
783
+ min = Math.min(r, g, b),
784
+ max = Math.max(r, g, b),
785
+ delta = max - min,
786
+ h, s, l;
787
+
788
+ if (max == min)
789
+ h = 0;
790
+ else if (r == max)
791
+ h = (g - b) / delta;
792
+ else if (g == max)
793
+ h = 2 + (b - r) / delta;
794
+ else if (b == max)
795
+ h = 4 + (r - g)/ delta;
796
+
797
+ h = Math.min(h * 60, 360);
798
+
799
+ if (h < 0)
800
+ h += 360;
801
+
802
+ l = (min + max) / 2;
803
+
804
+ if (max == min)
805
+ s = 0;
806
+ else if (l <= 0.5)
807
+ s = delta / (max + min);
808
+ else
809
+ s = delta / (2 - max - min);
810
+
811
+ return [h, s * 100, l * 100];
812
+ }
813
+
814
+ function rgb2hsv(rgb) {
815
+ var r = rgb[0],
816
+ g = rgb[1],
817
+ b = rgb[2],
818
+ min = Math.min(r, g, b),
819
+ max = Math.max(r, g, b),
820
+ delta = max - min,
821
+ h, s, v;
822
+
823
+ if (max == 0)
824
+ s = 0;
825
+ else
826
+ s = (delta/max * 1000)/10;
827
+
828
+ if (max == min)
829
+ h = 0;
830
+ else if (r == max)
831
+ h = (g - b) / delta;
832
+ else if (g == max)
833
+ h = 2 + (b - r) / delta;
834
+ else if (b == max)
835
+ h = 4 + (r - g) / delta;
836
+
837
+ h = Math.min(h * 60, 360);
838
+
839
+ if (h < 0)
840
+ h += 360;
841
+
842
+ v = ((max / 255) * 1000) / 10;
843
+
844
+ return [h, s, v];
845
+ }
846
+
847
+ function rgb2hwb(rgb) {
848
+ var r = rgb[0],
849
+ g = rgb[1],
850
+ b = rgb[2],
851
+ h = rgb2hsl(rgb)[0],
852
+ w = 1/255 * Math.min(r, Math.min(g, b)),
853
+ b = 1 - 1/255 * Math.max(r, Math.max(g, b));
854
+
855
+ return [h, w * 100, b * 100];
856
+ }
857
+
858
+ function rgb2cmyk(rgb) {
859
+ var r = rgb[0] / 255,
860
+ g = rgb[1] / 255,
861
+ b = rgb[2] / 255,
862
+ c, m, y, k;
863
+
864
+ k = Math.min(1 - r, 1 - g, 1 - b);
865
+ c = (1 - r - k) / (1 - k) || 0;
866
+ m = (1 - g - k) / (1 - k) || 0;
867
+ y = (1 - b - k) / (1 - k) || 0;
868
+ return [c * 100, m * 100, y * 100, k * 100];
869
+ }
870
+
871
+ function rgb2keyword(rgb) {
872
+ return reverseKeywords[JSON.stringify(rgb)];
873
+ }
874
+
875
+ function rgb2xyz(rgb) {
876
+ var r = rgb[0] / 255,
877
+ g = rgb[1] / 255,
878
+ b = rgb[2] / 255;
879
+
880
+ // assume sRGB
881
+ r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92);
882
+ g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92);
883
+ b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92);
884
+
885
+ var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
886
+ var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
887
+ var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
888
+
889
+ return [x * 100, y *100, z * 100];
890
+ }
891
+
892
+ function rgb2lab(rgb) {
893
+ var xyz = rgb2xyz(rgb),
894
+ x = xyz[0],
895
+ y = xyz[1],
896
+ z = xyz[2],
897
+ l, a, b;
898
+
899
+ x /= 95.047;
900
+ y /= 100;
901
+ z /= 108.883;
902
+
903
+ x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);
904
+ y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);
905
+ z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);
906
+
907
+ l = (116 * y) - 16;
908
+ a = 500 * (x - y);
909
+ b = 200 * (y - z);
910
+
911
+ return [l, a, b];
912
+ }
913
+
914
+ function rgb2lch(args) {
915
+ return lab2lch(rgb2lab(args));
916
+ }
917
+
918
+ function hsl2rgb(hsl) {
919
+ var h = hsl[0] / 360,
920
+ s = hsl[1] / 100,
921
+ l = hsl[2] / 100,
922
+ t1, t2, t3, rgb, val;
923
+
924
+ if (s == 0) {
925
+ val = l * 255;
926
+ return [val, val, val];
927
+ }
928
+
929
+ if (l < 0.5)
930
+ t2 = l * (1 + s);
931
+ else
932
+ t2 = l + s - l * s;
933
+ t1 = 2 * l - t2;
934
+
935
+ rgb = [0, 0, 0];
936
+ for (var i = 0; i < 3; i++) {
937
+ t3 = h + 1 / 3 * - (i - 1);
938
+ t3 < 0 && t3++;
939
+ t3 > 1 && t3--;
940
+
941
+ if (6 * t3 < 1)
942
+ val = t1 + (t2 - t1) * 6 * t3;
943
+ else if (2 * t3 < 1)
944
+ val = t2;
945
+ else if (3 * t3 < 2)
946
+ val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
947
+ else
948
+ val = t1;
949
+
950
+ rgb[i] = val * 255;
951
+ }
952
+
953
+ return rgb;
954
+ }
955
+
956
+ function hsl2hsv(hsl) {
957
+ var h = hsl[0],
958
+ s = hsl[1] / 100,
959
+ l = hsl[2] / 100,
960
+ sv, v;
961
+
962
+ if(l === 0) {
963
+ // no need to do calc on black
964
+ // also avoids divide by 0 error
965
+ return [0, 0, 0];
966
+ }
967
+
968
+ l *= 2;
969
+ s *= (l <= 1) ? l : 2 - l;
970
+ v = (l + s) / 2;
971
+ sv = (2 * s) / (l + s);
972
+ return [h, sv * 100, v * 100];
973
+ }
974
+
975
+ function hsl2hwb(args) {
976
+ return rgb2hwb(hsl2rgb(args));
977
+ }
978
+
979
+ function hsl2cmyk(args) {
980
+ return rgb2cmyk(hsl2rgb(args));
981
+ }
982
+
983
+ function hsl2keyword(args) {
984
+ return rgb2keyword(hsl2rgb(args));
985
+ }
986
+
987
+
988
+ function hsv2rgb(hsv) {
989
+ var h = hsv[0] / 60,
990
+ s = hsv[1] / 100,
991
+ v = hsv[2] / 100,
992
+ hi = Math.floor(h) % 6;
993
+
994
+ var f = h - Math.floor(h),
995
+ p = 255 * v * (1 - s),
996
+ q = 255 * v * (1 - (s * f)),
997
+ t = 255 * v * (1 - (s * (1 - f))),
998
+ v = 255 * v;
999
+
1000
+ switch(hi) {
1001
+ case 0:
1002
+ return [v, t, p];
1003
+ case 1:
1004
+ return [q, v, p];
1005
+ case 2:
1006
+ return [p, v, t];
1007
+ case 3:
1008
+ return [p, q, v];
1009
+ case 4:
1010
+ return [t, p, v];
1011
+ case 5:
1012
+ return [v, p, q];
1013
+ }
1014
+ }
1015
+
1016
+ function hsv2hsl(hsv) {
1017
+ var h = hsv[0],
1018
+ s = hsv[1] / 100,
1019
+ v = hsv[2] / 100,
1020
+ sl, l;
1021
+
1022
+ l = (2 - s) * v;
1023
+ sl = s * v;
1024
+ sl /= (l <= 1) ? l : 2 - l;
1025
+ sl = sl || 0;
1026
+ l /= 2;
1027
+ return [h, sl * 100, l * 100];
1028
+ }
1029
+
1030
+ function hsv2hwb(args) {
1031
+ return rgb2hwb(hsv2rgb(args))
1032
+ }
1033
+
1034
+ function hsv2cmyk(args) {
1035
+ return rgb2cmyk(hsv2rgb(args));
1036
+ }
1037
+
1038
+ function hsv2keyword(args) {
1039
+ return rgb2keyword(hsv2rgb(args));
1040
+ }
1041
+
1042
+ // http://dev.w3.org/csswg/css-color/#hwb-to-rgb
1043
+ function hwb2rgb(hwb) {
1044
+ var h = hwb[0] / 360,
1045
+ wh = hwb[1] / 100,
1046
+ bl = hwb[2] / 100,
1047
+ ratio = wh + bl,
1048
+ i, v, f, n;
1049
+
1050
+ // wh + bl cant be > 1
1051
+ if (ratio > 1) {
1052
+ wh /= ratio;
1053
+ bl /= ratio;
1054
+ }
1055
+
1056
+ i = Math.floor(6 * h);
1057
+ v = 1 - bl;
1058
+ f = 6 * h - i;
1059
+ if ((i & 0x01) != 0) {
1060
+ f = 1 - f;
1061
+ }
1062
+ n = wh + f * (v - wh); // linear interpolation
1063
+
1064
+ switch (i) {
1065
+ default:
1066
+ case 6:
1067
+ case 0: r = v; g = n; b = wh; break;
1068
+ case 1: r = n; g = v; b = wh; break;
1069
+ case 2: r = wh; g = v; b = n; break;
1070
+ case 3: r = wh; g = n; b = v; break;
1071
+ case 4: r = n; g = wh; b = v; break;
1072
+ case 5: r = v; g = wh; b = n; break;
1073
+ }
1074
+
1075
+ return [r * 255, g * 255, b * 255];
1076
+ }
1077
+
1078
+ function hwb2hsl(args) {
1079
+ return rgb2hsl(hwb2rgb(args));
1080
+ }
1081
+
1082
+ function hwb2hsv(args) {
1083
+ return rgb2hsv(hwb2rgb(args));
1084
+ }
1085
+
1086
+ function hwb2cmyk(args) {
1087
+ return rgb2cmyk(hwb2rgb(args));
1088
+ }
1089
+
1090
+ function hwb2keyword(args) {
1091
+ return rgb2keyword(hwb2rgb(args));
1092
+ }
1093
+
1094
+ function cmyk2rgb(cmyk) {
1095
+ var c = cmyk[0] / 100,
1096
+ m = cmyk[1] / 100,
1097
+ y = cmyk[2] / 100,
1098
+ k = cmyk[3] / 100,
1099
+ r, g, b;
1100
+
1101
+ r = 1 - Math.min(1, c * (1 - k) + k);
1102
+ g = 1 - Math.min(1, m * (1 - k) + k);
1103
+ b = 1 - Math.min(1, y * (1 - k) + k);
1104
+ return [r * 255, g * 255, b * 255];
1105
+ }
1106
+
1107
+ function cmyk2hsl(args) {
1108
+ return rgb2hsl(cmyk2rgb(args));
1109
+ }
1110
+
1111
+ function cmyk2hsv(args) {
1112
+ return rgb2hsv(cmyk2rgb(args));
1113
+ }
1114
+
1115
+ function cmyk2hwb(args) {
1116
+ return rgb2hwb(cmyk2rgb(args));
1117
+ }
1118
+
1119
+ function cmyk2keyword(args) {
1120
+ return rgb2keyword(cmyk2rgb(args));
1121
+ }
1122
+
1123
+
1124
+ function xyz2rgb(xyz) {
1125
+ var x = xyz[0] / 100,
1126
+ y = xyz[1] / 100,
1127
+ z = xyz[2] / 100,
1128
+ r, g, b;
1129
+
1130
+ r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
1131
+ g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
1132
+ b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
1133
+
1134
+ // assume sRGB
1135
+ r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055)
1136
+ : r = (r * 12.92);
1137
+
1138
+ g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055)
1139
+ : g = (g * 12.92);
1140
+
1141
+ b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055)
1142
+ : b = (b * 12.92);
1143
+
1144
+ r = Math.min(Math.max(0, r), 1);
1145
+ g = Math.min(Math.max(0, g), 1);
1146
+ b = Math.min(Math.max(0, b), 1);
1147
+
1148
+ return [r * 255, g * 255, b * 255];
1149
+ }
1150
+
1151
+ function xyz2lab(xyz) {
1152
+ var x = xyz[0],
1153
+ y = xyz[1],
1154
+ z = xyz[2],
1155
+ l, a, b;
1156
+
1157
+ x /= 95.047;
1158
+ y /= 100;
1159
+ z /= 108.883;
1160
+
1161
+ x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);
1162
+ y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);
1163
+ z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);
1164
+
1165
+ l = (116 * y) - 16;
1166
+ a = 500 * (x - y);
1167
+ b = 200 * (y - z);
1168
+
1169
+ return [l, a, b];
1170
+ }
1171
+
1172
+ function xyz2lch(args) {
1173
+ return lab2lch(xyz2lab(args));
1174
+ }
1175
+
1176
+ function lab2xyz(lab) {
1177
+ var l = lab[0],
1178
+ a = lab[1],
1179
+ b = lab[2],
1180
+ x, y, z, y2;
1181
+
1182
+ if (l <= 8) {
1183
+ y = (l * 100) / 903.3;
1184
+ y2 = (7.787 * (y / 100)) + (16 / 116);
1185
+ } else {
1186
+ y = 100 * Math.pow((l + 16) / 116, 3);
1187
+ y2 = Math.pow(y / 100, 1/3);
1188
+ }
1189
+
1190
+ x = x / 95.047 <= 0.008856 ? x = (95.047 * ((a / 500) + y2 - (16 / 116))) / 7.787 : 95.047 * Math.pow((a / 500) + y2, 3);
1191
+
1192
+ z = z / 108.883 <= 0.008859 ? z = (108.883 * (y2 - (b / 200) - (16 / 116))) / 7.787 : 108.883 * Math.pow(y2 - (b / 200), 3);
1193
+
1194
+ return [x, y, z];
1195
+ }
1196
+
1197
+ function lab2lch(lab) {
1198
+ var l = lab[0],
1199
+ a = lab[1],
1200
+ b = lab[2],
1201
+ hr, h, c;
1202
+
1203
+ hr = Math.atan2(b, a);
1204
+ h = hr * 360 / 2 / Math.PI;
1205
+ if (h < 0) {
1206
+ h += 360;
1207
+ }
1208
+ c = Math.sqrt(a * a + b * b);
1209
+ return [l, c, h];
1210
+ }
1211
+
1212
+ function lab2rgb(args) {
1213
+ return xyz2rgb(lab2xyz(args));
1214
+ }
1215
+
1216
+ function lch2lab(lch) {
1217
+ var l = lch[0],
1218
+ c = lch[1],
1219
+ h = lch[2],
1220
+ a, b, hr;
1221
+
1222
+ hr = h / 360 * 2 * Math.PI;
1223
+ a = c * Math.cos(hr);
1224
+ b = c * Math.sin(hr);
1225
+ return [l, a, b];
1226
+ }
1227
+
1228
+ function lch2xyz(args) {
1229
+ return lab2xyz(lch2lab(args));
1230
+ }
1231
+
1232
+ function lch2rgb(args) {
1233
+ return lab2rgb(lch2lab(args));
1234
+ }
1235
+
1236
+ function keyword2rgb(keyword) {
1237
+ return cssKeywords[keyword];
1238
+ }
1239
+
1240
+ function keyword2hsl(args) {
1241
+ return rgb2hsl(keyword2rgb(args));
1242
+ }
1243
+
1244
+ function keyword2hsv(args) {
1245
+ return rgb2hsv(keyword2rgb(args));
1246
+ }
1247
+
1248
+ function keyword2hwb(args) {
1249
+ return rgb2hwb(keyword2rgb(args));
1250
+ }
1251
+
1252
+ function keyword2cmyk(args) {
1253
+ return rgb2cmyk(keyword2rgb(args));
1254
+ }
1255
+
1256
+ function keyword2lab(args) {
1257
+ return rgb2lab(keyword2rgb(args));
1258
+ }
1259
+
1260
+ function keyword2xyz(args) {
1261
+ return rgb2xyz(keyword2rgb(args));
1262
+ }
1263
+
1264
+ var cssKeywords = {
1265
+ aliceblue: [240,248,255],
1266
+ antiquewhite: [250,235,215],
1267
+ aqua: [0,255,255],
1268
+ aquamarine: [127,255,212],
1269
+ azure: [240,255,255],
1270
+ beige: [245,245,220],
1271
+ bisque: [255,228,196],
1272
+ black: [0,0,0],
1273
+ blanchedalmond: [255,235,205],
1274
+ blue: [0,0,255],
1275
+ blueviolet: [138,43,226],
1276
+ brown: [165,42,42],
1277
+ burlywood: [222,184,135],
1278
+ cadetblue: [95,158,160],
1279
+ chartreuse: [127,255,0],
1280
+ chocolate: [210,105,30],
1281
+ coral: [255,127,80],
1282
+ cornflowerblue: [100,149,237],
1283
+ cornsilk: [255,248,220],
1284
+ crimson: [220,20,60],
1285
+ cyan: [0,255,255],
1286
+ darkblue: [0,0,139],
1287
+ darkcyan: [0,139,139],
1288
+ darkgoldenrod: [184,134,11],
1289
+ darkgray: [169,169,169],
1290
+ darkgreen: [0,100,0],
1291
+ darkgrey: [169,169,169],
1292
+ darkkhaki: [189,183,107],
1293
+ darkmagenta: [139,0,139],
1294
+ darkolivegreen: [85,107,47],
1295
+ darkorange: [255,140,0],
1296
+ darkorchid: [153,50,204],
1297
+ darkred: [139,0,0],
1298
+ darksalmon: [233,150,122],
1299
+ darkseagreen: [143,188,143],
1300
+ darkslateblue: [72,61,139],
1301
+ darkslategray: [47,79,79],
1302
+ darkslategrey: [47,79,79],
1303
+ darkturquoise: [0,206,209],
1304
+ darkviolet: [148,0,211],
1305
+ deeppink: [255,20,147],
1306
+ deepskyblue: [0,191,255],
1307
+ dimgray: [105,105,105],
1308
+ dimgrey: [105,105,105],
1309
+ dodgerblue: [30,144,255],
1310
+ firebrick: [178,34,34],
1311
+ floralwhite: [255,250,240],
1312
+ forestgreen: [34,139,34],
1313
+ fuchsia: [255,0,255],
1314
+ gainsboro: [220,220,220],
1315
+ ghostwhite: [248,248,255],
1316
+ gold: [255,215,0],
1317
+ goldenrod: [218,165,32],
1318
+ gray: [128,128,128],
1319
+ green: [0,128,0],
1320
+ greenyellow: [173,255,47],
1321
+ grey: [128,128,128],
1322
+ honeydew: [240,255,240],
1323
+ hotpink: [255,105,180],
1324
+ indianred: [205,92,92],
1325
+ indigo: [75,0,130],
1326
+ ivory: [255,255,240],
1327
+ khaki: [240,230,140],
1328
+ lavender: [230,230,250],
1329
+ lavenderblush: [255,240,245],
1330
+ lawngreen: [124,252,0],
1331
+ lemonchiffon: [255,250,205],
1332
+ lightblue: [173,216,230],
1333
+ lightcoral: [240,128,128],
1334
+ lightcyan: [224,255,255],
1335
+ lightgoldenrodyellow: [250,250,210],
1336
+ lightgray: [211,211,211],
1337
+ lightgreen: [144,238,144],
1338
+ lightgrey: [211,211,211],
1339
+ lightpink: [255,182,193],
1340
+ lightsalmon: [255,160,122],
1341
+ lightseagreen: [32,178,170],
1342
+ lightskyblue: [135,206,250],
1343
+ lightslategray: [119,136,153],
1344
+ lightslategrey: [119,136,153],
1345
+ lightsteelblue: [176,196,222],
1346
+ lightyellow: [255,255,224],
1347
+ lime: [0,255,0],
1348
+ limegreen: [50,205,50],
1349
+ linen: [250,240,230],
1350
+ magenta: [255,0,255],
1351
+ maroon: [128,0,0],
1352
+ mediumaquamarine: [102,205,170],
1353
+ mediumblue: [0,0,205],
1354
+ mediumorchid: [186,85,211],
1355
+ mediumpurple: [147,112,219],
1356
+ mediumseagreen: [60,179,113],
1357
+ mediumslateblue: [123,104,238],
1358
+ mediumspringgreen: [0,250,154],
1359
+ mediumturquoise: [72,209,204],
1360
+ mediumvioletred: [199,21,133],
1361
+ midnightblue: [25,25,112],
1362
+ mintcream: [245,255,250],
1363
+ mistyrose: [255,228,225],
1364
+ moccasin: [255,228,181],
1365
+ navajowhite: [255,222,173],
1366
+ navy: [0,0,128],
1367
+ oldlace: [253,245,230],
1368
+ olive: [128,128,0],
1369
+ olivedrab: [107,142,35],
1370
+ orange: [255,165,0],
1371
+ orangered: [255,69,0],
1372
+ orchid: [218,112,214],
1373
+ palegoldenrod: [238,232,170],
1374
+ palegreen: [152,251,152],
1375
+ paleturquoise: [175,238,238],
1376
+ palevioletred: [219,112,147],
1377
+ papayawhip: [255,239,213],
1378
+ peachpuff: [255,218,185],
1379
+ peru: [205,133,63],
1380
+ pink: [255,192,203],
1381
+ plum: [221,160,221],
1382
+ powderblue: [176,224,230],
1383
+ purple: [128,0,128],
1384
+ rebeccapurple: [102, 51, 153],
1385
+ red: [255,0,0],
1386
+ rosybrown: [188,143,143],
1387
+ royalblue: [65,105,225],
1388
+ saddlebrown: [139,69,19],
1389
+ salmon: [250,128,114],
1390
+ sandybrown: [244,164,96],
1391
+ seagreen: [46,139,87],
1392
+ seashell: [255,245,238],
1393
+ sienna: [160,82,45],
1394
+ silver: [192,192,192],
1395
+ skyblue: [135,206,235],
1396
+ slateblue: [106,90,205],
1397
+ slategray: [112,128,144],
1398
+ slategrey: [112,128,144],
1399
+ snow: [255,250,250],
1400
+ springgreen: [0,255,127],
1401
+ steelblue: [70,130,180],
1402
+ tan: [210,180,140],
1403
+ teal: [0,128,128],
1404
+ thistle: [216,191,216],
1405
+ tomato: [255,99,71],
1406
+ turquoise: [64,224,208],
1407
+ violet: [238,130,238],
1408
+ wheat: [245,222,179],
1409
+ white: [255,255,255],
1410
+ whitesmoke: [245,245,245],
1411
+ yellow: [255,255,0],
1412
+ yellowgreen: [154,205,50]
1413
+ };
1414
+
1415
+ var reverseKeywords = {};
1416
+ for (var key in cssKeywords) {
1417
+ reverseKeywords[JSON.stringify(cssKeywords[key])] = key;
1418
+ }
1419
+
1420
+ },{}],4:[function(require,module,exports){
1421
+ var conversions = require(3);
1422
+
1423
+ var convert = function() {
1424
+ return new Converter();
1425
+ }
1426
+
1427
+ for (var func in conversions) {
1428
+ // export Raw versions
1429
+ convert[func + "Raw"] = (function(func) {
1430
+ // accept array or plain args
1431
+ return function(arg) {
1432
+ if (typeof arg == "number")
1433
+ arg = Array.prototype.slice.call(arguments);
1434
+ return conversions[func](arg);
1435
+ }
1436
+ })(func);
1437
+
1438
+ var pair = /(\w+)2(\w+)/.exec(func),
1439
+ from = pair[1],
1440
+ to = pair[2];
1441
+
1442
+ // export rgb2hsl and ["rgb"]["hsl"]
1443
+ convert[from] = convert[from] || {};
1444
+
1445
+ convert[from][to] = convert[func] = (function(func) {
1446
+ return function(arg) {
1447
+ if (typeof arg == "number")
1448
+ arg = Array.prototype.slice.call(arguments);
1449
+
1450
+ var val = conversions[func](arg);
1451
+ if (typeof val == "string" || val === undefined)
1452
+ return val; // keyword
1453
+
1454
+ for (var i = 0; i < val.length; i++)
1455
+ val[i] = Math.round(val[i]);
1456
+ return val;
1457
+ }
1458
+ })(func);
1459
+ }
1460
+
1461
+
1462
+ /* Converter does lazy conversion and caching */
1463
+ var Converter = function() {
1464
+ this.convs = {};
1465
+ };
1466
+
1467
+ /* Either get the values for a space or
1468
+ set the values for a space, depending on args */
1469
+ Converter.prototype.routeSpace = function(space, args) {
1470
+ var values = args[0];
1471
+ if (values === undefined) {
1472
+ // color.rgb()
1473
+ return this.getValues(space);
1474
+ }
1475
+ // color.rgb(10, 10, 10)
1476
+ if (typeof values == "number") {
1477
+ values = Array.prototype.slice.call(args);
1478
+ }
1479
+
1480
+ return this.setValues(space, values);
1481
+ };
1482
+
1483
+ /* Set the values for a space, invalidating cache */
1484
+ Converter.prototype.setValues = function(space, values) {
1485
+ this.space = space;
1486
+ this.convs = {};
1487
+ this.convs[space] = values;
1488
+ return this;
1489
+ };
1490
+
1491
+ /* Get the values for a space. If there's already
1492
+ a conversion for the space, fetch it, otherwise
1493
+ compute it */
1494
+ Converter.prototype.getValues = function(space) {
1495
+ var vals = this.convs[space];
1496
+ if (!vals) {
1497
+ var fspace = this.space,
1498
+ from = this.convs[fspace];
1499
+ vals = convert[fspace][space](from);
1500
+
1501
+ this.convs[space] = vals;
1502
+ }
1503
+ return vals;
1504
+ };
1505
+
1506
+ ["rgb", "hsl", "hsv", "cmyk", "keyword"].forEach(function(space) {
1507
+ Converter.prototype[space] = function(vals) {
1508
+ return this.routeSpace(space, arguments);
1509
+ }
1510
+ });
1511
+
1512
+ module.exports = convert;
1513
+ },{"3":3}],5:[function(require,module,exports){
1514
+ 'use strict'
1515
+
1516
+ module.exports = {
1517
+ "aliceblue": [240, 248, 255],
1518
+ "antiquewhite": [250, 235, 215],
1519
+ "aqua": [0, 255, 255],
1520
+ "aquamarine": [127, 255, 212],
1521
+ "azure": [240, 255, 255],
1522
+ "beige": [245, 245, 220],
1523
+ "bisque": [255, 228, 196],
1524
+ "black": [0, 0, 0],
1525
+ "blanchedalmond": [255, 235, 205],
1526
+ "blue": [0, 0, 255],
1527
+ "blueviolet": [138, 43, 226],
1528
+ "brown": [165, 42, 42],
1529
+ "burlywood": [222, 184, 135],
1530
+ "cadetblue": [95, 158, 160],
1531
+ "chartreuse": [127, 255, 0],
1532
+ "chocolate": [210, 105, 30],
1533
+ "coral": [255, 127, 80],
1534
+ "cornflowerblue": [100, 149, 237],
1535
+ "cornsilk": [255, 248, 220],
1536
+ "crimson": [220, 20, 60],
1537
+ "cyan": [0, 255, 255],
1538
+ "darkblue": [0, 0, 139],
1539
+ "darkcyan": [0, 139, 139],
1540
+ "darkgoldenrod": [184, 134, 11],
1541
+ "darkgray": [169, 169, 169],
1542
+ "darkgreen": [0, 100, 0],
1543
+ "darkgrey": [169, 169, 169],
1544
+ "darkkhaki": [189, 183, 107],
1545
+ "darkmagenta": [139, 0, 139],
1546
+ "darkolivegreen": [85, 107, 47],
1547
+ "darkorange": [255, 140, 0],
1548
+ "darkorchid": [153, 50, 204],
1549
+ "darkred": [139, 0, 0],
1550
+ "darksalmon": [233, 150, 122],
1551
+ "darkseagreen": [143, 188, 143],
1552
+ "darkslateblue": [72, 61, 139],
1553
+ "darkslategray": [47, 79, 79],
1554
+ "darkslategrey": [47, 79, 79],
1555
+ "darkturquoise": [0, 206, 209],
1556
+ "darkviolet": [148, 0, 211],
1557
+ "deeppink": [255, 20, 147],
1558
+ "deepskyblue": [0, 191, 255],
1559
+ "dimgray": [105, 105, 105],
1560
+ "dimgrey": [105, 105, 105],
1561
+ "dodgerblue": [30, 144, 255],
1562
+ "firebrick": [178, 34, 34],
1563
+ "floralwhite": [255, 250, 240],
1564
+ "forestgreen": [34, 139, 34],
1565
+ "fuchsia": [255, 0, 255],
1566
+ "gainsboro": [220, 220, 220],
1567
+ "ghostwhite": [248, 248, 255],
1568
+ "gold": [255, 215, 0],
1569
+ "goldenrod": [218, 165, 32],
1570
+ "gray": [128, 128, 128],
1571
+ "green": [0, 128, 0],
1572
+ "greenyellow": [173, 255, 47],
1573
+ "grey": [128, 128, 128],
1574
+ "honeydew": [240, 255, 240],
1575
+ "hotpink": [255, 105, 180],
1576
+ "indianred": [205, 92, 92],
1577
+ "indigo": [75, 0, 130],
1578
+ "ivory": [255, 255, 240],
1579
+ "khaki": [240, 230, 140],
1580
+ "lavender": [230, 230, 250],
1581
+ "lavenderblush": [255, 240, 245],
1582
+ "lawngreen": [124, 252, 0],
1583
+ "lemonchiffon": [255, 250, 205],
1584
+ "lightblue": [173, 216, 230],
1585
+ "lightcoral": [240, 128, 128],
1586
+ "lightcyan": [224, 255, 255],
1587
+ "lightgoldenrodyellow": [250, 250, 210],
1588
+ "lightgray": [211, 211, 211],
1589
+ "lightgreen": [144, 238, 144],
1590
+ "lightgrey": [211, 211, 211],
1591
+ "lightpink": [255, 182, 193],
1592
+ "lightsalmon": [255, 160, 122],
1593
+ "lightseagreen": [32, 178, 170],
1594
+ "lightskyblue": [135, 206, 250],
1595
+ "lightslategray": [119, 136, 153],
1596
+ "lightslategrey": [119, 136, 153],
1597
+ "lightsteelblue": [176, 196, 222],
1598
+ "lightyellow": [255, 255, 224],
1599
+ "lime": [0, 255, 0],
1600
+ "limegreen": [50, 205, 50],
1601
+ "linen": [250, 240, 230],
1602
+ "magenta": [255, 0, 255],
1603
+ "maroon": [128, 0, 0],
1604
+ "mediumaquamarine": [102, 205, 170],
1605
+ "mediumblue": [0, 0, 205],
1606
+ "mediumorchid": [186, 85, 211],
1607
+ "mediumpurple": [147, 112, 219],
1608
+ "mediumseagreen": [60, 179, 113],
1609
+ "mediumslateblue": [123, 104, 238],
1610
+ "mediumspringgreen": [0, 250, 154],
1611
+ "mediumturquoise": [72, 209, 204],
1612
+ "mediumvioletred": [199, 21, 133],
1613
+ "midnightblue": [25, 25, 112],
1614
+ "mintcream": [245, 255, 250],
1615
+ "mistyrose": [255, 228, 225],
1616
+ "moccasin": [255, 228, 181],
1617
+ "navajowhite": [255, 222, 173],
1618
+ "navy": [0, 0, 128],
1619
+ "oldlace": [253, 245, 230],
1620
+ "olive": [128, 128, 0],
1621
+ "olivedrab": [107, 142, 35],
1622
+ "orange": [255, 165, 0],
1623
+ "orangered": [255, 69, 0],
1624
+ "orchid": [218, 112, 214],
1625
+ "palegoldenrod": [238, 232, 170],
1626
+ "palegreen": [152, 251, 152],
1627
+ "paleturquoise": [175, 238, 238],
1628
+ "palevioletred": [219, 112, 147],
1629
+ "papayawhip": [255, 239, 213],
1630
+ "peachpuff": [255, 218, 185],
1631
+ "peru": [205, 133, 63],
1632
+ "pink": [255, 192, 203],
1633
+ "plum": [221, 160, 221],
1634
+ "powderblue": [176, 224, 230],
1635
+ "purple": [128, 0, 128],
1636
+ "rebeccapurple": [102, 51, 153],
1637
+ "red": [255, 0, 0],
1638
+ "rosybrown": [188, 143, 143],
1639
+ "royalblue": [65, 105, 225],
1640
+ "saddlebrown": [139, 69, 19],
1641
+ "salmon": [250, 128, 114],
1642
+ "sandybrown": [244, 164, 96],
1643
+ "seagreen": [46, 139, 87],
1644
+ "seashell": [255, 245, 238],
1645
+ "sienna": [160, 82, 45],
1646
+ "silver": [192, 192, 192],
1647
+ "skyblue": [135, 206, 235],
1648
+ "slateblue": [106, 90, 205],
1649
+ "slategray": [112, 128, 144],
1650
+ "slategrey": [112, 128, 144],
1651
+ "snow": [255, 250, 250],
1652
+ "springgreen": [0, 255, 127],
1653
+ "steelblue": [70, 130, 180],
1654
+ "tan": [210, 180, 140],
1655
+ "teal": [0, 128, 128],
1656
+ "thistle": [216, 191, 216],
1657
+ "tomato": [255, 99, 71],
1658
+ "turquoise": [64, 224, 208],
1659
+ "violet": [238, 130, 238],
1660
+ "wheat": [245, 222, 179],
1661
+ "white": [255, 255, 255],
1662
+ "whitesmoke": [245, 245, 245],
1663
+ "yellow": [255, 255, 0],
1664
+ "yellowgreen": [154, 205, 50]
1665
+ };
1666
+
1667
+ },{}],6:[function(require,module,exports){
1668
+ //! moment.js
1669
+ //! version : 2.18.1
1670
+ //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
1671
+ //! license : MIT
1672
+ //! momentjs.com
1673
+
1674
+ ;(function (global, factory) {
1675
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
1676
+ typeof define === 'function' && define.amd ? define(factory) :
1677
+ global.moment = factory()
1678
+ }(this, (function () { 'use strict';
1679
+
1680
+ var hookCallback;
1681
+
1682
+ function hooks () {
1683
+ return hookCallback.apply(null, arguments);
1684
+ }
1685
+
1686
+ // This is done to register the method called with moment()
1687
+ // without creating circular dependencies.
1688
+ function setHookCallback (callback) {
1689
+ hookCallback = callback;
1690
+ }
1691
+
1692
+ function isArray(input) {
1693
+ return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
1694
+ }
1695
+
1696
+ function isObject(input) {
1697
+ // IE8 will treat undefined and null as object if it wasn't for
1698
+ // input != null
1699
+ return input != null && Object.prototype.toString.call(input) === '[object Object]';
1700
+ }
1701
+
1702
+ function isObjectEmpty(obj) {
1703
+ var k;
1704
+ for (k in obj) {
1705
+ // even if its not own property I'd still call it non-empty
1706
+ return false;
1707
+ }
1708
+ return true;
1709
+ }
1710
+
1711
+ function isUndefined(input) {
1712
+ return input === void 0;
1713
+ }
1714
+
1715
+ function isNumber(input) {
1716
+ return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
1717
+ }
1718
+
1719
+ function isDate(input) {
1720
+ return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
1721
+ }
1722
+
1723
+ function map(arr, fn) {
1724
+ var res = [], i;
1725
+ for (i = 0; i < arr.length; ++i) {
1726
+ res.push(fn(arr[i], i));
1727
+ }
1728
+ return res;
1729
+ }
1730
+
1731
+ function hasOwnProp(a, b) {
1732
+ return Object.prototype.hasOwnProperty.call(a, b);
1733
+ }
1734
+
1735
+ function extend(a, b) {
1736
+ for (var i in b) {
1737
+ if (hasOwnProp(b, i)) {
1738
+ a[i] = b[i];
1739
+ }
1740
+ }
1741
+
1742
+ if (hasOwnProp(b, 'toString')) {
1743
+ a.toString = b.toString;
1744
+ }
1745
+
1746
+ if (hasOwnProp(b, 'valueOf')) {
1747
+ a.valueOf = b.valueOf;
1748
+ }
1749
+
1750
+ return a;
1751
+ }
1752
+
1753
+ function createUTC (input, format, locale, strict) {
1754
+ return createLocalOrUTC(input, format, locale, strict, true).utc();
1755
+ }
1756
+
1757
+ function defaultParsingFlags() {
1758
+ // We need to deep clone this object.
1759
+ return {
1760
+ empty : false,
1761
+ unusedTokens : [],
1762
+ unusedInput : [],
1763
+ overflow : -2,
1764
+ charsLeftOver : 0,
1765
+ nullInput : false,
1766
+ invalidMonth : null,
1767
+ invalidFormat : false,
1768
+ userInvalidated : false,
1769
+ iso : false,
1770
+ parsedDateParts : [],
1771
+ meridiem : null,
1772
+ rfc2822 : false,
1773
+ weekdayMismatch : false
1774
+ };
1775
+ }
1776
+
1777
+ function getParsingFlags(m) {
1778
+ if (m._pf == null) {
1779
+ m._pf = defaultParsingFlags();
1780
+ }
1781
+ return m._pf;
1782
+ }
1783
+
1784
+ var some;
1785
+ if (Array.prototype.some) {
1786
+ some = Array.prototype.some;
1787
+ } else {
1788
+ some = function (fun) {
1789
+ var t = Object(this);
1790
+ var len = t.length >>> 0;
1791
+
1792
+ for (var i = 0; i < len; i++) {
1793
+ if (i in t && fun.call(this, t[i], i, t)) {
1794
+ return true;
1795
+ }
1796
+ }
1797
+
1798
+ return false;
1799
+ };
1800
+ }
1801
+
1802
+ var some$1 = some;
1803
+
1804
+ function isValid(m) {
1805
+ if (m._isValid == null) {
1806
+ var flags = getParsingFlags(m);
1807
+ var parsedParts = some$1.call(flags.parsedDateParts, function (i) {
1808
+ return i != null;
1809
+ });
1810
+ var isNowValid = !isNaN(m._d.getTime()) &&
1811
+ flags.overflow < 0 &&
1812
+ !flags.empty &&
1813
+ !flags.invalidMonth &&
1814
+ !flags.invalidWeekday &&
1815
+ !flags.nullInput &&
1816
+ !flags.invalidFormat &&
1817
+ !flags.userInvalidated &&
1818
+ (!flags.meridiem || (flags.meridiem && parsedParts));
1819
+
1820
+ if (m._strict) {
1821
+ isNowValid = isNowValid &&
1822
+ flags.charsLeftOver === 0 &&
1823
+ flags.unusedTokens.length === 0 &&
1824
+ flags.bigHour === undefined;
1825
+ }
1826
+
1827
+ if (Object.isFrozen == null || !Object.isFrozen(m)) {
1828
+ m._isValid = isNowValid;
1829
+ }
1830
+ else {
1831
+ return isNowValid;
1832
+ }
1833
+ }
1834
+ return m._isValid;
1835
+ }
1836
+
1837
+ function createInvalid (flags) {
1838
+ var m = createUTC(NaN);
1839
+ if (flags != null) {
1840
+ extend(getParsingFlags(m), flags);
1841
+ }
1842
+ else {
1843
+ getParsingFlags(m).userInvalidated = true;
1844
+ }
1845
+
1846
+ return m;
1847
+ }
1848
+
1849
+ // Plugins that add properties should also add the key here (null value),
1850
+ // so we can properly clone ourselves.
1851
+ var momentProperties = hooks.momentProperties = [];
1852
+
1853
+ function copyConfig(to, from) {
1854
+ var i, prop, val;
1855
+
1856
+ if (!isUndefined(from._isAMomentObject)) {
1857
+ to._isAMomentObject = from._isAMomentObject;
1858
+ }
1859
+ if (!isUndefined(from._i)) {
1860
+ to._i = from._i;
1861
+ }
1862
+ if (!isUndefined(from._f)) {
1863
+ to._f = from._f;
1864
+ }
1865
+ if (!isUndefined(from._l)) {
1866
+ to._l = from._l;
1867
+ }
1868
+ if (!isUndefined(from._strict)) {
1869
+ to._strict = from._strict;
1870
+ }
1871
+ if (!isUndefined(from._tzm)) {
1872
+ to._tzm = from._tzm;
1873
+ }
1874
+ if (!isUndefined(from._isUTC)) {
1875
+ to._isUTC = from._isUTC;
1876
+ }
1877
+ if (!isUndefined(from._offset)) {
1878
+ to._offset = from._offset;
1879
+ }
1880
+ if (!isUndefined(from._pf)) {
1881
+ to._pf = getParsingFlags(from);
1882
+ }
1883
+ if (!isUndefined(from._locale)) {
1884
+ to._locale = from._locale;
1885
+ }
1886
+
1887
+ if (momentProperties.length > 0) {
1888
+ for (i = 0; i < momentProperties.length; i++) {
1889
+ prop = momentProperties[i];
1890
+ val = from[prop];
1891
+ if (!isUndefined(val)) {
1892
+ to[prop] = val;
1893
+ }
1894
+ }
1895
+ }
1896
+
1897
+ return to;
1898
+ }
1899
+
1900
+ var updateInProgress = false;
1901
+
1902
+ // Moment prototype object
1903
+ function Moment(config) {
1904
+ copyConfig(this, config);
1905
+ this._d = new Date(config._d != null ? config._d.getTime() : NaN);
1906
+ if (!this.isValid()) {
1907
+ this._d = new Date(NaN);
1908
+ }
1909
+ // Prevent infinite loop in case updateOffset creates new moment
1910
+ // objects.
1911
+ if (updateInProgress === false) {
1912
+ updateInProgress = true;
1913
+ hooks.updateOffset(this);
1914
+ updateInProgress = false;
1915
+ }
1916
+ }
1917
+
1918
+ function isMoment (obj) {
1919
+ return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
1920
+ }
1921
+
1922
+ function absFloor (number) {
1923
+ if (number < 0) {
1924
+ // -0 -> 0
1925
+ return Math.ceil(number) || 0;
1926
+ } else {
1927
+ return Math.floor(number);
1928
+ }
1929
+ }
1930
+
1931
+ function toInt(argumentForCoercion) {
1932
+ var coercedNumber = +argumentForCoercion,
1933
+ value = 0;
1934
+
1935
+ if (coercedNumber !== 0 && isFinite(coercedNumber)) {
1936
+ value = absFloor(coercedNumber);
1937
+ }
1938
+
1939
+ return value;
1940
+ }
1941
+
1942
+ // compare two arrays, return the number of differences
1943
+ function compareArrays(array1, array2, dontConvert) {
1944
+ var len = Math.min(array1.length, array2.length),
1945
+ lengthDiff = Math.abs(array1.length - array2.length),
1946
+ diffs = 0,
1947
+ i;
1948
+ for (i = 0; i < len; i++) {
1949
+ if ((dontConvert && array1[i] !== array2[i]) ||
1950
+ (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
1951
+ diffs++;
1952
+ }
1953
+ }
1954
+ return diffs + lengthDiff;
1955
+ }
1956
+
1957
+ function warn(msg) {
1958
+ if (hooks.suppressDeprecationWarnings === false &&
1959
+ (typeof console !== 'undefined') && console.warn) {
1960
+ console.warn('Deprecation warning: ' + msg);
1961
+ }
1962
+ }
1963
+
1964
+ function deprecate(msg, fn) {
1965
+ var firstTime = true;
1966
+
1967
+ return extend(function () {
1968
+ if (hooks.deprecationHandler != null) {
1969
+ hooks.deprecationHandler(null, msg);
1970
+ }
1971
+ if (firstTime) {
1972
+ var args = [];
1973
+ var arg;
1974
+ for (var i = 0; i < arguments.length; i++) {
1975
+ arg = '';
1976
+ if (typeof arguments[i] === 'object') {
1977
+ arg += '\n[' + i + '] ';
1978
+ for (var key in arguments[0]) {
1979
+ arg += key + ': ' + arguments[0][key] + ', ';
1980
+ }
1981
+ arg = arg.slice(0, -2); // Remove trailing comma and space
1982
+ } else {
1983
+ arg = arguments[i];
1984
+ }
1985
+ args.push(arg);
1986
+ }
1987
+ warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
1988
+ firstTime = false;
1989
+ }
1990
+ return fn.apply(this, arguments);
1991
+ }, fn);
1992
+ }
1993
+
1994
+ var deprecations = {};
1995
+
1996
+ function deprecateSimple(name, msg) {
1997
+ if (hooks.deprecationHandler != null) {
1998
+ hooks.deprecationHandler(name, msg);
1999
+ }
2000
+ if (!deprecations[name]) {
2001
+ warn(msg);
2002
+ deprecations[name] = true;
2003
+ }
2004
+ }
2005
+
2006
+ hooks.suppressDeprecationWarnings = false;
2007
+ hooks.deprecationHandler = null;
2008
+
2009
+ function isFunction(input) {
2010
+ return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
2011
+ }
2012
+
2013
+ function set (config) {
2014
+ var prop, i;
2015
+ for (i in config) {
2016
+ prop = config[i];
2017
+ if (isFunction(prop)) {
2018
+ this[i] = prop;
2019
+ } else {
2020
+ this['_' + i] = prop;
2021
+ }
2022
+ }
2023
+ this._config = config;
2024
+ // Lenient ordinal parsing accepts just a number in addition to
2025
+ // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
2026
+ // TODO: Remove "ordinalParse" fallback in next major release.
2027
+ this._dayOfMonthOrdinalParseLenient = new RegExp(
2028
+ (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
2029
+ '|' + (/\d{1,2}/).source);
2030
+ }
2031
+
2032
+ function mergeConfigs(parentConfig, childConfig) {
2033
+ var res = extend({}, parentConfig), prop;
2034
+ for (prop in childConfig) {
2035
+ if (hasOwnProp(childConfig, prop)) {
2036
+ if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
2037
+ res[prop] = {};
2038
+ extend(res[prop], parentConfig[prop]);
2039
+ extend(res[prop], childConfig[prop]);
2040
+ } else if (childConfig[prop] != null) {
2041
+ res[prop] = childConfig[prop];
2042
+ } else {
2043
+ delete res[prop];
2044
+ }
2045
+ }
2046
+ }
2047
+ for (prop in parentConfig) {
2048
+ if (hasOwnProp(parentConfig, prop) &&
2049
+ !hasOwnProp(childConfig, prop) &&
2050
+ isObject(parentConfig[prop])) {
2051
+ // make sure changes to properties don't modify parent config
2052
+ res[prop] = extend({}, res[prop]);
2053
+ }
2054
+ }
2055
+ return res;
2056
+ }
2057
+
2058
+ function Locale(config) {
2059
+ if (config != null) {
2060
+ this.set(config);
2061
+ }
2062
+ }
2063
+
2064
+ var keys;
2065
+
2066
+ if (Object.keys) {
2067
+ keys = Object.keys;
2068
+ } else {
2069
+ keys = function (obj) {
2070
+ var i, res = [];
2071
+ for (i in obj) {
2072
+ if (hasOwnProp(obj, i)) {
2073
+ res.push(i);
2074
+ }
2075
+ }
2076
+ return res;
2077
+ };
2078
+ }
2079
+
2080
+ var keys$1 = keys;
2081
+
2082
+ var defaultCalendar = {
2083
+ sameDay : '[Today at] LT',
2084
+ nextDay : '[Tomorrow at] LT',
2085
+ nextWeek : 'dddd [at] LT',
2086
+ lastDay : '[Yesterday at] LT',
2087
+ lastWeek : '[Last] dddd [at] LT',
2088
+ sameElse : 'L'
2089
+ };
2090
+
2091
+ function calendar (key, mom, now) {
2092
+ var output = this._calendar[key] || this._calendar['sameElse'];
2093
+ return isFunction(output) ? output.call(mom, now) : output;
2094
+ }
2095
+
2096
+ var defaultLongDateFormat = {
2097
+ LTS : 'h:mm:ss A',
2098
+ LT : 'h:mm A',
2099
+ L : 'MM/DD/YYYY',
2100
+ LL : 'MMMM D, YYYY',
2101
+ LLL : 'MMMM D, YYYY h:mm A',
2102
+ LLLL : 'dddd, MMMM D, YYYY h:mm A'
2103
+ };
2104
+
2105
+ function longDateFormat (key) {
2106
+ var format = this._longDateFormat[key],
2107
+ formatUpper = this._longDateFormat[key.toUpperCase()];
2108
+
2109
+ if (format || !formatUpper) {
2110
+ return format;
2111
+ }
2112
+
2113
+ this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
2114
+ return val.slice(1);
2115
+ });
2116
+
2117
+ return this._longDateFormat[key];
2118
+ }
2119
+
2120
+ var defaultInvalidDate = 'Invalid date';
2121
+
2122
+ function invalidDate () {
2123
+ return this._invalidDate;
2124
+ }
2125
+
2126
+ var defaultOrdinal = '%d';
2127
+ var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
2128
+
2129
+ function ordinal (number) {
2130
+ return this._ordinal.replace('%d', number);
2131
+ }
2132
+
2133
+ var defaultRelativeTime = {
2134
+ future : 'in %s',
2135
+ past : '%s ago',
2136
+ s : 'a few seconds',
2137
+ ss : '%d seconds',
2138
+ m : 'a minute',
2139
+ mm : '%d minutes',
2140
+ h : 'an hour',
2141
+ hh : '%d hours',
2142
+ d : 'a day',
2143
+ dd : '%d days',
2144
+ M : 'a month',
2145
+ MM : '%d months',
2146
+ y : 'a year',
2147
+ yy : '%d years'
2148
+ };
2149
+
2150
+ function relativeTime (number, withoutSuffix, string, isFuture) {
2151
+ var output = this._relativeTime[string];
2152
+ return (isFunction(output)) ?
2153
+ output(number, withoutSuffix, string, isFuture) :
2154
+ output.replace(/%d/i, number);
2155
+ }
2156
+
2157
+ function pastFuture (diff, output) {
2158
+ var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
2159
+ return isFunction(format) ? format(output) : format.replace(/%s/i, output);
2160
+ }
2161
+
2162
+ var aliases = {};
2163
+
2164
+ function addUnitAlias (unit, shorthand) {
2165
+ var lowerCase = unit.toLowerCase();
2166
+ aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
2167
+ }
2168
+
2169
+ function normalizeUnits(units) {
2170
+ return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
2171
+ }
2172
+
2173
+ function normalizeObjectUnits(inputObject) {
2174
+ var normalizedInput = {},
2175
+ normalizedProp,
2176
+ prop;
2177
+
2178
+ for (prop in inputObject) {
2179
+ if (hasOwnProp(inputObject, prop)) {
2180
+ normalizedProp = normalizeUnits(prop);
2181
+ if (normalizedProp) {
2182
+ normalizedInput[normalizedProp] = inputObject[prop];
2183
+ }
2184
+ }
2185
+ }
2186
+
2187
+ return normalizedInput;
2188
+ }
2189
+
2190
+ var priorities = {};
2191
+
2192
+ function addUnitPriority(unit, priority) {
2193
+ priorities[unit] = priority;
2194
+ }
2195
+
2196
+ function getPrioritizedUnits(unitsObj) {
2197
+ var units = [];
2198
+ for (var u in unitsObj) {
2199
+ units.push({unit: u, priority: priorities[u]});
2200
+ }
2201
+ units.sort(function (a, b) {
2202
+ return a.priority - b.priority;
2203
+ });
2204
+ return units;
2205
+ }
2206
+
2207
+ function makeGetSet (unit, keepTime) {
2208
+ return function (value) {
2209
+ if (value != null) {
2210
+ set$1(this, unit, value);
2211
+ hooks.updateOffset(this, keepTime);
2212
+ return this;
2213
+ } else {
2214
+ return get(this, unit);
2215
+ }
2216
+ };
2217
+ }
2218
+
2219
+ function get (mom, unit) {
2220
+ return mom.isValid() ?
2221
+ mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
2222
+ }
2223
+
2224
+ function set$1 (mom, unit, value) {
2225
+ if (mom.isValid()) {
2226
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
2227
+ }
2228
+ }
2229
+
2230
+ // MOMENTS
2231
+
2232
+ function stringGet (units) {
2233
+ units = normalizeUnits(units);
2234
+ if (isFunction(this[units])) {
2235
+ return this[units]();
2236
+ }
2237
+ return this;
2238
+ }
2239
+
2240
+
2241
+ function stringSet (units, value) {
2242
+ if (typeof units === 'object') {
2243
+ units = normalizeObjectUnits(units);
2244
+ var prioritized = getPrioritizedUnits(units);
2245
+ for (var i = 0; i < prioritized.length; i++) {
2246
+ this[prioritized[i].unit](units[prioritized[i].unit]);
2247
+ }
2248
+ } else {
2249
+ units = normalizeUnits(units);
2250
+ if (isFunction(this[units])) {
2251
+ return this[units](value);
2252
+ }
2253
+ }
2254
+ return this;
2255
+ }
2256
+
2257
+ function zeroFill(number, targetLength, forceSign) {
2258
+ var absNumber = '' + Math.abs(number),
2259
+ zerosToFill = targetLength - absNumber.length,
2260
+ sign = number >= 0;
2261
+ return (sign ? (forceSign ? '+' : '') : '-') +
2262
+ Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
2263
+ }
2264
+
2265
+ var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
2266
+
2267
+ var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
2268
+
2269
+ var formatFunctions = {};
2270
+
2271
+ var formatTokenFunctions = {};
2272
+
2273
+ // token: 'M'
2274
+ // padded: ['MM', 2]
2275
+ // ordinal: 'Mo'
2276
+ // callback: function () { this.month() + 1 }
2277
+ function addFormatToken (token, padded, ordinal, callback) {
2278
+ var func = callback;
2279
+ if (typeof callback === 'string') {
2280
+ func = function () {
2281
+ return this[callback]();
2282
+ };
2283
+ }
2284
+ if (token) {
2285
+ formatTokenFunctions[token] = func;
2286
+ }
2287
+ if (padded) {
2288
+ formatTokenFunctions[padded[0]] = function () {
2289
+ return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
2290
+ };
2291
+ }
2292
+ if (ordinal) {
2293
+ formatTokenFunctions[ordinal] = function () {
2294
+ return this.localeData().ordinal(func.apply(this, arguments), token);
2295
+ };
2296
+ }
2297
+ }
2298
+
2299
+ function removeFormattingTokens(input) {
2300
+ if (input.match(/\[[\s\S]/)) {
2301
+ return input.replace(/^\[|\]$/g, '');
2302
+ }
2303
+ return input.replace(/\\/g, '');
2304
+ }
2305
+
2306
+ function makeFormatFunction(format) {
2307
+ var array = format.match(formattingTokens), i, length;
2308
+
2309
+ for (i = 0, length = array.length; i < length; i++) {
2310
+ if (formatTokenFunctions[array[i]]) {
2311
+ array[i] = formatTokenFunctions[array[i]];
2312
+ } else {
2313
+ array[i] = removeFormattingTokens(array[i]);
2314
+ }
2315
+ }
2316
+
2317
+ return function (mom) {
2318
+ var output = '', i;
2319
+ for (i = 0; i < length; i++) {
2320
+ output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
2321
+ }
2322
+ return output;
2323
+ };
2324
+ }
2325
+
2326
+ // format date using native date object
2327
+ function formatMoment(m, format) {
2328
+ if (!m.isValid()) {
2329
+ return m.localeData().invalidDate();
2330
+ }
2331
+
2332
+ format = expandFormat(format, m.localeData());
2333
+ formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
2334
+
2335
+ return formatFunctions[format](m);
2336
+ }
2337
+
2338
+ function expandFormat(format, locale) {
2339
+ var i = 5;
2340
+
2341
+ function replaceLongDateFormatTokens(input) {
2342
+ return locale.longDateFormat(input) || input;
2343
+ }
2344
+
2345
+ localFormattingTokens.lastIndex = 0;
2346
+ while (i >= 0 && localFormattingTokens.test(format)) {
2347
+ format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
2348
+ localFormattingTokens.lastIndex = 0;
2349
+ i -= 1;
2350
+ }
2351
+
2352
+ return format;
2353
+ }
2354
+
2355
+ var match1 = /\d/; // 0 - 9
2356
+ var match2 = /\d\d/; // 00 - 99
2357
+ var match3 = /\d{3}/; // 000 - 999
2358
+ var match4 = /\d{4}/; // 0000 - 9999
2359
+ var match6 = /[+-]?\d{6}/; // -999999 - 999999
2360
+ var match1to2 = /\d\d?/; // 0 - 99
2361
+ var match3to4 = /\d\d\d\d?/; // 999 - 9999
2362
+ var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999
2363
+ var match1to3 = /\d{1,3}/; // 0 - 999
2364
+ var match1to4 = /\d{1,4}/; // 0 - 9999
2365
+ var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
2366
+
2367
+ var matchUnsigned = /\d+/; // 0 - inf
2368
+ var matchSigned = /[+-]?\d+/; // -inf - inf
2369
+
2370
+ var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
2371
+ var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
2372
+
2373
+ var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
2374
+
2375
+ // any word (or two) characters or numbers including two/three word month in arabic.
2376
+ // includes scottish gaelic two word and hyphenated months
2377
+ var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
2378
+
2379
+
2380
+ var regexes = {};
2381
+
2382
+ function addRegexToken (token, regex, strictRegex) {
2383
+ regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
2384
+ return (isStrict && strictRegex) ? strictRegex : regex;
2385
+ };
2386
+ }
2387
+
2388
+ function getParseRegexForToken (token, config) {
2389
+ if (!hasOwnProp(regexes, token)) {
2390
+ return new RegExp(unescapeFormat(token));
2391
+ }
2392
+
2393
+ return regexes[token](config._strict, config._locale);
2394
+ }
2395
+
2396
+ // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
2397
+ function unescapeFormat(s) {
2398
+ return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
2399
+ return p1 || p2 || p3 || p4;
2400
+ }));
2401
+ }
2402
+
2403
+ function regexEscape(s) {
2404
+ return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
2405
+ }
2406
+
2407
+ var tokens = {};
2408
+
2409
+ function addParseToken (token, callback) {
2410
+ var i, func = callback;
2411
+ if (typeof token === 'string') {
2412
+ token = [token];
2413
+ }
2414
+ if (isNumber(callback)) {
2415
+ func = function (input, array) {
2416
+ array[callback] = toInt(input);
2417
+ };
2418
+ }
2419
+ for (i = 0; i < token.length; i++) {
2420
+ tokens[token[i]] = func;
2421
+ }
2422
+ }
2423
+
2424
+ function addWeekParseToken (token, callback) {
2425
+ addParseToken(token, function (input, array, config, token) {
2426
+ config._w = config._w || {};
2427
+ callback(input, config._w, config, token);
2428
+ });
2429
+ }
2430
+
2431
+ function addTimeToArrayFromToken(token, input, config) {
2432
+ if (input != null && hasOwnProp(tokens, token)) {
2433
+ tokens[token](input, config._a, config, token);
2434
+ }
2435
+ }
2436
+
2437
+ var YEAR = 0;
2438
+ var MONTH = 1;
2439
+ var DATE = 2;
2440
+ var HOUR = 3;
2441
+ var MINUTE = 4;
2442
+ var SECOND = 5;
2443
+ var MILLISECOND = 6;
2444
+ var WEEK = 7;
2445
+ var WEEKDAY = 8;
2446
+
2447
+ var indexOf;
2448
+
2449
+ if (Array.prototype.indexOf) {
2450
+ indexOf = Array.prototype.indexOf;
2451
+ } else {
2452
+ indexOf = function (o) {
2453
+ // I know
2454
+ var i;
2455
+ for (i = 0; i < this.length; ++i) {
2456
+ if (this[i] === o) {
2457
+ return i;
2458
+ }
2459
+ }
2460
+ return -1;
2461
+ };
2462
+ }
2463
+
2464
+ var indexOf$1 = indexOf;
2465
+
2466
+ function daysInMonth(year, month) {
2467
+ return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
2468
+ }
2469
+
2470
+ // FORMATTING
2471
+
2472
+ addFormatToken('M', ['MM', 2], 'Mo', function () {
2473
+ return this.month() + 1;
2474
+ });
2475
+
2476
+ addFormatToken('MMM', 0, 0, function (format) {
2477
+ return this.localeData().monthsShort(this, format);
2478
+ });
2479
+
2480
+ addFormatToken('MMMM', 0, 0, function (format) {
2481
+ return this.localeData().months(this, format);
2482
+ });
2483
+
2484
+ // ALIASES
2485
+
2486
+ addUnitAlias('month', 'M');
2487
+
2488
+ // PRIORITY
2489
+
2490
+ addUnitPriority('month', 8);
2491
+
2492
+ // PARSING
2493
+
2494
+ addRegexToken('M', match1to2);
2495
+ addRegexToken('MM', match1to2, match2);
2496
+ addRegexToken('MMM', function (isStrict, locale) {
2497
+ return locale.monthsShortRegex(isStrict);
2498
+ });
2499
+ addRegexToken('MMMM', function (isStrict, locale) {
2500
+ return locale.monthsRegex(isStrict);
2501
+ });
2502
+
2503
+ addParseToken(['M', 'MM'], function (input, array) {
2504
+ array[MONTH] = toInt(input) - 1;
2505
+ });
2506
+
2507
+ addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
2508
+ var month = config._locale.monthsParse(input, token, config._strict);
2509
+ // if we didn't find a month name, mark the date as invalid.
2510
+ if (month != null) {
2511
+ array[MONTH] = month;
2512
+ } else {
2513
+ getParsingFlags(config).invalidMonth = input;
2514
+ }
2515
+ });
2516
+
2517
+ // LOCALES
2518
+
2519
+ var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
2520
+ var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
2521
+ function localeMonths (m, format) {
2522
+ if (!m) {
2523
+ return isArray(this._months) ? this._months :
2524
+ this._months['standalone'];
2525
+ }
2526
+ return isArray(this._months) ? this._months[m.month()] :
2527
+ this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
2528
+ }
2529
+
2530
+ var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
2531
+ function localeMonthsShort (m, format) {
2532
+ if (!m) {
2533
+ return isArray(this._monthsShort) ? this._monthsShort :
2534
+ this._monthsShort['standalone'];
2535
+ }
2536
+ return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
2537
+ this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
2538
+ }
2539
+
2540
+ function handleStrictParse(monthName, format, strict) {
2541
+ var i, ii, mom, llc = monthName.toLocaleLowerCase();
2542
+ if (!this._monthsParse) {
2543
+ // this is not used
2544
+ this._monthsParse = [];
2545
+ this._longMonthsParse = [];
2546
+ this._shortMonthsParse = [];
2547
+ for (i = 0; i < 12; ++i) {
2548
+ mom = createUTC([2000, i]);
2549
+ this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
2550
+ this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
2551
+ }
2552
+ }
2553
+
2554
+ if (strict) {
2555
+ if (format === 'MMM') {
2556
+ ii = indexOf$1.call(this._shortMonthsParse, llc);
2557
+ return ii !== -1 ? ii : null;
2558
+ } else {
2559
+ ii = indexOf$1.call(this._longMonthsParse, llc);
2560
+ return ii !== -1 ? ii : null;
2561
+ }
2562
+ } else {
2563
+ if (format === 'MMM') {
2564
+ ii = indexOf$1.call(this._shortMonthsParse, llc);
2565
+ if (ii !== -1) {
2566
+ return ii;
2567
+ }
2568
+ ii = indexOf$1.call(this._longMonthsParse, llc);
2569
+ return ii !== -1 ? ii : null;
2570
+ } else {
2571
+ ii = indexOf$1.call(this._longMonthsParse, llc);
2572
+ if (ii !== -1) {
2573
+ return ii;
2574
+ }
2575
+ ii = indexOf$1.call(this._shortMonthsParse, llc);
2576
+ return ii !== -1 ? ii : null;
2577
+ }
2578
+ }
2579
+ }
2580
+
2581
+ function localeMonthsParse (monthName, format, strict) {
2582
+ var i, mom, regex;
2583
+
2584
+ if (this._monthsParseExact) {
2585
+ return handleStrictParse.call(this, monthName, format, strict);
2586
+ }
2587
+
2588
+ if (!this._monthsParse) {
2589
+ this._monthsParse = [];
2590
+ this._longMonthsParse = [];
2591
+ this._shortMonthsParse = [];
2592
+ }
2593
+
2594
+ // TODO: add sorting
2595
+ // Sorting makes sure if one month (or abbr) is a prefix of another
2596
+ // see sorting in computeMonthsParse
2597
+ for (i = 0; i < 12; i++) {
2598
+ // make the regex if we don't have it already
2599
+ mom = createUTC([2000, i]);
2600
+ if (strict && !this._longMonthsParse[i]) {
2601
+ this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
2602
+ this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
2603
+ }
2604
+ if (!strict && !this._monthsParse[i]) {
2605
+ regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
2606
+ this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
2607
+ }
2608
+ // test the regex
2609
+ if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
2610
+ return i;
2611
+ } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
2612
+ return i;
2613
+ } else if (!strict && this._monthsParse[i].test(monthName)) {
2614
+ return i;
2615
+ }
2616
+ }
2617
+ }
2618
+
2619
+ // MOMENTS
2620
+
2621
+ function setMonth (mom, value) {
2622
+ var dayOfMonth;
2623
+
2624
+ if (!mom.isValid()) {
2625
+ // No op
2626
+ return mom;
2627
+ }
2628
+
2629
+ if (typeof value === 'string') {
2630
+ if (/^\d+$/.test(value)) {
2631
+ value = toInt(value);
2632
+ } else {
2633
+ value = mom.localeData().monthsParse(value);
2634
+ // TODO: Another silent failure?
2635
+ if (!isNumber(value)) {
2636
+ return mom;
2637
+ }
2638
+ }
2639
+ }
2640
+
2641
+ dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
2642
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
2643
+ return mom;
2644
+ }
2645
+
2646
+ function getSetMonth (value) {
2647
+ if (value != null) {
2648
+ setMonth(this, value);
2649
+ hooks.updateOffset(this, true);
2650
+ return this;
2651
+ } else {
2652
+ return get(this, 'Month');
2653
+ }
2654
+ }
2655
+
2656
+ function getDaysInMonth () {
2657
+ return daysInMonth(this.year(), this.month());
2658
+ }
2659
+
2660
+ var defaultMonthsShortRegex = matchWord;
2661
+ function monthsShortRegex (isStrict) {
2662
+ if (this._monthsParseExact) {
2663
+ if (!hasOwnProp(this, '_monthsRegex')) {
2664
+ computeMonthsParse.call(this);
2665
+ }
2666
+ if (isStrict) {
2667
+ return this._monthsShortStrictRegex;
2668
+ } else {
2669
+ return this._monthsShortRegex;
2670
+ }
2671
+ } else {
2672
+ if (!hasOwnProp(this, '_monthsShortRegex')) {
2673
+ this._monthsShortRegex = defaultMonthsShortRegex;
2674
+ }
2675
+ return this._monthsShortStrictRegex && isStrict ?
2676
+ this._monthsShortStrictRegex : this._monthsShortRegex;
2677
+ }
2678
+ }
2679
+
2680
+ var defaultMonthsRegex = matchWord;
2681
+ function monthsRegex (isStrict) {
2682
+ if (this._monthsParseExact) {
2683
+ if (!hasOwnProp(this, '_monthsRegex')) {
2684
+ computeMonthsParse.call(this);
2685
+ }
2686
+ if (isStrict) {
2687
+ return this._monthsStrictRegex;
2688
+ } else {
2689
+ return this._monthsRegex;
2690
+ }
2691
+ } else {
2692
+ if (!hasOwnProp(this, '_monthsRegex')) {
2693
+ this._monthsRegex = defaultMonthsRegex;
2694
+ }
2695
+ return this._monthsStrictRegex && isStrict ?
2696
+ this._monthsStrictRegex : this._monthsRegex;
2697
+ }
2698
+ }
2699
+
2700
+ function computeMonthsParse () {
2701
+ function cmpLenRev(a, b) {
2702
+ return b.length - a.length;
2703
+ }
2704
+
2705
+ var shortPieces = [], longPieces = [], mixedPieces = [],
2706
+ i, mom;
2707
+ for (i = 0; i < 12; i++) {
2708
+ // make the regex if we don't have it already
2709
+ mom = createUTC([2000, i]);
2710
+ shortPieces.push(this.monthsShort(mom, ''));
2711
+ longPieces.push(this.months(mom, ''));
2712
+ mixedPieces.push(this.months(mom, ''));
2713
+ mixedPieces.push(this.monthsShort(mom, ''));
2714
+ }
2715
+ // Sorting makes sure if one month (or abbr) is a prefix of another it
2716
+ // will match the longer piece.
2717
+ shortPieces.sort(cmpLenRev);
2718
+ longPieces.sort(cmpLenRev);
2719
+ mixedPieces.sort(cmpLenRev);
2720
+ for (i = 0; i < 12; i++) {
2721
+ shortPieces[i] = regexEscape(shortPieces[i]);
2722
+ longPieces[i] = regexEscape(longPieces[i]);
2723
+ }
2724
+ for (i = 0; i < 24; i++) {
2725
+ mixedPieces[i] = regexEscape(mixedPieces[i]);
2726
+ }
2727
+
2728
+ this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
2729
+ this._monthsShortRegex = this._monthsRegex;
2730
+ this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
2731
+ this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
2732
+ }
2733
+
2734
+ // FORMATTING
2735
+
2736
+ addFormatToken('Y', 0, 0, function () {
2737
+ var y = this.year();
2738
+ return y <= 9999 ? '' + y : '+' + y;
2739
+ });
2740
+
2741
+ addFormatToken(0, ['YY', 2], 0, function () {
2742
+ return this.year() % 100;
2743
+ });
2744
+
2745
+ addFormatToken(0, ['YYYY', 4], 0, 'year');
2746
+ addFormatToken(0, ['YYYYY', 5], 0, 'year');
2747
+ addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
2748
+
2749
+ // ALIASES
2750
+
2751
+ addUnitAlias('year', 'y');
2752
+
2753
+ // PRIORITIES
2754
+
2755
+ addUnitPriority('year', 1);
2756
+
2757
+ // PARSING
2758
+
2759
+ addRegexToken('Y', matchSigned);
2760
+ addRegexToken('YY', match1to2, match2);
2761
+ addRegexToken('YYYY', match1to4, match4);
2762
+ addRegexToken('YYYYY', match1to6, match6);
2763
+ addRegexToken('YYYYYY', match1to6, match6);
2764
+
2765
+ addParseToken(['YYYYY', 'YYYYYY'], YEAR);
2766
+ addParseToken('YYYY', function (input, array) {
2767
+ array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
2768
+ });
2769
+ addParseToken('YY', function (input, array) {
2770
+ array[YEAR] = hooks.parseTwoDigitYear(input);
2771
+ });
2772
+ addParseToken('Y', function (input, array) {
2773
+ array[YEAR] = parseInt(input, 10);
2774
+ });
2775
+
2776
+ // HELPERS
2777
+
2778
+ function daysInYear(year) {
2779
+ return isLeapYear(year) ? 366 : 365;
2780
+ }
2781
+
2782
+ function isLeapYear(year) {
2783
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
2784
+ }
2785
+
2786
+ // HOOKS
2787
+
2788
+ hooks.parseTwoDigitYear = function (input) {
2789
+ return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
2790
+ };
2791
+
2792
+ // MOMENTS
2793
+
2794
+ var getSetYear = makeGetSet('FullYear', true);
2795
+
2796
+ function getIsLeapYear () {
2797
+ return isLeapYear(this.year());
2798
+ }
2799
+
2800
+ function createDate (y, m, d, h, M, s, ms) {
2801
+ // can't just apply() to create a date:
2802
+ // https://stackoverflow.com/q/181348
2803
+ var date = new Date(y, m, d, h, M, s, ms);
2804
+
2805
+ // the date constructor remaps years 0-99 to 1900-1999
2806
+ if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
2807
+ date.setFullYear(y);
2808
+ }
2809
+ return date;
2810
+ }
2811
+
2812
+ function createUTCDate (y) {
2813
+ var date = new Date(Date.UTC.apply(null, arguments));
2814
+
2815
+ // the Date.UTC function remaps years 0-99 to 1900-1999
2816
+ if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
2817
+ date.setUTCFullYear(y);
2818
+ }
2819
+ return date;
2820
+ }
2821
+
2822
+ // start-of-first-week - start-of-year
2823
+ function firstWeekOffset(year, dow, doy) {
2824
+ var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
2825
+ fwd = 7 + dow - doy,
2826
+ // first-week day local weekday -- which local weekday is fwd
2827
+ fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
2828
+
2829
+ return -fwdlw + fwd - 1;
2830
+ }
2831
+
2832
+ // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
2833
+ function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
2834
+ var localWeekday = (7 + weekday - dow) % 7,
2835
+ weekOffset = firstWeekOffset(year, dow, doy),
2836
+ dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
2837
+ resYear, resDayOfYear;
2838
+
2839
+ if (dayOfYear <= 0) {
2840
+ resYear = year - 1;
2841
+ resDayOfYear = daysInYear(resYear) + dayOfYear;
2842
+ } else if (dayOfYear > daysInYear(year)) {
2843
+ resYear = year + 1;
2844
+ resDayOfYear = dayOfYear - daysInYear(year);
2845
+ } else {
2846
+ resYear = year;
2847
+ resDayOfYear = dayOfYear;
2848
+ }
2849
+
2850
+ return {
2851
+ year: resYear,
2852
+ dayOfYear: resDayOfYear
2853
+ };
2854
+ }
2855
+
2856
+ function weekOfYear(mom, dow, doy) {
2857
+ var weekOffset = firstWeekOffset(mom.year(), dow, doy),
2858
+ week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
2859
+ resWeek, resYear;
2860
+
2861
+ if (week < 1) {
2862
+ resYear = mom.year() - 1;
2863
+ resWeek = week + weeksInYear(resYear, dow, doy);
2864
+ } else if (week > weeksInYear(mom.year(), dow, doy)) {
2865
+ resWeek = week - weeksInYear(mom.year(), dow, doy);
2866
+ resYear = mom.year() + 1;
2867
+ } else {
2868
+ resYear = mom.year();
2869
+ resWeek = week;
2870
+ }
2871
+
2872
+ return {
2873
+ week: resWeek,
2874
+ year: resYear
2875
+ };
2876
+ }
2877
+
2878
+ function weeksInYear(year, dow, doy) {
2879
+ var weekOffset = firstWeekOffset(year, dow, doy),
2880
+ weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
2881
+ return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
2882
+ }
2883
+
2884
+ // FORMATTING
2885
+
2886
+ addFormatToken('w', ['ww', 2], 'wo', 'week');
2887
+ addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
2888
+
2889
+ // ALIASES
2890
+
2891
+ addUnitAlias('week', 'w');
2892
+ addUnitAlias('isoWeek', 'W');
2893
+
2894
+ // PRIORITIES
2895
+
2896
+ addUnitPriority('week', 5);
2897
+ addUnitPriority('isoWeek', 5);
2898
+
2899
+ // PARSING
2900
+
2901
+ addRegexToken('w', match1to2);
2902
+ addRegexToken('ww', match1to2, match2);
2903
+ addRegexToken('W', match1to2);
2904
+ addRegexToken('WW', match1to2, match2);
2905
+
2906
+ addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
2907
+ week[token.substr(0, 1)] = toInt(input);
2908
+ });
2909
+
2910
+ // HELPERS
2911
+
2912
+ // LOCALES
2913
+
2914
+ function localeWeek (mom) {
2915
+ return weekOfYear(mom, this._week.dow, this._week.doy).week;
2916
+ }
2917
+
2918
+ var defaultLocaleWeek = {
2919
+ dow : 0, // Sunday is the first day of the week.
2920
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
2921
+ };
2922
+
2923
+ function localeFirstDayOfWeek () {
2924
+ return this._week.dow;
2925
+ }
2926
+
2927
+ function localeFirstDayOfYear () {
2928
+ return this._week.doy;
2929
+ }
2930
+
2931
+ // MOMENTS
2932
+
2933
+ function getSetWeek (input) {
2934
+ var week = this.localeData().week(this);
2935
+ return input == null ? week : this.add((input - week) * 7, 'd');
2936
+ }
2937
+
2938
+ function getSetISOWeek (input) {
2939
+ var week = weekOfYear(this, 1, 4).week;
2940
+ return input == null ? week : this.add((input - week) * 7, 'd');
2941
+ }
2942
+
2943
+ // FORMATTING
2944
+
2945
+ addFormatToken('d', 0, 'do', 'day');
2946
+
2947
+ addFormatToken('dd', 0, 0, function (format) {
2948
+ return this.localeData().weekdaysMin(this, format);
2949
+ });
2950
+
2951
+ addFormatToken('ddd', 0, 0, function (format) {
2952
+ return this.localeData().weekdaysShort(this, format);
2953
+ });
2954
+
2955
+ addFormatToken('dddd', 0, 0, function (format) {
2956
+ return this.localeData().weekdays(this, format);
2957
+ });
2958
+
2959
+ addFormatToken('e', 0, 0, 'weekday');
2960
+ addFormatToken('E', 0, 0, 'isoWeekday');
2961
+
2962
+ // ALIASES
2963
+
2964
+ addUnitAlias('day', 'd');
2965
+ addUnitAlias('weekday', 'e');
2966
+ addUnitAlias('isoWeekday', 'E');
2967
+
2968
+ // PRIORITY
2969
+ addUnitPriority('day', 11);
2970
+ addUnitPriority('weekday', 11);
2971
+ addUnitPriority('isoWeekday', 11);
2972
+
2973
+ // PARSING
2974
+
2975
+ addRegexToken('d', match1to2);
2976
+ addRegexToken('e', match1to2);
2977
+ addRegexToken('E', match1to2);
2978
+ addRegexToken('dd', function (isStrict, locale) {
2979
+ return locale.weekdaysMinRegex(isStrict);
2980
+ });
2981
+ addRegexToken('ddd', function (isStrict, locale) {
2982
+ return locale.weekdaysShortRegex(isStrict);
2983
+ });
2984
+ addRegexToken('dddd', function (isStrict, locale) {
2985
+ return locale.weekdaysRegex(isStrict);
2986
+ });
2987
+
2988
+ addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
2989
+ var weekday = config._locale.weekdaysParse(input, token, config._strict);
2990
+ // if we didn't get a weekday name, mark the date as invalid
2991
+ if (weekday != null) {
2992
+ week.d = weekday;
2993
+ } else {
2994
+ getParsingFlags(config).invalidWeekday = input;
2995
+ }
2996
+ });
2997
+
2998
+ addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
2999
+ week[token] = toInt(input);
3000
+ });
3001
+
3002
+ // HELPERS
3003
+
3004
+ function parseWeekday(input, locale) {
3005
+ if (typeof input !== 'string') {
3006
+ return input;
3007
+ }
3008
+
3009
+ if (!isNaN(input)) {
3010
+ return parseInt(input, 10);
3011
+ }
3012
+
3013
+ input = locale.weekdaysParse(input);
3014
+ if (typeof input === 'number') {
3015
+ return input;
3016
+ }
3017
+
3018
+ return null;
3019
+ }
3020
+
3021
+ function parseIsoWeekday(input, locale) {
3022
+ if (typeof input === 'string') {
3023
+ return locale.weekdaysParse(input) % 7 || 7;
3024
+ }
3025
+ return isNaN(input) ? null : input;
3026
+ }
3027
+
3028
+ // LOCALES
3029
+
3030
+ var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
3031
+ function localeWeekdays (m, format) {
3032
+ if (!m) {
3033
+ return isArray(this._weekdays) ? this._weekdays :
3034
+ this._weekdays['standalone'];
3035
+ }
3036
+ return isArray(this._weekdays) ? this._weekdays[m.day()] :
3037
+ this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
3038
+ }
3039
+
3040
+ var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
3041
+ function localeWeekdaysShort (m) {
3042
+ return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
3043
+ }
3044
+
3045
+ var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
3046
+ function localeWeekdaysMin (m) {
3047
+ return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
3048
+ }
3049
+
3050
+ function handleStrictParse$1(weekdayName, format, strict) {
3051
+ var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
3052
+ if (!this._weekdaysParse) {
3053
+ this._weekdaysParse = [];
3054
+ this._shortWeekdaysParse = [];
3055
+ this._minWeekdaysParse = [];
3056
+
3057
+ for (i = 0; i < 7; ++i) {
3058
+ mom = createUTC([2000, 1]).day(i);
3059
+ this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
3060
+ this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
3061
+ this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
3062
+ }
3063
+ }
3064
+
3065
+ if (strict) {
3066
+ if (format === 'dddd') {
3067
+ ii = indexOf$1.call(this._weekdaysParse, llc);
3068
+ return ii !== -1 ? ii : null;
3069
+ } else if (format === 'ddd') {
3070
+ ii = indexOf$1.call(this._shortWeekdaysParse, llc);
3071
+ return ii !== -1 ? ii : null;
3072
+ } else {
3073
+ ii = indexOf$1.call(this._minWeekdaysParse, llc);
3074
+ return ii !== -1 ? ii : null;
3075
+ }
3076
+ } else {
3077
+ if (format === 'dddd') {
3078
+ ii = indexOf$1.call(this._weekdaysParse, llc);
3079
+ if (ii !== -1) {
3080
+ return ii;
3081
+ }
3082
+ ii = indexOf$1.call(this._shortWeekdaysParse, llc);
3083
+ if (ii !== -1) {
3084
+ return ii;
3085
+ }
3086
+ ii = indexOf$1.call(this._minWeekdaysParse, llc);
3087
+ return ii !== -1 ? ii : null;
3088
+ } else if (format === 'ddd') {
3089
+ ii = indexOf$1.call(this._shortWeekdaysParse, llc);
3090
+ if (ii !== -1) {
3091
+ return ii;
3092
+ }
3093
+ ii = indexOf$1.call(this._weekdaysParse, llc);
3094
+ if (ii !== -1) {
3095
+ return ii;
3096
+ }
3097
+ ii = indexOf$1.call(this._minWeekdaysParse, llc);
3098
+ return ii !== -1 ? ii : null;
3099
+ } else {
3100
+ ii = indexOf$1.call(this._minWeekdaysParse, llc);
3101
+ if (ii !== -1) {
3102
+ return ii;
3103
+ }
3104
+ ii = indexOf$1.call(this._weekdaysParse, llc);
3105
+ if (ii !== -1) {
3106
+ return ii;
3107
+ }
3108
+ ii = indexOf$1.call(this._shortWeekdaysParse, llc);
3109
+ return ii !== -1 ? ii : null;
3110
+ }
3111
+ }
3112
+ }
3113
+
3114
+ function localeWeekdaysParse (weekdayName, format, strict) {
3115
+ var i, mom, regex;
3116
+
3117
+ if (this._weekdaysParseExact) {
3118
+ return handleStrictParse$1.call(this, weekdayName, format, strict);
3119
+ }
3120
+
3121
+ if (!this._weekdaysParse) {
3122
+ this._weekdaysParse = [];
3123
+ this._minWeekdaysParse = [];
3124
+ this._shortWeekdaysParse = [];
3125
+ this._fullWeekdaysParse = [];
3126
+ }
3127
+
3128
+ for (i = 0; i < 7; i++) {
3129
+ // make the regex if we don't have it already
3130
+
3131
+ mom = createUTC([2000, 1]).day(i);
3132
+ if (strict && !this._fullWeekdaysParse[i]) {
3133
+ this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
3134
+ this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
3135
+ this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
3136
+ }
3137
+ if (!this._weekdaysParse[i]) {
3138
+ regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
3139
+ this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
3140
+ }
3141
+ // test the regex
3142
+ if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
3143
+ return i;
3144
+ } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
3145
+ return i;
3146
+ } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
3147
+ return i;
3148
+ } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
3149
+ return i;
3150
+ }
3151
+ }
3152
+ }
3153
+
3154
+ // MOMENTS
3155
+
3156
+ function getSetDayOfWeek (input) {
3157
+ if (!this.isValid()) {
3158
+ return input != null ? this : NaN;
3159
+ }
3160
+ var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
3161
+ if (input != null) {
3162
+ input = parseWeekday(input, this.localeData());
3163
+ return this.add(input - day, 'd');
3164
+ } else {
3165
+ return day;
3166
+ }
3167
+ }
3168
+
3169
+ function getSetLocaleDayOfWeek (input) {
3170
+ if (!this.isValid()) {
3171
+ return input != null ? this : NaN;
3172
+ }
3173
+ var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
3174
+ return input == null ? weekday : this.add(input - weekday, 'd');
3175
+ }
3176
+
3177
+ function getSetISODayOfWeek (input) {
3178
+ if (!this.isValid()) {
3179
+ return input != null ? this : NaN;
3180
+ }
3181
+
3182
+ // behaves the same as moment#day except
3183
+ // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
3184
+ // as a setter, sunday should belong to the previous week.
3185
+
3186
+ if (input != null) {
3187
+ var weekday = parseIsoWeekday(input, this.localeData());
3188
+ return this.day(this.day() % 7 ? weekday : weekday - 7);
3189
+ } else {
3190
+ return this.day() || 7;
3191
+ }
3192
+ }
3193
+
3194
+ var defaultWeekdaysRegex = matchWord;
3195
+ function weekdaysRegex (isStrict) {
3196
+ if (this._weekdaysParseExact) {
3197
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
3198
+ computeWeekdaysParse.call(this);
3199
+ }
3200
+ if (isStrict) {
3201
+ return this._weekdaysStrictRegex;
3202
+ } else {
3203
+ return this._weekdaysRegex;
3204
+ }
3205
+ } else {
3206
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
3207
+ this._weekdaysRegex = defaultWeekdaysRegex;
3208
+ }
3209
+ return this._weekdaysStrictRegex && isStrict ?
3210
+ this._weekdaysStrictRegex : this._weekdaysRegex;
3211
+ }
3212
+ }
3213
+
3214
+ var defaultWeekdaysShortRegex = matchWord;
3215
+ function weekdaysShortRegex (isStrict) {
3216
+ if (this._weekdaysParseExact) {
3217
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
3218
+ computeWeekdaysParse.call(this);
3219
+ }
3220
+ if (isStrict) {
3221
+ return this._weekdaysShortStrictRegex;
3222
+ } else {
3223
+ return this._weekdaysShortRegex;
3224
+ }
3225
+ } else {
3226
+ if (!hasOwnProp(this, '_weekdaysShortRegex')) {
3227
+ this._weekdaysShortRegex = defaultWeekdaysShortRegex;
3228
+ }
3229
+ return this._weekdaysShortStrictRegex && isStrict ?
3230
+ this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
3231
+ }
3232
+ }
3233
+
3234
+ var defaultWeekdaysMinRegex = matchWord;
3235
+ function weekdaysMinRegex (isStrict) {
3236
+ if (this._weekdaysParseExact) {
3237
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
3238
+ computeWeekdaysParse.call(this);
3239
+ }
3240
+ if (isStrict) {
3241
+ return this._weekdaysMinStrictRegex;
3242
+ } else {
3243
+ return this._weekdaysMinRegex;
3244
+ }
3245
+ } else {
3246
+ if (!hasOwnProp(this, '_weekdaysMinRegex')) {
3247
+ this._weekdaysMinRegex = defaultWeekdaysMinRegex;
3248
+ }
3249
+ return this._weekdaysMinStrictRegex && isStrict ?
3250
+ this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
3251
+ }
3252
+ }
3253
+
3254
+
3255
+ function computeWeekdaysParse () {
3256
+ function cmpLenRev(a, b) {
3257
+ return b.length - a.length;
3258
+ }
3259
+
3260
+ var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
3261
+ i, mom, minp, shortp, longp;
3262
+ for (i = 0; i < 7; i++) {
3263
+ // make the regex if we don't have it already
3264
+ mom = createUTC([2000, 1]).day(i);
3265
+ minp = this.weekdaysMin(mom, '');
3266
+ shortp = this.weekdaysShort(mom, '');
3267
+ longp = this.weekdays(mom, '');
3268
+ minPieces.push(minp);
3269
+ shortPieces.push(shortp);
3270
+ longPieces.push(longp);
3271
+ mixedPieces.push(minp);
3272
+ mixedPieces.push(shortp);
3273
+ mixedPieces.push(longp);
3274
+ }
3275
+ // Sorting makes sure if one weekday (or abbr) is a prefix of another it
3276
+ // will match the longer piece.
3277
+ minPieces.sort(cmpLenRev);
3278
+ shortPieces.sort(cmpLenRev);
3279
+ longPieces.sort(cmpLenRev);
3280
+ mixedPieces.sort(cmpLenRev);
3281
+ for (i = 0; i < 7; i++) {
3282
+ shortPieces[i] = regexEscape(shortPieces[i]);
3283
+ longPieces[i] = regexEscape(longPieces[i]);
3284
+ mixedPieces[i] = regexEscape(mixedPieces[i]);
3285
+ }
3286
+
3287
+ this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
3288
+ this._weekdaysShortRegex = this._weekdaysRegex;
3289
+ this._weekdaysMinRegex = this._weekdaysRegex;
3290
+
3291
+ this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
3292
+ this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
3293
+ this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
3294
+ }
3295
+
3296
+ // FORMATTING
3297
+
3298
+ function hFormat() {
3299
+ return this.hours() % 12 || 12;
3300
+ }
3301
+
3302
+ function kFormat() {
3303
+ return this.hours() || 24;
3304
+ }
3305
+
3306
+ addFormatToken('H', ['HH', 2], 0, 'hour');
3307
+ addFormatToken('h', ['hh', 2], 0, hFormat);
3308
+ addFormatToken('k', ['kk', 2], 0, kFormat);
3309
+
3310
+ addFormatToken('hmm', 0, 0, function () {
3311
+ return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
3312
+ });
3313
+
3314
+ addFormatToken('hmmss', 0, 0, function () {
3315
+ return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
3316
+ zeroFill(this.seconds(), 2);
3317
+ });
3318
+
3319
+ addFormatToken('Hmm', 0, 0, function () {
3320
+ return '' + this.hours() + zeroFill(this.minutes(), 2);
3321
+ });
3322
+
3323
+ addFormatToken('Hmmss', 0, 0, function () {
3324
+ return '' + this.hours() + zeroFill(this.minutes(), 2) +
3325
+ zeroFill(this.seconds(), 2);
3326
+ });
3327
+
3328
+ function meridiem (token, lowercase) {
3329
+ addFormatToken(token, 0, 0, function () {
3330
+ return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
3331
+ });
3332
+ }
3333
+
3334
+ meridiem('a', true);
3335
+ meridiem('A', false);
3336
+
3337
+ // ALIASES
3338
+
3339
+ addUnitAlias('hour', 'h');
3340
+
3341
+ // PRIORITY
3342
+ addUnitPriority('hour', 13);
3343
+
3344
+ // PARSING
3345
+
3346
+ function matchMeridiem (isStrict, locale) {
3347
+ return locale._meridiemParse;
3348
+ }
3349
+
3350
+ addRegexToken('a', matchMeridiem);
3351
+ addRegexToken('A', matchMeridiem);
3352
+ addRegexToken('H', match1to2);
3353
+ addRegexToken('h', match1to2);
3354
+ addRegexToken('k', match1to2);
3355
+ addRegexToken('HH', match1to2, match2);
3356
+ addRegexToken('hh', match1to2, match2);
3357
+ addRegexToken('kk', match1to2, match2);
3358
+
3359
+ addRegexToken('hmm', match3to4);
3360
+ addRegexToken('hmmss', match5to6);
3361
+ addRegexToken('Hmm', match3to4);
3362
+ addRegexToken('Hmmss', match5to6);
3363
+
3364
+ addParseToken(['H', 'HH'], HOUR);
3365
+ addParseToken(['k', 'kk'], function (input, array, config) {
3366
+ var kInput = toInt(input);
3367
+ array[HOUR] = kInput === 24 ? 0 : kInput;
3368
+ });
3369
+ addParseToken(['a', 'A'], function (input, array, config) {
3370
+ config._isPm = config._locale.isPM(input);
3371
+ config._meridiem = input;
3372
+ });
3373
+ addParseToken(['h', 'hh'], function (input, array, config) {
3374
+ array[HOUR] = toInt(input);
3375
+ getParsingFlags(config).bigHour = true;
3376
+ });
3377
+ addParseToken('hmm', function (input, array, config) {
3378
+ var pos = input.length - 2;
3379
+ array[HOUR] = toInt(input.substr(0, pos));
3380
+ array[MINUTE] = toInt(input.substr(pos));
3381
+ getParsingFlags(config).bigHour = true;
3382
+ });
3383
+ addParseToken('hmmss', function (input, array, config) {
3384
+ var pos1 = input.length - 4;
3385
+ var pos2 = input.length - 2;
3386
+ array[HOUR] = toInt(input.substr(0, pos1));
3387
+ array[MINUTE] = toInt(input.substr(pos1, 2));
3388
+ array[SECOND] = toInt(input.substr(pos2));
3389
+ getParsingFlags(config).bigHour = true;
3390
+ });
3391
+ addParseToken('Hmm', function (input, array, config) {
3392
+ var pos = input.length - 2;
3393
+ array[HOUR] = toInt(input.substr(0, pos));
3394
+ array[MINUTE] = toInt(input.substr(pos));
3395
+ });
3396
+ addParseToken('Hmmss', function (input, array, config) {
3397
+ var pos1 = input.length - 4;
3398
+ var pos2 = input.length - 2;
3399
+ array[HOUR] = toInt(input.substr(0, pos1));
3400
+ array[MINUTE] = toInt(input.substr(pos1, 2));
3401
+ array[SECOND] = toInt(input.substr(pos2));
3402
+ });
3403
+
3404
+ // LOCALES
3405
+
3406
+ function localeIsPM (input) {
3407
+ // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
3408
+ // Using charAt should be more compatible.
3409
+ return ((input + '').toLowerCase().charAt(0) === 'p');
3410
+ }
3411
+
3412
+ var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
3413
+ function localeMeridiem (hours, minutes, isLower) {
3414
+ if (hours > 11) {
3415
+ return isLower ? 'pm' : 'PM';
3416
+ } else {
3417
+ return isLower ? 'am' : 'AM';
3418
+ }
3419
+ }
3420
+
3421
+
3422
+ // MOMENTS
3423
+
3424
+ // Setting the hour should keep the time, because the user explicitly
3425
+ // specified which hour he wants. So trying to maintain the same hour (in
3426
+ // a new timezone) makes sense. Adding/subtracting hours does not follow
3427
+ // this rule.
3428
+ var getSetHour = makeGetSet('Hours', true);
3429
+
3430
+ // months
3431
+ // week
3432
+ // weekdays
3433
+ // meridiem
3434
+ var baseConfig = {
3435
+ calendar: defaultCalendar,
3436
+ longDateFormat: defaultLongDateFormat,
3437
+ invalidDate: defaultInvalidDate,
3438
+ ordinal: defaultOrdinal,
3439
+ dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
3440
+ relativeTime: defaultRelativeTime,
3441
+
3442
+ months: defaultLocaleMonths,
3443
+ monthsShort: defaultLocaleMonthsShort,
3444
+
3445
+ week: defaultLocaleWeek,
3446
+
3447
+ weekdays: defaultLocaleWeekdays,
3448
+ weekdaysMin: defaultLocaleWeekdaysMin,
3449
+ weekdaysShort: defaultLocaleWeekdaysShort,
3450
+
3451
+ meridiemParse: defaultLocaleMeridiemParse
3452
+ };
3453
+
3454
+ // internal storage for locale config files
3455
+ var locales = {};
3456
+ var localeFamilies = {};
3457
+ var globalLocale;
3458
+
3459
+ function normalizeLocale(key) {
3460
+ return key ? key.toLowerCase().replace('_', '-') : key;
3461
+ }
3462
+
3463
+ // pick the locale from the array
3464
+ // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
3465
+ // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
3466
+ function chooseLocale(names) {
3467
+ var i = 0, j, next, locale, split;
3468
+
3469
+ while (i < names.length) {
3470
+ split = normalizeLocale(names[i]).split('-');
3471
+ j = split.length;
3472
+ next = normalizeLocale(names[i + 1]);
3473
+ next = next ? next.split('-') : null;
3474
+ while (j > 0) {
3475
+ locale = loadLocale(split.slice(0, j).join('-'));
3476
+ if (locale) {
3477
+ return locale;
3478
+ }
3479
+ if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
3480
+ //the next array item is better than a shallower substring of this one
3481
+ break;
3482
+ }
3483
+ j--;
3484
+ }
3485
+ i++;
3486
+ }
3487
+ return null;
3488
+ }
3489
+
3490
+ function loadLocale(name) {
3491
+ var oldLocale = null;
3492
+ // TODO: Find a better way to register and load all the locales in Node
3493
+ if (!locales[name] && (typeof module !== 'undefined') &&
3494
+ module && module.exports) {
3495
+ try {
3496
+ oldLocale = globalLocale._abbr;
3497
+ require('./locale/' + name);
3498
+ // because defineLocale currently also sets the global locale, we
3499
+ // want to undo that for lazy loaded locales
3500
+ getSetGlobalLocale(oldLocale);
3501
+ } catch (e) { }
3502
+ }
3503
+ return locales[name];
3504
+ }
3505
+
3506
+ // This function will load locale and then set the global locale. If
3507
+ // no arguments are passed in, it will simply return the current global
3508
+ // locale key.
3509
+ function getSetGlobalLocale (key, values) {
3510
+ var data;
3511
+ if (key) {
3512
+ if (isUndefined(values)) {
3513
+ data = getLocale(key);
3514
+ }
3515
+ else {
3516
+ data = defineLocale(key, values);
3517
+ }
3518
+
3519
+ if (data) {
3520
+ // moment.duration._locale = moment._locale = data;
3521
+ globalLocale = data;
3522
+ }
3523
+ }
3524
+
3525
+ return globalLocale._abbr;
3526
+ }
3527
+
3528
+ function defineLocale (name, config) {
3529
+ if (config !== null) {
3530
+ var parentConfig = baseConfig;
3531
+ config.abbr = name;
3532
+ if (locales[name] != null) {
3533
+ deprecateSimple('defineLocaleOverride',
3534
+ 'use moment.updateLocale(localeName, config) to change ' +
3535
+ 'an existing locale. moment.defineLocale(localeName, ' +
3536
+ 'config) should only be used for creating a new locale ' +
3537
+ 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
3538
+ parentConfig = locales[name]._config;
3539
+ } else if (config.parentLocale != null) {
3540
+ if (locales[config.parentLocale] != null) {
3541
+ parentConfig = locales[config.parentLocale]._config;
3542
+ } else {
3543
+ if (!localeFamilies[config.parentLocale]) {
3544
+ localeFamilies[config.parentLocale] = [];
3545
+ }
3546
+ localeFamilies[config.parentLocale].push({
3547
+ name: name,
3548
+ config: config
3549
+ });
3550
+ return null;
3551
+ }
3552
+ }
3553
+ locales[name] = new Locale(mergeConfigs(parentConfig, config));
3554
+
3555
+ if (localeFamilies[name]) {
3556
+ localeFamilies[name].forEach(function (x) {
3557
+ defineLocale(x.name, x.config);
3558
+ });
3559
+ }
3560
+
3561
+ // backwards compat for now: also set the locale
3562
+ // make sure we set the locale AFTER all child locales have been
3563
+ // created, so we won't end up with the child locale set.
3564
+ getSetGlobalLocale(name);
3565
+
3566
+
3567
+ return locales[name];
3568
+ } else {
3569
+ // useful for testing
3570
+ delete locales[name];
3571
+ return null;
3572
+ }
3573
+ }
3574
+
3575
+ function updateLocale(name, config) {
3576
+ if (config != null) {
3577
+ var locale, parentConfig = baseConfig;
3578
+ // MERGE
3579
+ if (locales[name] != null) {
3580
+ parentConfig = locales[name]._config;
3581
+ }
3582
+ config = mergeConfigs(parentConfig, config);
3583
+ locale = new Locale(config);
3584
+ locale.parentLocale = locales[name];
3585
+ locales[name] = locale;
3586
+
3587
+ // backwards compat for now: also set the locale
3588
+ getSetGlobalLocale(name);
3589
+ } else {
3590
+ // pass null for config to unupdate, useful for tests
3591
+ if (locales[name] != null) {
3592
+ if (locales[name].parentLocale != null) {
3593
+ locales[name] = locales[name].parentLocale;
3594
+ } else if (locales[name] != null) {
3595
+ delete locales[name];
3596
+ }
3597
+ }
3598
+ }
3599
+ return locales[name];
3600
+ }
3601
+
3602
+ // returns locale data
3603
+ function getLocale (key) {
3604
+ var locale;
3605
+
3606
+ if (key && key._locale && key._locale._abbr) {
3607
+ key = key._locale._abbr;
3608
+ }
3609
+
3610
+ if (!key) {
3611
+ return globalLocale;
3612
+ }
3613
+
3614
+ if (!isArray(key)) {
3615
+ //short-circuit everything else
3616
+ locale = loadLocale(key);
3617
+ if (locale) {
3618
+ return locale;
3619
+ }
3620
+ key = [key];
3621
+ }
3622
+
3623
+ return chooseLocale(key);
3624
+ }
3625
+
3626
+ function listLocales() {
3627
+ return keys$1(locales);
3628
+ }
3629
+
3630
+ function checkOverflow (m) {
3631
+ var overflow;
3632
+ var a = m._a;
3633
+
3634
+ if (a && getParsingFlags(m).overflow === -2) {
3635
+ overflow =
3636
+ a[MONTH] < 0 || a[MONTH] > 11 ? MONTH :
3637
+ a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
3638
+ a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
3639
+ a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE :
3640
+ a[SECOND] < 0 || a[SECOND] > 59 ? SECOND :
3641
+ a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
3642
+ -1;
3643
+
3644
+ if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
3645
+ overflow = DATE;
3646
+ }
3647
+ if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
3648
+ overflow = WEEK;
3649
+ }
3650
+ if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
3651
+ overflow = WEEKDAY;
3652
+ }
3653
+
3654
+ getParsingFlags(m).overflow = overflow;
3655
+ }
3656
+
3657
+ return m;
3658
+ }
3659
+
3660
+ // iso 8601 regex
3661
+ // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
3662
+ var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
3663
+ var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
3664
+
3665
+ var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
3666
+
3667
+ var isoDates = [
3668
+ ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
3669
+ ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
3670
+ ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
3671
+ ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
3672
+ ['YYYY-DDD', /\d{4}-\d{3}/],
3673
+ ['YYYY-MM', /\d{4}-\d\d/, false],
3674
+ ['YYYYYYMMDD', /[+-]\d{10}/],
3675
+ ['YYYYMMDD', /\d{8}/],
3676
+ // YYYYMM is NOT allowed by the standard
3677
+ ['GGGG[W]WWE', /\d{4}W\d{3}/],
3678
+ ['GGGG[W]WW', /\d{4}W\d{2}/, false],
3679
+ ['YYYYDDD', /\d{7}/]
3680
+ ];
3681
+
3682
+ // iso time formats and regexes
3683
+ var isoTimes = [
3684
+ ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
3685
+ ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
3686
+ ['HH:mm:ss', /\d\d:\d\d:\d\d/],
3687
+ ['HH:mm', /\d\d:\d\d/],
3688
+ ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
3689
+ ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
3690
+ ['HHmmss', /\d\d\d\d\d\d/],
3691
+ ['HHmm', /\d\d\d\d/],
3692
+ ['HH', /\d\d/]
3693
+ ];
3694
+
3695
+ var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
3696
+
3697
+ // date from iso format
3698
+ function configFromISO(config) {
3699
+ var i, l,
3700
+ string = config._i,
3701
+ match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
3702
+ allowTime, dateFormat, timeFormat, tzFormat;
3703
+
3704
+ if (match) {
3705
+ getParsingFlags(config).iso = true;
3706
+
3707
+ for (i = 0, l = isoDates.length; i < l; i++) {
3708
+ if (isoDates[i][1].exec(match[1])) {
3709
+ dateFormat = isoDates[i][0];
3710
+ allowTime = isoDates[i][2] !== false;
3711
+ break;
3712
+ }
3713
+ }
3714
+ if (dateFormat == null) {
3715
+ config._isValid = false;
3716
+ return;
3717
+ }
3718
+ if (match[3]) {
3719
+ for (i = 0, l = isoTimes.length; i < l; i++) {
3720
+ if (isoTimes[i][1].exec(match[3])) {
3721
+ // match[2] should be 'T' or space
3722
+ timeFormat = (match[2] || ' ') + isoTimes[i][0];
3723
+ break;
3724
+ }
3725
+ }
3726
+ if (timeFormat == null) {
3727
+ config._isValid = false;
3728
+ return;
3729
+ }
3730
+ }
3731
+ if (!allowTime && timeFormat != null) {
3732
+ config._isValid = false;
3733
+ return;
3734
+ }
3735
+ if (match[4]) {
3736
+ if (tzRegex.exec(match[4])) {
3737
+ tzFormat = 'Z';
3738
+ } else {
3739
+ config._isValid = false;
3740
+ return;
3741
+ }
3742
+ }
3743
+ config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
3744
+ configFromStringAndFormat(config);
3745
+ } else {
3746
+ config._isValid = false;
3747
+ }
3748
+ }
3749
+
3750
+ // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
3751
+ var basicRfcRegex = /^((?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d?\d\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(?:\d\d)?\d\d\s)(\d\d:\d\d)(\:\d\d)?(\s(?:UT|GMT|[ECMP][SD]T|[A-IK-Za-ik-z]|[+-]\d{4}))$/;
3752
+
3753
+ // date and time from ref 2822 format
3754
+ function configFromRFC2822(config) {
3755
+ var string, match, dayFormat,
3756
+ dateFormat, timeFormat, tzFormat;
3757
+ var timezones = {
3758
+ ' GMT': ' +0000',
3759
+ ' EDT': ' -0400',
3760
+ ' EST': ' -0500',
3761
+ ' CDT': ' -0500',
3762
+ ' CST': ' -0600',
3763
+ ' MDT': ' -0600',
3764
+ ' MST': ' -0700',
3765
+ ' PDT': ' -0700',
3766
+ ' PST': ' -0800'
3767
+ };
3768
+ var military = 'YXWVUTSRQPONZABCDEFGHIKLM';
3769
+ var timezone, timezoneIndex;
3770
+
3771
+ string = config._i
3772
+ .replace(/\([^\)]*\)|[\n\t]/g, ' ') // Remove comments and folding whitespace
3773
+ .replace(/(\s\s+)/g, ' ') // Replace multiple-spaces with a single space
3774
+ .replace(/^\s|\s$/g, ''); // Remove leading and trailing spaces
3775
+ match = basicRfcRegex.exec(string);
3776
+
3777
+ if (match) {
3778
+ dayFormat = match[1] ? 'ddd' + ((match[1].length === 5) ? ', ' : ' ') : '';
3779
+ dateFormat = 'D MMM ' + ((match[2].length > 10) ? 'YYYY ' : 'YY ');
3780
+ timeFormat = 'HH:mm' + (match[4] ? ':ss' : '');
3781
+
3782
+ // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
3783
+ if (match[1]) { // day of week given
3784
+ var momentDate = new Date(match[2]);
3785
+ var momentDay = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][momentDate.getDay()];
3786
+
3787
+ if (match[1].substr(0,3) !== momentDay) {
3788
+ getParsingFlags(config).weekdayMismatch = true;
3789
+ config._isValid = false;
3790
+ return;
3791
+ }
3792
+ }
3793
+
3794
+ switch (match[5].length) {
3795
+ case 2: // military
3796
+ if (timezoneIndex === 0) {
3797
+ timezone = ' +0000';
3798
+ } else {
3799
+ timezoneIndex = military.indexOf(match[5][1].toUpperCase()) - 12;
3800
+ timezone = ((timezoneIndex < 0) ? ' -' : ' +') +
3801
+ (('' + timezoneIndex).replace(/^-?/, '0')).match(/..$/)[0] + '00';
3802
+ }
3803
+ break;
3804
+ case 4: // Zone
3805
+ timezone = timezones[match[5]];
3806
+ break;
3807
+ default: // UT or +/-9999
3808
+ timezone = timezones[' GMT'];
3809
+ }
3810
+ match[5] = timezone;
3811
+ config._i = match.splice(1).join('');
3812
+ tzFormat = ' ZZ';
3813
+ config._f = dayFormat + dateFormat + timeFormat + tzFormat;
3814
+ configFromStringAndFormat(config);
3815
+ getParsingFlags(config).rfc2822 = true;
3816
+ } else {
3817
+ config._isValid = false;
3818
+ }
3819
+ }
3820
+
3821
+ // date from iso format or fallback
3822
+ function configFromString(config) {
3823
+ var matched = aspNetJsonRegex.exec(config._i);
3824
+
3825
+ if (matched !== null) {
3826
+ config._d = new Date(+matched[1]);
3827
+ return;
3828
+ }
3829
+
3830
+ configFromISO(config);
3831
+ if (config._isValid === false) {
3832
+ delete config._isValid;
3833
+ } else {
3834
+ return;
3835
+ }
3836
+
3837
+ configFromRFC2822(config);
3838
+ if (config._isValid === false) {
3839
+ delete config._isValid;
3840
+ } else {
3841
+ return;
3842
+ }
3843
+
3844
+ // Final attempt, use Input Fallback
3845
+ hooks.createFromInputFallback(config);
3846
+ }
3847
+
3848
+ hooks.createFromInputFallback = deprecate(
3849
+ 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
3850
+ 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
3851
+ 'discouraged and will be removed in an upcoming major release. Please refer to ' +
3852
+ 'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
3853
+ function (config) {
3854
+ config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
3855
+ }
3856
+ );
3857
+
3858
+ // Pick the first defined of two or three arguments.
3859
+ function defaults(a, b, c) {
3860
+ if (a != null) {
3861
+ return a;
3862
+ }
3863
+ if (b != null) {
3864
+ return b;
3865
+ }
3866
+ return c;
3867
+ }
3868
+
3869
+ function currentDateArray(config) {
3870
+ // hooks is actually the exported moment object
3871
+ var nowValue = new Date(hooks.now());
3872
+ if (config._useUTC) {
3873
+ return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
3874
+ }
3875
+ return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
3876
+ }
3877
+
3878
+ // convert an array to a date.
3879
+ // the array should mirror the parameters below
3880
+ // note: all values past the year are optional and will default to the lowest possible value.
3881
+ // [year, month, day , hour, minute, second, millisecond]
3882
+ function configFromArray (config) {
3883
+ var i, date, input = [], currentDate, yearToUse;
3884
+
3885
+ if (config._d) {
3886
+ return;
3887
+ }
3888
+
3889
+ currentDate = currentDateArray(config);
3890
+
3891
+ //compute day of the year from weeks and weekdays
3892
+ if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
3893
+ dayOfYearFromWeekInfo(config);
3894
+ }
3895
+
3896
+ //if the day of the year is set, figure out what it is
3897
+ if (config._dayOfYear != null) {
3898
+ yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
3899
+
3900
+ if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
3901
+ getParsingFlags(config)._overflowDayOfYear = true;
3902
+ }
3903
+
3904
+ date = createUTCDate(yearToUse, 0, config._dayOfYear);
3905
+ config._a[MONTH] = date.getUTCMonth();
3906
+ config._a[DATE] = date.getUTCDate();
3907
+ }
3908
+
3909
+ // Default to current date.
3910
+ // * if no year, month, day of month are given, default to today
3911
+ // * if day of month is given, default month and year
3912
+ // * if month is given, default only year
3913
+ // * if year is given, don't default anything
3914
+ for (i = 0; i < 3 && config._a[i] == null; ++i) {
3915
+ config._a[i] = input[i] = currentDate[i];
3916
+ }
3917
+
3918
+ // Zero out whatever was not defaulted, including time
3919
+ for (; i < 7; i++) {
3920
+ config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
3921
+ }
3922
+
3923
+ // Check for 24:00:00.000
3924
+ if (config._a[HOUR] === 24 &&
3925
+ config._a[MINUTE] === 0 &&
3926
+ config._a[SECOND] === 0 &&
3927
+ config._a[MILLISECOND] === 0) {
3928
+ config._nextDay = true;
3929
+ config._a[HOUR] = 0;
3930
+ }
3931
+
3932
+ config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
3933
+ // Apply timezone offset from input. The actual utcOffset can be changed
3934
+ // with parseZone.
3935
+ if (config._tzm != null) {
3936
+ config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
3937
+ }
3938
+
3939
+ if (config._nextDay) {
3940
+ config._a[HOUR] = 24;
3941
+ }
3942
+ }
3943
+
3944
+ function dayOfYearFromWeekInfo(config) {
3945
+ var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
3946
+
3947
+ w = config._w;
3948
+ if (w.GG != null || w.W != null || w.E != null) {
3949
+ dow = 1;
3950
+ doy = 4;
3951
+
3952
+ // TODO: We need to take the current isoWeekYear, but that depends on
3953
+ // how we interpret now (local, utc, fixed offset). So create
3954
+ // a now version of current config (take local/utc/offset flags, and
3955
+ // create now).
3956
+ weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
3957
+ week = defaults(w.W, 1);
3958
+ weekday = defaults(w.E, 1);
3959
+ if (weekday < 1 || weekday > 7) {
3960
+ weekdayOverflow = true;
3961
+ }
3962
+ } else {
3963
+ dow = config._locale._week.dow;
3964
+ doy = config._locale._week.doy;
3965
+
3966
+ var curWeek = weekOfYear(createLocal(), dow, doy);
3967
+
3968
+ weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
3969
+
3970
+ // Default to current week.
3971
+ week = defaults(w.w, curWeek.week);
3972
+
3973
+ if (w.d != null) {
3974
+ // weekday -- low day numbers are considered next week
3975
+ weekday = w.d;
3976
+ if (weekday < 0 || weekday > 6) {
3977
+ weekdayOverflow = true;
3978
+ }
3979
+ } else if (w.e != null) {
3980
+ // local weekday -- counting starts from begining of week
3981
+ weekday = w.e + dow;
3982
+ if (w.e < 0 || w.e > 6) {
3983
+ weekdayOverflow = true;
3984
+ }
3985
+ } else {
3986
+ // default to begining of week
3987
+ weekday = dow;
3988
+ }
3989
+ }
3990
+ if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
3991
+ getParsingFlags(config)._overflowWeeks = true;
3992
+ } else if (weekdayOverflow != null) {
3993
+ getParsingFlags(config)._overflowWeekday = true;
3994
+ } else {
3995
+ temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
3996
+ config._a[YEAR] = temp.year;
3997
+ config._dayOfYear = temp.dayOfYear;
3998
+ }
3999
+ }
4000
+
4001
+ // constant that refers to the ISO standard
4002
+ hooks.ISO_8601 = function () {};
4003
+
4004
+ // constant that refers to the RFC 2822 form
4005
+ hooks.RFC_2822 = function () {};
4006
+
4007
+ // date from string and format string
4008
+ function configFromStringAndFormat(config) {
4009
+ // TODO: Move this to another part of the creation flow to prevent circular deps
4010
+ if (config._f === hooks.ISO_8601) {
4011
+ configFromISO(config);
4012
+ return;
4013
+ }
4014
+ if (config._f === hooks.RFC_2822) {
4015
+ configFromRFC2822(config);
4016
+ return;
4017
+ }
4018
+ config._a = [];
4019
+ getParsingFlags(config).empty = true;
4020
+
4021
+ // This array is used to make a Date, either with `new Date` or `Date.UTC`
4022
+ var string = '' + config._i,
4023
+ i, parsedInput, tokens, token, skipped,
4024
+ stringLength = string.length,
4025
+ totalParsedInputLength = 0;
4026
+
4027
+ tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
4028
+
4029
+ for (i = 0; i < tokens.length; i++) {
4030
+ token = tokens[i];
4031
+ parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
4032
+ // console.log('token', token, 'parsedInput', parsedInput,
4033
+ // 'regex', getParseRegexForToken(token, config));
4034
+ if (parsedInput) {
4035
+ skipped = string.substr(0, string.indexOf(parsedInput));
4036
+ if (skipped.length > 0) {
4037
+ getParsingFlags(config).unusedInput.push(skipped);
4038
+ }
4039
+ string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
4040
+ totalParsedInputLength += parsedInput.length;
4041
+ }
4042
+ // don't parse if it's not a known token
4043
+ if (formatTokenFunctions[token]) {
4044
+ if (parsedInput) {
4045
+ getParsingFlags(config).empty = false;
4046
+ }
4047
+ else {
4048
+ getParsingFlags(config).unusedTokens.push(token);
4049
+ }
4050
+ addTimeToArrayFromToken(token, parsedInput, config);
4051
+ }
4052
+ else if (config._strict && !parsedInput) {
4053
+ getParsingFlags(config).unusedTokens.push(token);
4054
+ }
4055
+ }
4056
+
4057
+ // add remaining unparsed input length to the string
4058
+ getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
4059
+ if (string.length > 0) {
4060
+ getParsingFlags(config).unusedInput.push(string);
4061
+ }
4062
+
4063
+ // clear _12h flag if hour is <= 12
4064
+ if (config._a[HOUR] <= 12 &&
4065
+ getParsingFlags(config).bigHour === true &&
4066
+ config._a[HOUR] > 0) {
4067
+ getParsingFlags(config).bigHour = undefined;
4068
+ }
4069
+
4070
+ getParsingFlags(config).parsedDateParts = config._a.slice(0);
4071
+ getParsingFlags(config).meridiem = config._meridiem;
4072
+ // handle meridiem
4073
+ config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
4074
+
4075
+ configFromArray(config);
4076
+ checkOverflow(config);
4077
+ }
4078
+
4079
+
4080
+ function meridiemFixWrap (locale, hour, meridiem) {
4081
+ var isPm;
4082
+
4083
+ if (meridiem == null) {
4084
+ // nothing to do
4085
+ return hour;
4086
+ }
4087
+ if (locale.meridiemHour != null) {
4088
+ return locale.meridiemHour(hour, meridiem);
4089
+ } else if (locale.isPM != null) {
4090
+ // Fallback
4091
+ isPm = locale.isPM(meridiem);
4092
+ if (isPm && hour < 12) {
4093
+ hour += 12;
4094
+ }
4095
+ if (!isPm && hour === 12) {
4096
+ hour = 0;
4097
+ }
4098
+ return hour;
4099
+ } else {
4100
+ // this is not supposed to happen
4101
+ return hour;
4102
+ }
4103
+ }
4104
+
4105
+ // date from string and array of format strings
4106
+ function configFromStringAndArray(config) {
4107
+ var tempConfig,
4108
+ bestMoment,
4109
+
4110
+ scoreToBeat,
4111
+ i,
4112
+ currentScore;
4113
+
4114
+ if (config._f.length === 0) {
4115
+ getParsingFlags(config).invalidFormat = true;
4116
+ config._d = new Date(NaN);
4117
+ return;
4118
+ }
4119
+
4120
+ for (i = 0; i < config._f.length; i++) {
4121
+ currentScore = 0;
4122
+ tempConfig = copyConfig({}, config);
4123
+ if (config._useUTC != null) {
4124
+ tempConfig._useUTC = config._useUTC;
4125
+ }
4126
+ tempConfig._f = config._f[i];
4127
+ configFromStringAndFormat(tempConfig);
4128
+
4129
+ if (!isValid(tempConfig)) {
4130
+ continue;
4131
+ }
4132
+
4133
+ // if there is any input that was not parsed add a penalty for that format
4134
+ currentScore += getParsingFlags(tempConfig).charsLeftOver;
4135
+
4136
+ //or tokens
4137
+ currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
4138
+
4139
+ getParsingFlags(tempConfig).score = currentScore;
4140
+
4141
+ if (scoreToBeat == null || currentScore < scoreToBeat) {
4142
+ scoreToBeat = currentScore;
4143
+ bestMoment = tempConfig;
4144
+ }
4145
+ }
4146
+
4147
+ extend(config, bestMoment || tempConfig);
4148
+ }
4149
+
4150
+ function configFromObject(config) {
4151
+ if (config._d) {
4152
+ return;
4153
+ }
4154
+
4155
+ var i = normalizeObjectUnits(config._i);
4156
+ config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
4157
+ return obj && parseInt(obj, 10);
4158
+ });
4159
+
4160
+ configFromArray(config);
4161
+ }
4162
+
4163
+ function createFromConfig (config) {
4164
+ var res = new Moment(checkOverflow(prepareConfig(config)));
4165
+ if (res._nextDay) {
4166
+ // Adding is smart enough around DST
4167
+ res.add(1, 'd');
4168
+ res._nextDay = undefined;
4169
+ }
4170
+
4171
+ return res;
4172
+ }
4173
+
4174
+ function prepareConfig (config) {
4175
+ var input = config._i,
4176
+ format = config._f;
4177
+
4178
+ config._locale = config._locale || getLocale(config._l);
4179
+
4180
+ if (input === null || (format === undefined && input === '')) {
4181
+ return createInvalid({nullInput: true});
4182
+ }
4183
+
4184
+ if (typeof input === 'string') {
4185
+ config._i = input = config._locale.preparse(input);
4186
+ }
4187
+
4188
+ if (isMoment(input)) {
4189
+ return new Moment(checkOverflow(input));
4190
+ } else if (isDate(input)) {
4191
+ config._d = input;
4192
+ } else if (isArray(format)) {
4193
+ configFromStringAndArray(config);
4194
+ } else if (format) {
4195
+ configFromStringAndFormat(config);
4196
+ } else {
4197
+ configFromInput(config);
4198
+ }
4199
+
4200
+ if (!isValid(config)) {
4201
+ config._d = null;
4202
+ }
4203
+
4204
+ return config;
4205
+ }
4206
+
4207
+ function configFromInput(config) {
4208
+ var input = config._i;
4209
+ if (isUndefined(input)) {
4210
+ config._d = new Date(hooks.now());
4211
+ } else if (isDate(input)) {
4212
+ config._d = new Date(input.valueOf());
4213
+ } else if (typeof input === 'string') {
4214
+ configFromString(config);
4215
+ } else if (isArray(input)) {
4216
+ config._a = map(input.slice(0), function (obj) {
4217
+ return parseInt(obj, 10);
4218
+ });
4219
+ configFromArray(config);
4220
+ } else if (isObject(input)) {
4221
+ configFromObject(config);
4222
+ } else if (isNumber(input)) {
4223
+ // from milliseconds
4224
+ config._d = new Date(input);
4225
+ } else {
4226
+ hooks.createFromInputFallback(config);
4227
+ }
4228
+ }
4229
+
4230
+ function createLocalOrUTC (input, format, locale, strict, isUTC) {
4231
+ var c = {};
4232
+
4233
+ if (locale === true || locale === false) {
4234
+ strict = locale;
4235
+ locale = undefined;
4236
+ }
4237
+
4238
+ if ((isObject(input) && isObjectEmpty(input)) ||
4239
+ (isArray(input) && input.length === 0)) {
4240
+ input = undefined;
4241
+ }
4242
+ // object construction must be done this way.
4243
+ // https://github.com/moment/moment/issues/1423
4244
+ c._isAMomentObject = true;
4245
+ c._useUTC = c._isUTC = isUTC;
4246
+ c._l = locale;
4247
+ c._i = input;
4248
+ c._f = format;
4249
+ c._strict = strict;
4250
+
4251
+ return createFromConfig(c);
4252
+ }
4253
+
4254
+ function createLocal (input, format, locale, strict) {
4255
+ return createLocalOrUTC(input, format, locale, strict, false);
4256
+ }
4257
+
4258
+ var prototypeMin = deprecate(
4259
+ 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
4260
+ function () {
4261
+ var other = createLocal.apply(null, arguments);
4262
+ if (this.isValid() && other.isValid()) {
4263
+ return other < this ? this : other;
4264
+ } else {
4265
+ return createInvalid();
4266
+ }
4267
+ }
4268
+ );
4269
+
4270
+ var prototypeMax = deprecate(
4271
+ 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
4272
+ function () {
4273
+ var other = createLocal.apply(null, arguments);
4274
+ if (this.isValid() && other.isValid()) {
4275
+ return other > this ? this : other;
4276
+ } else {
4277
+ return createInvalid();
4278
+ }
4279
+ }
4280
+ );
4281
+
4282
+ // Pick a moment m from moments so that m[fn](other) is true for all
4283
+ // other. This relies on the function fn to be transitive.
4284
+ //
4285
+ // moments should either be an array of moment objects or an array, whose
4286
+ // first element is an array of moment objects.
4287
+ function pickBy(fn, moments) {
4288
+ var res, i;
4289
+ if (moments.length === 1 && isArray(moments[0])) {
4290
+ moments = moments[0];
4291
+ }
4292
+ if (!moments.length) {
4293
+ return createLocal();
4294
+ }
4295
+ res = moments[0];
4296
+ for (i = 1; i < moments.length; ++i) {
4297
+ if (!moments[i].isValid() || moments[i][fn](res)) {
4298
+ res = moments[i];
4299
+ }
4300
+ }
4301
+ return res;
4302
+ }
4303
+
4304
+ // TODO: Use [].sort instead?
4305
+ function min () {
4306
+ var args = [].slice.call(arguments, 0);
4307
+
4308
+ return pickBy('isBefore', args);
4309
+ }
4310
+
4311
+ function max () {
4312
+ var args = [].slice.call(arguments, 0);
4313
+
4314
+ return pickBy('isAfter', args);
4315
+ }
4316
+
4317
+ var now = function () {
4318
+ return Date.now ? Date.now() : +(new Date());
4319
+ };
4320
+
4321
+ var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
4322
+
4323
+ function isDurationValid(m) {
4324
+ for (var key in m) {
4325
+ if (!(ordering.indexOf(key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
4326
+ return false;
4327
+ }
4328
+ }
4329
+
4330
+ var unitHasDecimal = false;
4331
+ for (var i = 0; i < ordering.length; ++i) {
4332
+ if (m[ordering[i]]) {
4333
+ if (unitHasDecimal) {
4334
+ return false; // only allow non-integers for smallest unit
4335
+ }
4336
+ if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
4337
+ unitHasDecimal = true;
4338
+ }
4339
+ }
4340
+ }
4341
+
4342
+ return true;
4343
+ }
4344
+
4345
+ function isValid$1() {
4346
+ return this._isValid;
4347
+ }
4348
+
4349
+ function createInvalid$1() {
4350
+ return createDuration(NaN);
4351
+ }
4352
+
4353
+ function Duration (duration) {
4354
+ var normalizedInput = normalizeObjectUnits(duration),
4355
+ years = normalizedInput.year || 0,
4356
+ quarters = normalizedInput.quarter || 0,
4357
+ months = normalizedInput.month || 0,
4358
+ weeks = normalizedInput.week || 0,
4359
+ days = normalizedInput.day || 0,
4360
+ hours = normalizedInput.hour || 0,
4361
+ minutes = normalizedInput.minute || 0,
4362
+ seconds = normalizedInput.second || 0,
4363
+ milliseconds = normalizedInput.millisecond || 0;
4364
+
4365
+ this._isValid = isDurationValid(normalizedInput);
4366
+
4367
+ // representation for dateAddRemove
4368
+ this._milliseconds = +milliseconds +
4369
+ seconds * 1e3 + // 1000
4370
+ minutes * 6e4 + // 1000 * 60
4371
+ hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
4372
+ // Because of dateAddRemove treats 24 hours as different from a
4373
+ // day when working around DST, we need to store them separately
4374
+ this._days = +days +
4375
+ weeks * 7;
4376
+ // It is impossible translate months into days without knowing
4377
+ // which months you are are talking about, so we have to store
4378
+ // it separately.
4379
+ this._months = +months +
4380
+ quarters * 3 +
4381
+ years * 12;
4382
+
4383
+ this._data = {};
4384
+
4385
+ this._locale = getLocale();
4386
+
4387
+ this._bubble();
4388
+ }
4389
+
4390
+ function isDuration (obj) {
4391
+ return obj instanceof Duration;
4392
+ }
4393
+
4394
+ function absRound (number) {
4395
+ if (number < 0) {
4396
+ return Math.round(-1 * number) * -1;
4397
+ } else {
4398
+ return Math.round(number);
4399
+ }
4400
+ }
4401
+
4402
+ // FORMATTING
4403
+
4404
+ function offset (token, separator) {
4405
+ addFormatToken(token, 0, 0, function () {
4406
+ var offset = this.utcOffset();
4407
+ var sign = '+';
4408
+ if (offset < 0) {
4409
+ offset = -offset;
4410
+ sign = '-';
4411
+ }
4412
+ return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
4413
+ });
4414
+ }
4415
+
4416
+ offset('Z', ':');
4417
+ offset('ZZ', '');
4418
+
4419
+ // PARSING
4420
+
4421
+ addRegexToken('Z', matchShortOffset);
4422
+ addRegexToken('ZZ', matchShortOffset);
4423
+ addParseToken(['Z', 'ZZ'], function (input, array, config) {
4424
+ config._useUTC = true;
4425
+ config._tzm = offsetFromString(matchShortOffset, input);
4426
+ });
4427
+
4428
+ // HELPERS
4429
+
4430
+ // timezone chunker
4431
+ // '+10:00' > ['10', '00']
4432
+ // '-1530' > ['-15', '30']
4433
+ var chunkOffset = /([\+\-]|\d\d)/gi;
4434
+
4435
+ function offsetFromString(matcher, string) {
4436
+ var matches = (string || '').match(matcher);
4437
+
4438
+ if (matches === null) {
4439
+ return null;
4440
+ }
4441
+
4442
+ var chunk = matches[matches.length - 1] || [];
4443
+ var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
4444
+ var minutes = +(parts[1] * 60) + toInt(parts[2]);
4445
+
4446
+ return minutes === 0 ?
4447
+ 0 :
4448
+ parts[0] === '+' ? minutes : -minutes;
4449
+ }
4450
+
4451
+ // Return a moment from input, that is local/utc/zone equivalent to model.
4452
+ function cloneWithOffset(input, model) {
4453
+ var res, diff;
4454
+ if (model._isUTC) {
4455
+ res = model.clone();
4456
+ diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
4457
+ // Use low-level api, because this fn is low-level api.
4458
+ res._d.setTime(res._d.valueOf() + diff);
4459
+ hooks.updateOffset(res, false);
4460
+ return res;
4461
+ } else {
4462
+ return createLocal(input).local();
4463
+ }
4464
+ }
4465
+
4466
+ function getDateOffset (m) {
4467
+ // On Firefox.24 Date#getTimezoneOffset returns a floating point.
4468
+ // https://github.com/moment/moment/pull/1871
4469
+ return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
4470
+ }
4471
+
4472
+ // HOOKS
4473
+
4474
+ // This function will be called whenever a moment is mutated.
4475
+ // It is intended to keep the offset in sync with the timezone.
4476
+ hooks.updateOffset = function () {};
4477
+
4478
+ // MOMENTS
4479
+
4480
+ // keepLocalTime = true means only change the timezone, without
4481
+ // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
4482
+ // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
4483
+ // +0200, so we adjust the time as needed, to be valid.
4484
+ //
4485
+ // Keeping the time actually adds/subtracts (one hour)
4486
+ // from the actual represented time. That is why we call updateOffset
4487
+ // a second time. In case it wants us to change the offset again
4488
+ // _changeInProgress == true case, then we have to adjust, because
4489
+ // there is no such time in the given timezone.
4490
+ function getSetOffset (input, keepLocalTime, keepMinutes) {
4491
+ var offset = this._offset || 0,
4492
+ localAdjust;
4493
+ if (!this.isValid()) {
4494
+ return input != null ? this : NaN;
4495
+ }
4496
+ if (input != null) {
4497
+ if (typeof input === 'string') {
4498
+ input = offsetFromString(matchShortOffset, input);
4499
+ if (input === null) {
4500
+ return this;
4501
+ }
4502
+ } else if (Math.abs(input) < 16 && !keepMinutes) {
4503
+ input = input * 60;
4504
+ }
4505
+ if (!this._isUTC && keepLocalTime) {
4506
+ localAdjust = getDateOffset(this);
4507
+ }
4508
+ this._offset = input;
4509
+ this._isUTC = true;
4510
+ if (localAdjust != null) {
4511
+ this.add(localAdjust, 'm');
4512
+ }
4513
+ if (offset !== input) {
4514
+ if (!keepLocalTime || this._changeInProgress) {
4515
+ addSubtract(this, createDuration(input - offset, 'm'), 1, false);
4516
+ } else if (!this._changeInProgress) {
4517
+ this._changeInProgress = true;
4518
+ hooks.updateOffset(this, true);
4519
+ this._changeInProgress = null;
4520
+ }
4521
+ }
4522
+ return this;
4523
+ } else {
4524
+ return this._isUTC ? offset : getDateOffset(this);
4525
+ }
4526
+ }
4527
+
4528
+ function getSetZone (input, keepLocalTime) {
4529
+ if (input != null) {
4530
+ if (typeof input !== 'string') {
4531
+ input = -input;
4532
+ }
4533
+
4534
+ this.utcOffset(input, keepLocalTime);
4535
+
4536
+ return this;
4537
+ } else {
4538
+ return -this.utcOffset();
4539
+ }
4540
+ }
4541
+
4542
+ function setOffsetToUTC (keepLocalTime) {
4543
+ return this.utcOffset(0, keepLocalTime);
4544
+ }
4545
+
4546
+ function setOffsetToLocal (keepLocalTime) {
4547
+ if (this._isUTC) {
4548
+ this.utcOffset(0, keepLocalTime);
4549
+ this._isUTC = false;
4550
+
4551
+ if (keepLocalTime) {
4552
+ this.subtract(getDateOffset(this), 'm');
4553
+ }
4554
+ }
4555
+ return this;
4556
+ }
4557
+
4558
+ function setOffsetToParsedOffset () {
4559
+ if (this._tzm != null) {
4560
+ this.utcOffset(this._tzm, false, true);
4561
+ } else if (typeof this._i === 'string') {
4562
+ var tZone = offsetFromString(matchOffset, this._i);
4563
+ if (tZone != null) {
4564
+ this.utcOffset(tZone);
4565
+ }
4566
+ else {
4567
+ this.utcOffset(0, true);
4568
+ }
4569
+ }
4570
+ return this;
4571
+ }
4572
+
4573
+ function hasAlignedHourOffset (input) {
4574
+ if (!this.isValid()) {
4575
+ return false;
4576
+ }
4577
+ input = input ? createLocal(input).utcOffset() : 0;
4578
+
4579
+ return (this.utcOffset() - input) % 60 === 0;
4580
+ }
4581
+
4582
+ function isDaylightSavingTime () {
4583
+ return (
4584
+ this.utcOffset() > this.clone().month(0).utcOffset() ||
4585
+ this.utcOffset() > this.clone().month(5).utcOffset()
4586
+ );
4587
+ }
4588
+
4589
+ function isDaylightSavingTimeShifted () {
4590
+ if (!isUndefined(this._isDSTShifted)) {
4591
+ return this._isDSTShifted;
4592
+ }
4593
+
4594
+ var c = {};
4595
+
4596
+ copyConfig(c, this);
4597
+ c = prepareConfig(c);
4598
+
4599
+ if (c._a) {
4600
+ var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
4601
+ this._isDSTShifted = this.isValid() &&
4602
+ compareArrays(c._a, other.toArray()) > 0;
4603
+ } else {
4604
+ this._isDSTShifted = false;
4605
+ }
4606
+
4607
+ return this._isDSTShifted;
4608
+ }
4609
+
4610
+ function isLocal () {
4611
+ return this.isValid() ? !this._isUTC : false;
4612
+ }
4613
+
4614
+ function isUtcOffset () {
4615
+ return this.isValid() ? this._isUTC : false;
4616
+ }
4617
+
4618
+ function isUtc () {
4619
+ return this.isValid() ? this._isUTC && this._offset === 0 : false;
4620
+ }
4621
+
4622
+ // ASP.NET json date format regex
4623
+ var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
4624
+
4625
+ // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
4626
+ // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
4627
+ // and further modified to allow for strings containing both week and day
4628
+ var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;
4629
+
4630
+ function createDuration (input, key) {
4631
+ var duration = input,
4632
+ // matching against regexp is expensive, do it on demand
4633
+ match = null,
4634
+ sign,
4635
+ ret,
4636
+ diffRes;
4637
+
4638
+ if (isDuration(input)) {
4639
+ duration = {
4640
+ ms : input._milliseconds,
4641
+ d : input._days,
4642
+ M : input._months
4643
+ };
4644
+ } else if (isNumber(input)) {
4645
+ duration = {};
4646
+ if (key) {
4647
+ duration[key] = input;
4648
+ } else {
4649
+ duration.milliseconds = input;
4650
+ }
4651
+ } else if (!!(match = aspNetRegex.exec(input))) {
4652
+ sign = (match[1] === '-') ? -1 : 1;
4653
+ duration = {
4654
+ y : 0,
4655
+ d : toInt(match[DATE]) * sign,
4656
+ h : toInt(match[HOUR]) * sign,
4657
+ m : toInt(match[MINUTE]) * sign,
4658
+ s : toInt(match[SECOND]) * sign,
4659
+ ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
4660
+ };
4661
+ } else if (!!(match = isoRegex.exec(input))) {
4662
+ sign = (match[1] === '-') ? -1 : 1;
4663
+ duration = {
4664
+ y : parseIso(match[2], sign),
4665
+ M : parseIso(match[3], sign),
4666
+ w : parseIso(match[4], sign),
4667
+ d : parseIso(match[5], sign),
4668
+ h : parseIso(match[6], sign),
4669
+ m : parseIso(match[7], sign),
4670
+ s : parseIso(match[8], sign)
4671
+ };
4672
+ } else if (duration == null) {// checks for null or undefined
4673
+ duration = {};
4674
+ } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
4675
+ diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
4676
+
4677
+ duration = {};
4678
+ duration.ms = diffRes.milliseconds;
4679
+ duration.M = diffRes.months;
4680
+ }
4681
+
4682
+ ret = new Duration(duration);
4683
+
4684
+ if (isDuration(input) && hasOwnProp(input, '_locale')) {
4685
+ ret._locale = input._locale;
4686
+ }
4687
+
4688
+ return ret;
4689
+ }
4690
+
4691
+ createDuration.fn = Duration.prototype;
4692
+ createDuration.invalid = createInvalid$1;
4693
+
4694
+ function parseIso (inp, sign) {
4695
+ // We'd normally use ~~inp for this, but unfortunately it also
4696
+ // converts floats to ints.
4697
+ // inp may be undefined, so careful calling replace on it.
4698
+ var res = inp && parseFloat(inp.replace(',', '.'));
4699
+ // apply sign while we're at it
4700
+ return (isNaN(res) ? 0 : res) * sign;
4701
+ }
4702
+
4703
+ function positiveMomentsDifference(base, other) {
4704
+ var res = {milliseconds: 0, months: 0};
4705
+
4706
+ res.months = other.month() - base.month() +
4707
+ (other.year() - base.year()) * 12;
4708
+ if (base.clone().add(res.months, 'M').isAfter(other)) {
4709
+ --res.months;
4710
+ }
4711
+
4712
+ res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
4713
+
4714
+ return res;
4715
+ }
4716
+
4717
+ function momentsDifference(base, other) {
4718
+ var res;
4719
+ if (!(base.isValid() && other.isValid())) {
4720
+ return {milliseconds: 0, months: 0};
4721
+ }
4722
+
4723
+ other = cloneWithOffset(other, base);
4724
+ if (base.isBefore(other)) {
4725
+ res = positiveMomentsDifference(base, other);
4726
+ } else {
4727
+ res = positiveMomentsDifference(other, base);
4728
+ res.milliseconds = -res.milliseconds;
4729
+ res.months = -res.months;
4730
+ }
4731
+
4732
+ return res;
4733
+ }
4734
+
4735
+ // TODO: remove 'name' arg after deprecation is removed
4736
+ function createAdder(direction, name) {
4737
+ return function (val, period) {
4738
+ var dur, tmp;
4739
+ //invert the arguments, but complain about it
4740
+ if (period !== null && !isNaN(+period)) {
4741
+ deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
4742
+ 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
4743
+ tmp = val; val = period; period = tmp;
4744
+ }
4745
+
4746
+ val = typeof val === 'string' ? +val : val;
4747
+ dur = createDuration(val, period);
4748
+ addSubtract(this, dur, direction);
4749
+ return this;
4750
+ };
4751
+ }
4752
+
4753
+ function addSubtract (mom, duration, isAdding, updateOffset) {
4754
+ var milliseconds = duration._milliseconds,
4755
+ days = absRound(duration._days),
4756
+ months = absRound(duration._months);
4757
+
4758
+ if (!mom.isValid()) {
4759
+ // No op
4760
+ return;
4761
+ }
4762
+
4763
+ updateOffset = updateOffset == null ? true : updateOffset;
4764
+
4765
+ if (milliseconds) {
4766
+ mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
4767
+ }
4768
+ if (days) {
4769
+ set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
4770
+ }
4771
+ if (months) {
4772
+ setMonth(mom, get(mom, 'Month') + months * isAdding);
4773
+ }
4774
+ if (updateOffset) {
4775
+ hooks.updateOffset(mom, days || months);
4776
+ }
4777
+ }
4778
+
4779
+ var add = createAdder(1, 'add');
4780
+ var subtract = createAdder(-1, 'subtract');
4781
+
4782
+ function getCalendarFormat(myMoment, now) {
4783
+ var diff = myMoment.diff(now, 'days', true);
4784
+ return diff < -6 ? 'sameElse' :
4785
+ diff < -1 ? 'lastWeek' :
4786
+ diff < 0 ? 'lastDay' :
4787
+ diff < 1 ? 'sameDay' :
4788
+ diff < 2 ? 'nextDay' :
4789
+ diff < 7 ? 'nextWeek' : 'sameElse';
4790
+ }
4791
+
4792
+ function calendar$1 (time, formats) {
4793
+ // We want to compare the start of today, vs this.
4794
+ // Getting start-of-today depends on whether we're local/utc/offset or not.
4795
+ var now = time || createLocal(),
4796
+ sod = cloneWithOffset(now, this).startOf('day'),
4797
+ format = hooks.calendarFormat(this, sod) || 'sameElse';
4798
+
4799
+ var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
4800
+
4801
+ return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
4802
+ }
4803
+
4804
+ function clone () {
4805
+ return new Moment(this);
4806
+ }
4807
+
4808
+ function isAfter (input, units) {
4809
+ var localInput = isMoment(input) ? input : createLocal(input);
4810
+ if (!(this.isValid() && localInput.isValid())) {
4811
+ return false;
4812
+ }
4813
+ units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
4814
+ if (units === 'millisecond') {
4815
+ return this.valueOf() > localInput.valueOf();
4816
+ } else {
4817
+ return localInput.valueOf() < this.clone().startOf(units).valueOf();
4818
+ }
4819
+ }
4820
+
4821
+ function isBefore (input, units) {
4822
+ var localInput = isMoment(input) ? input : createLocal(input);
4823
+ if (!(this.isValid() && localInput.isValid())) {
4824
+ return false;
4825
+ }
4826
+ units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
4827
+ if (units === 'millisecond') {
4828
+ return this.valueOf() < localInput.valueOf();
4829
+ } else {
4830
+ return this.clone().endOf(units).valueOf() < localInput.valueOf();
4831
+ }
4832
+ }
4833
+
4834
+ function isBetween (from, to, units, inclusivity) {
4835
+ inclusivity = inclusivity || '()';
4836
+ return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
4837
+ (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
4838
+ }
4839
+
4840
+ function isSame (input, units) {
4841
+ var localInput = isMoment(input) ? input : createLocal(input),
4842
+ inputMs;
4843
+ if (!(this.isValid() && localInput.isValid())) {
4844
+ return false;
4845
+ }
4846
+ units = normalizeUnits(units || 'millisecond');
4847
+ if (units === 'millisecond') {
4848
+ return this.valueOf() === localInput.valueOf();
4849
+ } else {
4850
+ inputMs = localInput.valueOf();
4851
+ return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
4852
+ }
4853
+ }
4854
+
4855
+ function isSameOrAfter (input, units) {
4856
+ return this.isSame(input, units) || this.isAfter(input,units);
4857
+ }
4858
+
4859
+ function isSameOrBefore (input, units) {
4860
+ return this.isSame(input, units) || this.isBefore(input,units);
4861
+ }
4862
+
4863
+ function diff (input, units, asFloat) {
4864
+ var that,
4865
+ zoneDelta,
4866
+ delta, output;
4867
+
4868
+ if (!this.isValid()) {
4869
+ return NaN;
4870
+ }
4871
+
4872
+ that = cloneWithOffset(input, this);
4873
+
4874
+ if (!that.isValid()) {
4875
+ return NaN;
4876
+ }
4877
+
4878
+ zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
4879
+
4880
+ units = normalizeUnits(units);
4881
+
4882
+ if (units === 'year' || units === 'month' || units === 'quarter') {
4883
+ output = monthDiff(this, that);
4884
+ if (units === 'quarter') {
4885
+ output = output / 3;
4886
+ } else if (units === 'year') {
4887
+ output = output / 12;
4888
+ }
4889
+ } else {
4890
+ delta = this - that;
4891
+ output = units === 'second' ? delta / 1e3 : // 1000
4892
+ units === 'minute' ? delta / 6e4 : // 1000 * 60
4893
+ units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
4894
+ units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
4895
+ units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
4896
+ delta;
4897
+ }
4898
+ return asFloat ? output : absFloor(output);
4899
+ }
4900
+
4901
+ function monthDiff (a, b) {
4902
+ // difference in months
4903
+ var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
4904
+ // b is in (anchor - 1 month, anchor + 1 month)
4905
+ anchor = a.clone().add(wholeMonthDiff, 'months'),
4906
+ anchor2, adjust;
4907
+
4908
+ if (b - anchor < 0) {
4909
+ anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
4910
+ // linear across the month
4911
+ adjust = (b - anchor) / (anchor - anchor2);
4912
+ } else {
4913
+ anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
4914
+ // linear across the month
4915
+ adjust = (b - anchor) / (anchor2 - anchor);
4916
+ }
4917
+
4918
+ //check for negative zero, return zero if negative zero
4919
+ return -(wholeMonthDiff + adjust) || 0;
4920
+ }
4921
+
4922
+ hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
4923
+ hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
4924
+
4925
+ function toString () {
4926
+ return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
4927
+ }
4928
+
4929
+ function toISOString() {
4930
+ if (!this.isValid()) {
4931
+ return null;
4932
+ }
4933
+ var m = this.clone().utc();
4934
+ if (m.year() < 0 || m.year() > 9999) {
4935
+ return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
4936
+ }
4937
+ if (isFunction(Date.prototype.toISOString)) {
4938
+ // native implementation is ~50x faster, use it when we can
4939
+ return this.toDate().toISOString();
4940
+ }
4941
+ return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
4942
+ }
4943
+
4944
+ /**
4945
+ * Return a human readable representation of a moment that can
4946
+ * also be evaluated to get a new moment which is the same
4947
+ *
4948
+ * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
4949
+ */
4950
+ function inspect () {
4951
+ if (!this.isValid()) {
4952
+ return 'moment.invalid(/* ' + this._i + ' */)';
4953
+ }
4954
+ var func = 'moment';
4955
+ var zone = '';
4956
+ if (!this.isLocal()) {
4957
+ func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
4958
+ zone = 'Z';
4959
+ }
4960
+ var prefix = '[' + func + '("]';
4961
+ var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
4962
+ var datetime = '-MM-DD[T]HH:mm:ss.SSS';
4963
+ var suffix = zone + '[")]';
4964
+
4965
+ return this.format(prefix + year + datetime + suffix);
4966
+ }
4967
+
4968
+ function format (inputString) {
4969
+ if (!inputString) {
4970
+ inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
4971
+ }
4972
+ var output = formatMoment(this, inputString);
4973
+ return this.localeData().postformat(output);
4974
+ }
4975
+
4976
+ function from (time, withoutSuffix) {
4977
+ if (this.isValid() &&
4978
+ ((isMoment(time) && time.isValid()) ||
4979
+ createLocal(time).isValid())) {
4980
+ return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
4981
+ } else {
4982
+ return this.localeData().invalidDate();
4983
+ }
4984
+ }
4985
+
4986
+ function fromNow (withoutSuffix) {
4987
+ return this.from(createLocal(), withoutSuffix);
4988
+ }
4989
+
4990
+ function to (time, withoutSuffix) {
4991
+ if (this.isValid() &&
4992
+ ((isMoment(time) && time.isValid()) ||
4993
+ createLocal(time).isValid())) {
4994
+ return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
4995
+ } else {
4996
+ return this.localeData().invalidDate();
4997
+ }
4998
+ }
4999
+
5000
+ function toNow (withoutSuffix) {
5001
+ return this.to(createLocal(), withoutSuffix);
5002
+ }
5003
+
5004
+ // If passed a locale key, it will set the locale for this
5005
+ // instance. Otherwise, it will return the locale configuration
5006
+ // variables for this instance.
5007
+ function locale (key) {
5008
+ var newLocaleData;
5009
+
5010
+ if (key === undefined) {
5011
+ return this._locale._abbr;
5012
+ } else {
5013
+ newLocaleData = getLocale(key);
5014
+ if (newLocaleData != null) {
5015
+ this._locale = newLocaleData;
5016
+ }
5017
+ return this;
5018
+ }
5019
+ }
5020
+
5021
+ var lang = deprecate(
5022
+ 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
5023
+ function (key) {
5024
+ if (key === undefined) {
5025
+ return this.localeData();
5026
+ } else {
5027
+ return this.locale(key);
5028
+ }
5029
+ }
5030
+ );
5031
+
5032
+ function localeData () {
5033
+ return this._locale;
5034
+ }
5035
+
5036
+ function startOf (units) {
5037
+ units = normalizeUnits(units);
5038
+ // the following switch intentionally omits break keywords
5039
+ // to utilize falling through the cases.
5040
+ switch (units) {
5041
+ case 'year':
5042
+ this.month(0);
5043
+ /* falls through */
5044
+ case 'quarter':
5045
+ case 'month':
5046
+ this.date(1);
5047
+ /* falls through */
5048
+ case 'week':
5049
+ case 'isoWeek':
5050
+ case 'day':
5051
+ case 'date':
5052
+ this.hours(0);
5053
+ /* falls through */
5054
+ case 'hour':
5055
+ this.minutes(0);
5056
+ /* falls through */
5057
+ case 'minute':
5058
+ this.seconds(0);
5059
+ /* falls through */
5060
+ case 'second':
5061
+ this.milliseconds(0);
5062
+ }
5063
+
5064
+ // weeks are a special case
5065
+ if (units === 'week') {
5066
+ this.weekday(0);
5067
+ }
5068
+ if (units === 'isoWeek') {
5069
+ this.isoWeekday(1);
5070
+ }
5071
+
5072
+ // quarters are also special
5073
+ if (units === 'quarter') {
5074
+ this.month(Math.floor(this.month() / 3) * 3);
5075
+ }
5076
+
5077
+ return this;
5078
+ }
5079
+
5080
+ function endOf (units) {
5081
+ units = normalizeUnits(units);
5082
+ if (units === undefined || units === 'millisecond') {
5083
+ return this;
5084
+ }
5085
+
5086
+ // 'date' is an alias for 'day', so it should be considered as such.
5087
+ if (units === 'date') {
5088
+ units = 'day';
5089
+ }
5090
+
5091
+ return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
5092
+ }
5093
+
5094
+ function valueOf () {
5095
+ return this._d.valueOf() - ((this._offset || 0) * 60000);
5096
+ }
5097
+
5098
+ function unix () {
5099
+ return Math.floor(this.valueOf() / 1000);
5100
+ }
5101
+
5102
+ function toDate () {
5103
+ return new Date(this.valueOf());
5104
+ }
5105
+
5106
+ function toArray () {
5107
+ var m = this;
5108
+ return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
5109
+ }
5110
+
5111
+ function toObject () {
5112
+ var m = this;
5113
+ return {
5114
+ years: m.year(),
5115
+ months: m.month(),
5116
+ date: m.date(),
5117
+ hours: m.hours(),
5118
+ minutes: m.minutes(),
5119
+ seconds: m.seconds(),
5120
+ milliseconds: m.milliseconds()
5121
+ };
5122
+ }
5123
+
5124
+ function toJSON () {
5125
+ // new Date(NaN).toJSON() === null
5126
+ return this.isValid() ? this.toISOString() : null;
5127
+ }
5128
+
5129
+ function isValid$2 () {
5130
+ return isValid(this);
5131
+ }
5132
+
5133
+ function parsingFlags () {
5134
+ return extend({}, getParsingFlags(this));
5135
+ }
5136
+
5137
+ function invalidAt () {
5138
+ return getParsingFlags(this).overflow;
5139
+ }
5140
+
5141
+ function creationData() {
5142
+ return {
5143
+ input: this._i,
5144
+ format: this._f,
5145
+ locale: this._locale,
5146
+ isUTC: this._isUTC,
5147
+ strict: this._strict
5148
+ };
5149
+ }
5150
+
5151
+ // FORMATTING
5152
+
5153
+ addFormatToken(0, ['gg', 2], 0, function () {
5154
+ return this.weekYear() % 100;
5155
+ });
5156
+
5157
+ addFormatToken(0, ['GG', 2], 0, function () {
5158
+ return this.isoWeekYear() % 100;
5159
+ });
5160
+
5161
+ function addWeekYearFormatToken (token, getter) {
5162
+ addFormatToken(0, [token, token.length], 0, getter);
5163
+ }
5164
+
5165
+ addWeekYearFormatToken('gggg', 'weekYear');
5166
+ addWeekYearFormatToken('ggggg', 'weekYear');
5167
+ addWeekYearFormatToken('GGGG', 'isoWeekYear');
5168
+ addWeekYearFormatToken('GGGGG', 'isoWeekYear');
5169
+
5170
+ // ALIASES
5171
+
5172
+ addUnitAlias('weekYear', 'gg');
5173
+ addUnitAlias('isoWeekYear', 'GG');
5174
+
5175
+ // PRIORITY
5176
+
5177
+ addUnitPriority('weekYear', 1);
5178
+ addUnitPriority('isoWeekYear', 1);
5179
+
5180
+
5181
+ // PARSING
5182
+
5183
+ addRegexToken('G', matchSigned);
5184
+ addRegexToken('g', matchSigned);
5185
+ addRegexToken('GG', match1to2, match2);
5186
+ addRegexToken('gg', match1to2, match2);
5187
+ addRegexToken('GGGG', match1to4, match4);
5188
+ addRegexToken('gggg', match1to4, match4);
5189
+ addRegexToken('GGGGG', match1to6, match6);
5190
+ addRegexToken('ggggg', match1to6, match6);
5191
+
5192
+ addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
5193
+ week[token.substr(0, 2)] = toInt(input);
5194
+ });
5195
+
5196
+ addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
5197
+ week[token] = hooks.parseTwoDigitYear(input);
5198
+ });
5199
+
5200
+ // MOMENTS
5201
+
5202
+ function getSetWeekYear (input) {
5203
+ return getSetWeekYearHelper.call(this,
5204
+ input,
5205
+ this.week(),
5206
+ this.weekday(),
5207
+ this.localeData()._week.dow,
5208
+ this.localeData()._week.doy);
5209
+ }
5210
+
5211
+ function getSetISOWeekYear (input) {
5212
+ return getSetWeekYearHelper.call(this,
5213
+ input, this.isoWeek(), this.isoWeekday(), 1, 4);
5214
+ }
5215
+
5216
+ function getISOWeeksInYear () {
5217
+ return weeksInYear(this.year(), 1, 4);
5218
+ }
5219
+
5220
+ function getWeeksInYear () {
5221
+ var weekInfo = this.localeData()._week;
5222
+ return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
5223
+ }
5224
+
5225
+ function getSetWeekYearHelper(input, week, weekday, dow, doy) {
5226
+ var weeksTarget;
5227
+ if (input == null) {
5228
+ return weekOfYear(this, dow, doy).year;
5229
+ } else {
5230
+ weeksTarget = weeksInYear(input, dow, doy);
5231
+ if (week > weeksTarget) {
5232
+ week = weeksTarget;
5233
+ }
5234
+ return setWeekAll.call(this, input, week, weekday, dow, doy);
5235
+ }
5236
+ }
5237
+
5238
+ function setWeekAll(weekYear, week, weekday, dow, doy) {
5239
+ var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
5240
+ date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
5241
+
5242
+ this.year(date.getUTCFullYear());
5243
+ this.month(date.getUTCMonth());
5244
+ this.date(date.getUTCDate());
5245
+ return this;
5246
+ }
5247
+
5248
+ // FORMATTING
5249
+
5250
+ addFormatToken('Q', 0, 'Qo', 'quarter');
5251
+
5252
+ // ALIASES
5253
+
5254
+ addUnitAlias('quarter', 'Q');
5255
+
5256
+ // PRIORITY
5257
+
5258
+ addUnitPriority('quarter', 7);
5259
+
5260
+ // PARSING
5261
+
5262
+ addRegexToken('Q', match1);
5263
+ addParseToken('Q', function (input, array) {
5264
+ array[MONTH] = (toInt(input) - 1) * 3;
5265
+ });
5266
+
5267
+ // MOMENTS
5268
+
5269
+ function getSetQuarter (input) {
5270
+ return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
5271
+ }
5272
+
5273
+ // FORMATTING
5274
+
5275
+ addFormatToken('D', ['DD', 2], 'Do', 'date');
5276
+
5277
+ // ALIASES
5278
+
5279
+ addUnitAlias('date', 'D');
5280
+
5281
+ // PRIOROITY
5282
+ addUnitPriority('date', 9);
5283
+
5284
+ // PARSING
5285
+
5286
+ addRegexToken('D', match1to2);
5287
+ addRegexToken('DD', match1to2, match2);
5288
+ addRegexToken('Do', function (isStrict, locale) {
5289
+ // TODO: Remove "ordinalParse" fallback in next major release.
5290
+ return isStrict ?
5291
+ (locale._dayOfMonthOrdinalParse || locale._ordinalParse) :
5292
+ locale._dayOfMonthOrdinalParseLenient;
5293
+ });
5294
+
5295
+ addParseToken(['D', 'DD'], DATE);
5296
+ addParseToken('Do', function (input, array) {
5297
+ array[DATE] = toInt(input.match(match1to2)[0], 10);
5298
+ });
5299
+
5300
+ // MOMENTS
5301
+
5302
+ var getSetDayOfMonth = makeGetSet('Date', true);
5303
+
5304
+ // FORMATTING
5305
+
5306
+ addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
5307
+
5308
+ // ALIASES
5309
+
5310
+ addUnitAlias('dayOfYear', 'DDD');
5311
+
5312
+ // PRIORITY
5313
+ addUnitPriority('dayOfYear', 4);
5314
+
5315
+ // PARSING
5316
+
5317
+ addRegexToken('DDD', match1to3);
5318
+ addRegexToken('DDDD', match3);
5319
+ addParseToken(['DDD', 'DDDD'], function (input, array, config) {
5320
+ config._dayOfYear = toInt(input);
5321
+ });
5322
+
5323
+ // HELPERS
5324
+
5325
+ // MOMENTS
5326
+
5327
+ function getSetDayOfYear (input) {
5328
+ var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
5329
+ return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
5330
+ }
5331
+
5332
+ // FORMATTING
5333
+
5334
+ addFormatToken('m', ['mm', 2], 0, 'minute');
5335
+
5336
+ // ALIASES
5337
+
5338
+ addUnitAlias('minute', 'm');
5339
+
5340
+ // PRIORITY
5341
+
5342
+ addUnitPriority('minute', 14);
5343
+
5344
+ // PARSING
5345
+
5346
+ addRegexToken('m', match1to2);
5347
+ addRegexToken('mm', match1to2, match2);
5348
+ addParseToken(['m', 'mm'], MINUTE);
5349
+
5350
+ // MOMENTS
5351
+
5352
+ var getSetMinute = makeGetSet('Minutes', false);
5353
+
5354
+ // FORMATTING
5355
+
5356
+ addFormatToken('s', ['ss', 2], 0, 'second');
5357
+
5358
+ // ALIASES
5359
+
5360
+ addUnitAlias('second', 's');
5361
+
5362
+ // PRIORITY
5363
+
5364
+ addUnitPriority('second', 15);
5365
+
5366
+ // PARSING
5367
+
5368
+ addRegexToken('s', match1to2);
5369
+ addRegexToken('ss', match1to2, match2);
5370
+ addParseToken(['s', 'ss'], SECOND);
5371
+
5372
+ // MOMENTS
5373
+
5374
+ var getSetSecond = makeGetSet('Seconds', false);
5375
+
5376
+ // FORMATTING
5377
+
5378
+ addFormatToken('S', 0, 0, function () {
5379
+ return ~~(this.millisecond() / 100);
5380
+ });
5381
+
5382
+ addFormatToken(0, ['SS', 2], 0, function () {
5383
+ return ~~(this.millisecond() / 10);
5384
+ });
5385
+
5386
+ addFormatToken(0, ['SSS', 3], 0, 'millisecond');
5387
+ addFormatToken(0, ['SSSS', 4], 0, function () {
5388
+ return this.millisecond() * 10;
5389
+ });
5390
+ addFormatToken(0, ['SSSSS', 5], 0, function () {
5391
+ return this.millisecond() * 100;
5392
+ });
5393
+ addFormatToken(0, ['SSSSSS', 6], 0, function () {
5394
+ return this.millisecond() * 1000;
5395
+ });
5396
+ addFormatToken(0, ['SSSSSSS', 7], 0, function () {
5397
+ return this.millisecond() * 10000;
5398
+ });
5399
+ addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
5400
+ return this.millisecond() * 100000;
5401
+ });
5402
+ addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
5403
+ return this.millisecond() * 1000000;
5404
+ });
5405
+
5406
+
5407
+ // ALIASES
5408
+
5409
+ addUnitAlias('millisecond', 'ms');
5410
+
5411
+ // PRIORITY
5412
+
5413
+ addUnitPriority('millisecond', 16);
5414
+
5415
+ // PARSING
5416
+
5417
+ addRegexToken('S', match1to3, match1);
5418
+ addRegexToken('SS', match1to3, match2);
5419
+ addRegexToken('SSS', match1to3, match3);
5420
+
5421
+ var token;
5422
+ for (token = 'SSSS'; token.length <= 9; token += 'S') {
5423
+ addRegexToken(token, matchUnsigned);
5424
+ }
5425
+
5426
+ function parseMs(input, array) {
5427
+ array[MILLISECOND] = toInt(('0.' + input) * 1000);
5428
+ }
5429
+
5430
+ for (token = 'S'; token.length <= 9; token += 'S') {
5431
+ addParseToken(token, parseMs);
5432
+ }
5433
+ // MOMENTS
5434
+
5435
+ var getSetMillisecond = makeGetSet('Milliseconds', false);
5436
+
5437
+ // FORMATTING
5438
+
5439
+ addFormatToken('z', 0, 0, 'zoneAbbr');
5440
+ addFormatToken('zz', 0, 0, 'zoneName');
5441
+
5442
+ // MOMENTS
5443
+
5444
+ function getZoneAbbr () {
5445
+ return this._isUTC ? 'UTC' : '';
5446
+ }
5447
+
5448
+ function getZoneName () {
5449
+ return this._isUTC ? 'Coordinated Universal Time' : '';
5450
+ }
5451
+
5452
+ var proto = Moment.prototype;
5453
+
5454
+ proto.add = add;
5455
+ proto.calendar = calendar$1;
5456
+ proto.clone = clone;
5457
+ proto.diff = diff;
5458
+ proto.endOf = endOf;
5459
+ proto.format = format;
5460
+ proto.from = from;
5461
+ proto.fromNow = fromNow;
5462
+ proto.to = to;
5463
+ proto.toNow = toNow;
5464
+ proto.get = stringGet;
5465
+ proto.invalidAt = invalidAt;
5466
+ proto.isAfter = isAfter;
5467
+ proto.isBefore = isBefore;
5468
+ proto.isBetween = isBetween;
5469
+ proto.isSame = isSame;
5470
+ proto.isSameOrAfter = isSameOrAfter;
5471
+ proto.isSameOrBefore = isSameOrBefore;
5472
+ proto.isValid = isValid$2;
5473
+ proto.lang = lang;
5474
+ proto.locale = locale;
5475
+ proto.localeData = localeData;
5476
+ proto.max = prototypeMax;
5477
+ proto.min = prototypeMin;
5478
+ proto.parsingFlags = parsingFlags;
5479
+ proto.set = stringSet;
5480
+ proto.startOf = startOf;
5481
+ proto.subtract = subtract;
5482
+ proto.toArray = toArray;
5483
+ proto.toObject = toObject;
5484
+ proto.toDate = toDate;
5485
+ proto.toISOString = toISOString;
5486
+ proto.inspect = inspect;
5487
+ proto.toJSON = toJSON;
5488
+ proto.toString = toString;
5489
+ proto.unix = unix;
5490
+ proto.valueOf = valueOf;
5491
+ proto.creationData = creationData;
5492
+
5493
+ // Year
5494
+ proto.year = getSetYear;
5495
+ proto.isLeapYear = getIsLeapYear;
5496
+
5497
+ // Week Year
5498
+ proto.weekYear = getSetWeekYear;
5499
+ proto.isoWeekYear = getSetISOWeekYear;
5500
+
5501
+ // Quarter
5502
+ proto.quarter = proto.quarters = getSetQuarter;
5503
+
5504
+ // Month
5505
+ proto.month = getSetMonth;
5506
+ proto.daysInMonth = getDaysInMonth;
5507
+
5508
+ // Week
5509
+ proto.week = proto.weeks = getSetWeek;
5510
+ proto.isoWeek = proto.isoWeeks = getSetISOWeek;
5511
+ proto.weeksInYear = getWeeksInYear;
5512
+ proto.isoWeeksInYear = getISOWeeksInYear;
5513
+
5514
+ // Day
5515
+ proto.date = getSetDayOfMonth;
5516
+ proto.day = proto.days = getSetDayOfWeek;
5517
+ proto.weekday = getSetLocaleDayOfWeek;
5518
+ proto.isoWeekday = getSetISODayOfWeek;
5519
+ proto.dayOfYear = getSetDayOfYear;
5520
+
5521
+ // Hour
5522
+ proto.hour = proto.hours = getSetHour;
5523
+
5524
+ // Minute
5525
+ proto.minute = proto.minutes = getSetMinute;
5526
+
5527
+ // Second
5528
+ proto.second = proto.seconds = getSetSecond;
5529
+
5530
+ // Millisecond
5531
+ proto.millisecond = proto.milliseconds = getSetMillisecond;
5532
+
5533
+ // Offset
5534
+ proto.utcOffset = getSetOffset;
5535
+ proto.utc = setOffsetToUTC;
5536
+ proto.local = setOffsetToLocal;
5537
+ proto.parseZone = setOffsetToParsedOffset;
5538
+ proto.hasAlignedHourOffset = hasAlignedHourOffset;
5539
+ proto.isDST = isDaylightSavingTime;
5540
+ proto.isLocal = isLocal;
5541
+ proto.isUtcOffset = isUtcOffset;
5542
+ proto.isUtc = isUtc;
5543
+ proto.isUTC = isUtc;
5544
+
5545
+ // Timezone
5546
+ proto.zoneAbbr = getZoneAbbr;
5547
+ proto.zoneName = getZoneName;
5548
+
5549
+ // Deprecations
5550
+ proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
5551
+ proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
5552
+ proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);
5553
+ proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
5554
+ proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
5555
+
5556
+ function createUnix (input) {
5557
+ return createLocal(input * 1000);
5558
+ }
5559
+
5560
+ function createInZone () {
5561
+ return createLocal.apply(null, arguments).parseZone();
5562
+ }
5563
+
5564
+ function preParsePostFormat (string) {
5565
+ return string;
5566
+ }
5567
+
5568
+ var proto$1 = Locale.prototype;
5569
+
5570
+ proto$1.calendar = calendar;
5571
+ proto$1.longDateFormat = longDateFormat;
5572
+ proto$1.invalidDate = invalidDate;
5573
+ proto$1.ordinal = ordinal;
5574
+ proto$1.preparse = preParsePostFormat;
5575
+ proto$1.postformat = preParsePostFormat;
5576
+ proto$1.relativeTime = relativeTime;
5577
+ proto$1.pastFuture = pastFuture;
5578
+ proto$1.set = set;
5579
+
5580
+ // Month
5581
+ proto$1.months = localeMonths;
5582
+ proto$1.monthsShort = localeMonthsShort;
5583
+ proto$1.monthsParse = localeMonthsParse;
5584
+ proto$1.monthsRegex = monthsRegex;
5585
+ proto$1.monthsShortRegex = monthsShortRegex;
5586
+
5587
+ // Week
5588
+ proto$1.week = localeWeek;
5589
+ proto$1.firstDayOfYear = localeFirstDayOfYear;
5590
+ proto$1.firstDayOfWeek = localeFirstDayOfWeek;
5591
+
5592
+ // Day of Week
5593
+ proto$1.weekdays = localeWeekdays;
5594
+ proto$1.weekdaysMin = localeWeekdaysMin;
5595
+ proto$1.weekdaysShort = localeWeekdaysShort;
5596
+ proto$1.weekdaysParse = localeWeekdaysParse;
5597
+
5598
+ proto$1.weekdaysRegex = weekdaysRegex;
5599
+ proto$1.weekdaysShortRegex = weekdaysShortRegex;
5600
+ proto$1.weekdaysMinRegex = weekdaysMinRegex;
5601
+
5602
+ // Hours
5603
+ proto$1.isPM = localeIsPM;
5604
+ proto$1.meridiem = localeMeridiem;
5605
+
5606
+ function get$1 (format, index, field, setter) {
5607
+ var locale = getLocale();
5608
+ var utc = createUTC().set(setter, index);
5609
+ return locale[field](utc, format);
5610
+ }
5611
+
5612
+ function listMonthsImpl (format, index, field) {
5613
+ if (isNumber(format)) {
5614
+ index = format;
5615
+ format = undefined;
5616
+ }
5617
+
5618
+ format = format || '';
5619
+
5620
+ if (index != null) {
5621
+ return get$1(format, index, field, 'month');
5622
+ }
5623
+
5624
+ var i;
5625
+ var out = [];
5626
+ for (i = 0; i < 12; i++) {
5627
+ out[i] = get$1(format, i, field, 'month');
5628
+ }
5629
+ return out;
5630
+ }
5631
+
5632
+ // ()
5633
+ // (5)
5634
+ // (fmt, 5)
5635
+ // (fmt)
5636
+ // (true)
5637
+ // (true, 5)
5638
+ // (true, fmt, 5)
5639
+ // (true, fmt)
5640
+ function listWeekdaysImpl (localeSorted, format, index, field) {
5641
+ if (typeof localeSorted === 'boolean') {
5642
+ if (isNumber(format)) {
5643
+ index = format;
5644
+ format = undefined;
5645
+ }
5646
+
5647
+ format = format || '';
5648
+ } else {
5649
+ format = localeSorted;
5650
+ index = format;
5651
+ localeSorted = false;
5652
+
5653
+ if (isNumber(format)) {
5654
+ index = format;
5655
+ format = undefined;
5656
+ }
5657
+
5658
+ format = format || '';
5659
+ }
5660
+
5661
+ var locale = getLocale(),
5662
+ shift = localeSorted ? locale._week.dow : 0;
5663
+
5664
+ if (index != null) {
5665
+ return get$1(format, (index + shift) % 7, field, 'day');
5666
+ }
5667
+
5668
+ var i;
5669
+ var out = [];
5670
+ for (i = 0; i < 7; i++) {
5671
+ out[i] = get$1(format, (i + shift) % 7, field, 'day');
5672
+ }
5673
+ return out;
5674
+ }
5675
+
5676
+ function listMonths (format, index) {
5677
+ return listMonthsImpl(format, index, 'months');
5678
+ }
5679
+
5680
+ function listMonthsShort (format, index) {
5681
+ return listMonthsImpl(format, index, 'monthsShort');
5682
+ }
5683
+
5684
+ function listWeekdays (localeSorted, format, index) {
5685
+ return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
5686
+ }
5687
+
5688
+ function listWeekdaysShort (localeSorted, format, index) {
5689
+ return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
5690
+ }
5691
+
5692
+ function listWeekdaysMin (localeSorted, format, index) {
5693
+ return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
5694
+ }
5695
+
5696
+ getSetGlobalLocale('en', {
5697
+ dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
5698
+ ordinal : function (number) {
5699
+ var b = number % 10,
5700
+ output = (toInt(number % 100 / 10) === 1) ? 'th' :
5701
+ (b === 1) ? 'st' :
5702
+ (b === 2) ? 'nd' :
5703
+ (b === 3) ? 'rd' : 'th';
5704
+ return number + output;
5705
+ }
5706
+ });
5707
+
5708
+ // Side effect imports
5709
+ hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
5710
+ hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
5711
+
5712
+ var mathAbs = Math.abs;
5713
+
5714
+ function abs () {
5715
+ var data = this._data;
5716
+
5717
+ this._milliseconds = mathAbs(this._milliseconds);
5718
+ this._days = mathAbs(this._days);
5719
+ this._months = mathAbs(this._months);
5720
+
5721
+ data.milliseconds = mathAbs(data.milliseconds);
5722
+ data.seconds = mathAbs(data.seconds);
5723
+ data.minutes = mathAbs(data.minutes);
5724
+ data.hours = mathAbs(data.hours);
5725
+ data.months = mathAbs(data.months);
5726
+ data.years = mathAbs(data.years);
5727
+
5728
+ return this;
5729
+ }
5730
+
5731
+ function addSubtract$1 (duration, input, value, direction) {
5732
+ var other = createDuration(input, value);
5733
+
5734
+ duration._milliseconds += direction * other._milliseconds;
5735
+ duration._days += direction * other._days;
5736
+ duration._months += direction * other._months;
5737
+
5738
+ return duration._bubble();
5739
+ }
5740
+
5741
+ // supports only 2.0-style add(1, 's') or add(duration)
5742
+ function add$1 (input, value) {
5743
+ return addSubtract$1(this, input, value, 1);
5744
+ }
5745
+
5746
+ // supports only 2.0-style subtract(1, 's') or subtract(duration)
5747
+ function subtract$1 (input, value) {
5748
+ return addSubtract$1(this, input, value, -1);
5749
+ }
5750
+
5751
+ function absCeil (number) {
5752
+ if (number < 0) {
5753
+ return Math.floor(number);
5754
+ } else {
5755
+ return Math.ceil(number);
5756
+ }
5757
+ }
5758
+
5759
+ function bubble () {
5760
+ var milliseconds = this._milliseconds;
5761
+ var days = this._days;
5762
+ var months = this._months;
5763
+ var data = this._data;
5764
+ var seconds, minutes, hours, years, monthsFromDays;
5765
+
5766
+ // if we have a mix of positive and negative values, bubble down first
5767
+ // check: https://github.com/moment/moment/issues/2166
5768
+ if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
5769
+ (milliseconds <= 0 && days <= 0 && months <= 0))) {
5770
+ milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
5771
+ days = 0;
5772
+ months = 0;
5773
+ }
5774
+
5775
+ // The following code bubbles up values, see the tests for
5776
+ // examples of what that means.
5777
+ data.milliseconds = milliseconds % 1000;
5778
+
5779
+ seconds = absFloor(milliseconds / 1000);
5780
+ data.seconds = seconds % 60;
5781
+
5782
+ minutes = absFloor(seconds / 60);
5783
+ data.minutes = minutes % 60;
5784
+
5785
+ hours = absFloor(minutes / 60);
5786
+ data.hours = hours % 24;
5787
+
5788
+ days += absFloor(hours / 24);
5789
+
5790
+ // convert days to months
5791
+ monthsFromDays = absFloor(daysToMonths(days));
5792
+ months += monthsFromDays;
5793
+ days -= absCeil(monthsToDays(monthsFromDays));
5794
+
5795
+ // 12 months -> 1 year
5796
+ years = absFloor(months / 12);
5797
+ months %= 12;
5798
+
5799
+ data.days = days;
5800
+ data.months = months;
5801
+ data.years = years;
5802
+
5803
+ return this;
5804
+ }
5805
+
5806
+ function daysToMonths (days) {
5807
+ // 400 years have 146097 days (taking into account leap year rules)
5808
+ // 400 years have 12 months === 4800
5809
+ return days * 4800 / 146097;
5810
+ }
5811
+
5812
+ function monthsToDays (months) {
5813
+ // the reverse of daysToMonths
5814
+ return months * 146097 / 4800;
5815
+ }
5816
+
5817
+ function as (units) {
5818
+ if (!this.isValid()) {
5819
+ return NaN;
5820
+ }
5821
+ var days;
5822
+ var months;
5823
+ var milliseconds = this._milliseconds;
5824
+
5825
+ units = normalizeUnits(units);
5826
+
5827
+ if (units === 'month' || units === 'year') {
5828
+ days = this._days + milliseconds / 864e5;
5829
+ months = this._months + daysToMonths(days);
5830
+ return units === 'month' ? months : months / 12;
5831
+ } else {
5832
+ // handle milliseconds separately because of floating point math errors (issue #1867)
5833
+ days = this._days + Math.round(monthsToDays(this._months));
5834
+ switch (units) {
5835
+ case 'week' : return days / 7 + milliseconds / 6048e5;
5836
+ case 'day' : return days + milliseconds / 864e5;
5837
+ case 'hour' : return days * 24 + milliseconds / 36e5;
5838
+ case 'minute' : return days * 1440 + milliseconds / 6e4;
5839
+ case 'second' : return days * 86400 + milliseconds / 1000;
5840
+ // Math.floor prevents floating point math errors here
5841
+ case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
5842
+ default: throw new Error('Unknown unit ' + units);
5843
+ }
5844
+ }
5845
+ }
5846
+
5847
+ // TODO: Use this.as('ms')?
5848
+ function valueOf$1 () {
5849
+ if (!this.isValid()) {
5850
+ return NaN;
5851
+ }
5852
+ return (
5853
+ this._milliseconds +
5854
+ this._days * 864e5 +
5855
+ (this._months % 12) * 2592e6 +
5856
+ toInt(this._months / 12) * 31536e6
5857
+ );
5858
+ }
5859
+
5860
+ function makeAs (alias) {
5861
+ return function () {
5862
+ return this.as(alias);
5863
+ };
5864
+ }
5865
+
5866
+ var asMilliseconds = makeAs('ms');
5867
+ var asSeconds = makeAs('s');
5868
+ var asMinutes = makeAs('m');
5869
+ var asHours = makeAs('h');
5870
+ var asDays = makeAs('d');
5871
+ var asWeeks = makeAs('w');
5872
+ var asMonths = makeAs('M');
5873
+ var asYears = makeAs('y');
5874
+
5875
+ function get$2 (units) {
5876
+ units = normalizeUnits(units);
5877
+ return this.isValid() ? this[units + 's']() : NaN;
5878
+ }
5879
+
5880
+ function makeGetter(name) {
5881
+ return function () {
5882
+ return this.isValid() ? this._data[name] : NaN;
5883
+ };
5884
+ }
5885
+
5886
+ var milliseconds = makeGetter('milliseconds');
5887
+ var seconds = makeGetter('seconds');
5888
+ var minutes = makeGetter('minutes');
5889
+ var hours = makeGetter('hours');
5890
+ var days = makeGetter('days');
5891
+ var months = makeGetter('months');
5892
+ var years = makeGetter('years');
5893
+
5894
+ function weeks () {
5895
+ return absFloor(this.days() / 7);
5896
+ }
5897
+
5898
+ var round = Math.round;
5899
+ var thresholds = {
5900
+ ss: 44, // a few seconds to seconds
5901
+ s : 45, // seconds to minute
5902
+ m : 45, // minutes to hour
5903
+ h : 22, // hours to day
5904
+ d : 26, // days to month
5905
+ M : 11 // months to year
5906
+ };
5907
+
5908
+ // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
5909
+ function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
5910
+ return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
5911
+ }
5912
+
5913
+ function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
5914
+ var duration = createDuration(posNegDuration).abs();
5915
+ var seconds = round(duration.as('s'));
5916
+ var minutes = round(duration.as('m'));
5917
+ var hours = round(duration.as('h'));
5918
+ var days = round(duration.as('d'));
5919
+ var months = round(duration.as('M'));
5920
+ var years = round(duration.as('y'));
5921
+
5922
+ var a = seconds <= thresholds.ss && ['s', seconds] ||
5923
+ seconds < thresholds.s && ['ss', seconds] ||
5924
+ minutes <= 1 && ['m'] ||
5925
+ minutes < thresholds.m && ['mm', minutes] ||
5926
+ hours <= 1 && ['h'] ||
5927
+ hours < thresholds.h && ['hh', hours] ||
5928
+ days <= 1 && ['d'] ||
5929
+ days < thresholds.d && ['dd', days] ||
5930
+ months <= 1 && ['M'] ||
5931
+ months < thresholds.M && ['MM', months] ||
5932
+ years <= 1 && ['y'] || ['yy', years];
5933
+
5934
+ a[2] = withoutSuffix;
5935
+ a[3] = +posNegDuration > 0;
5936
+ a[4] = locale;
5937
+ return substituteTimeAgo.apply(null, a);
5938
+ }
5939
+
5940
+ // This function allows you to set the rounding function for relative time strings
5941
+ function getSetRelativeTimeRounding (roundingFunction) {
5942
+ if (roundingFunction === undefined) {
5943
+ return round;
5944
+ }
5945
+ if (typeof(roundingFunction) === 'function') {
5946
+ round = roundingFunction;
5947
+ return true;
5948
+ }
5949
+ return false;
5950
+ }
5951
+
5952
+ // This function allows you to set a threshold for relative time strings
5953
+ function getSetRelativeTimeThreshold (threshold, limit) {
5954
+ if (thresholds[threshold] === undefined) {
5955
+ return false;
5956
+ }
5957
+ if (limit === undefined) {
5958
+ return thresholds[threshold];
5959
+ }
5960
+ thresholds[threshold] = limit;
5961
+ if (threshold === 's') {
5962
+ thresholds.ss = limit - 1;
5963
+ }
5964
+ return true;
5965
+ }
5966
+
5967
+ function humanize (withSuffix) {
5968
+ if (!this.isValid()) {
5969
+ return this.localeData().invalidDate();
5970
+ }
5971
+
5972
+ var locale = this.localeData();
5973
+ var output = relativeTime$1(this, !withSuffix, locale);
5974
+
5975
+ if (withSuffix) {
5976
+ output = locale.pastFuture(+this, output);
5977
+ }
5978
+
5979
+ return locale.postformat(output);
5980
+ }
5981
+
5982
+ var abs$1 = Math.abs;
5983
+
5984
+ function toISOString$1() {
5985
+ // for ISO strings we do not use the normal bubbling rules:
5986
+ // * milliseconds bubble up until they become hours
5987
+ // * days do not bubble at all
5988
+ // * months bubble up until they become years
5989
+ // This is because there is no context-free conversion between hours and days
5990
+ // (think of clock changes)
5991
+ // and also not between days and months (28-31 days per month)
5992
+ if (!this.isValid()) {
5993
+ return this.localeData().invalidDate();
5994
+ }
5995
+
5996
+ var seconds = abs$1(this._milliseconds) / 1000;
5997
+ var days = abs$1(this._days);
5998
+ var months = abs$1(this._months);
5999
+ var minutes, hours, years;
6000
+
6001
+ // 3600 seconds -> 60 minutes -> 1 hour
6002
+ minutes = absFloor(seconds / 60);
6003
+ hours = absFloor(minutes / 60);
6004
+ seconds %= 60;
6005
+ minutes %= 60;
6006
+
6007
+ // 12 months -> 1 year
6008
+ years = absFloor(months / 12);
6009
+ months %= 12;
6010
+
6011
+
6012
+ // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
6013
+ var Y = years;
6014
+ var M = months;
6015
+ var D = days;
6016
+ var h = hours;
6017
+ var m = minutes;
6018
+ var s = seconds;
6019
+ var total = this.asSeconds();
6020
+
6021
+ if (!total) {
6022
+ // this is the same as C#'s (Noda) and python (isodate)...
6023
+ // but not other JS (goog.date)
6024
+ return 'P0D';
6025
+ }
6026
+
6027
+ return (total < 0 ? '-' : '') +
6028
+ 'P' +
6029
+ (Y ? Y + 'Y' : '') +
6030
+ (M ? M + 'M' : '') +
6031
+ (D ? D + 'D' : '') +
6032
+ ((h || m || s) ? 'T' : '') +
6033
+ (h ? h + 'H' : '') +
6034
+ (m ? m + 'M' : '') +
6035
+ (s ? s + 'S' : '');
6036
+ }
6037
+
6038
+ var proto$2 = Duration.prototype;
6039
+
6040
+ proto$2.isValid = isValid$1;
6041
+ proto$2.abs = abs;
6042
+ proto$2.add = add$1;
6043
+ proto$2.subtract = subtract$1;
6044
+ proto$2.as = as;
6045
+ proto$2.asMilliseconds = asMilliseconds;
6046
+ proto$2.asSeconds = asSeconds;
6047
+ proto$2.asMinutes = asMinutes;
6048
+ proto$2.asHours = asHours;
6049
+ proto$2.asDays = asDays;
6050
+ proto$2.asWeeks = asWeeks;
6051
+ proto$2.asMonths = asMonths;
6052
+ proto$2.asYears = asYears;
6053
+ proto$2.valueOf = valueOf$1;
6054
+ proto$2._bubble = bubble;
6055
+ proto$2.get = get$2;
6056
+ proto$2.milliseconds = milliseconds;
6057
+ proto$2.seconds = seconds;
6058
+ proto$2.minutes = minutes;
6059
+ proto$2.hours = hours;
6060
+ proto$2.days = days;
6061
+ proto$2.weeks = weeks;
6062
+ proto$2.months = months;
6063
+ proto$2.years = years;
6064
+ proto$2.humanize = humanize;
6065
+ proto$2.toISOString = toISOString$1;
6066
+ proto$2.toString = toISOString$1;
6067
+ proto$2.toJSON = toISOString$1;
6068
+ proto$2.locale = locale;
6069
+ proto$2.localeData = localeData;
6070
+
6071
+ // Deprecations
6072
+ proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
6073
+ proto$2.lang = lang;
6074
+
6075
+ // Side effect imports
6076
+
6077
+ // FORMATTING
6078
+
6079
+ addFormatToken('X', 0, 0, 'unix');
6080
+ addFormatToken('x', 0, 0, 'valueOf');
6081
+
6082
+ // PARSING
6083
+
6084
+ addRegexToken('x', matchSigned);
6085
+ addRegexToken('X', matchTimestamp);
6086
+ addParseToken('X', function (input, array, config) {
6087
+ config._d = new Date(parseFloat(input, 10) * 1000);
6088
+ });
6089
+ addParseToken('x', function (input, array, config) {
6090
+ config._d = new Date(toInt(input));
6091
+ });
6092
+
6093
+ // Side effect imports
6094
+
6095
+
6096
+ hooks.version = '2.18.1';
6097
+
6098
+ setHookCallback(createLocal);
6099
+
6100
+ hooks.fn = proto;
6101
+ hooks.min = min;
6102
+ hooks.max = max;
6103
+ hooks.now = now;
6104
+ hooks.utc = createUTC;
6105
+ hooks.unix = createUnix;
6106
+ hooks.months = listMonths;
6107
+ hooks.isDate = isDate;
6108
+ hooks.locale = getSetGlobalLocale;
6109
+ hooks.invalid = createInvalid;
6110
+ hooks.duration = createDuration;
6111
+ hooks.isMoment = isMoment;
6112
+ hooks.weekdays = listWeekdays;
6113
+ hooks.parseZone = createInZone;
6114
+ hooks.localeData = getLocale;
6115
+ hooks.isDuration = isDuration;
6116
+ hooks.monthsShort = listMonthsShort;
6117
+ hooks.weekdaysMin = listWeekdaysMin;
6118
+ hooks.defineLocale = defineLocale;
6119
+ hooks.updateLocale = updateLocale;
6120
+ hooks.locales = listLocales;
6121
+ hooks.weekdaysShort = listWeekdaysShort;
6122
+ hooks.normalizeUnits = normalizeUnits;
6123
+ hooks.relativeTimeRounding = getSetRelativeTimeRounding;
6124
+ hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
6125
+ hooks.calendarFormat = getCalendarFormat;
6126
+ hooks.prototype = proto;
6127
+
6128
+ return hooks;
6129
+
6130
+ })));
6131
+
6132
+ },{}],7:[function(require,module,exports){
6133
+ /**
6134
+ * @namespace Chart
6135
+ */
6136
+ var Chart = require(29)();
6137
+
6138
+ Chart.helpers = require(45);
6139
+
6140
+ // @todo dispatch these helpers into appropriated helpers/helpers.* file and write unit tests!
6141
+ require(27)(Chart);
6142
+
6143
+ Chart.defaults = require(25);
6144
+ Chart.Element = require(26);
6145
+ Chart.elements = require(40);
6146
+ Chart.Interaction = require(28);
6147
+ Chart.platform = require(48);
6148
+
6149
+ require(31)(Chart);
6150
+ require(22)(Chart);
6151
+ require(23)(Chart);
6152
+ require(24)(Chart);
6153
+ require(30)(Chart);
6154
+ require(33)(Chart);
6155
+ require(32)(Chart);
6156
+ require(35)(Chart);
6157
+
6158
+ require(54)(Chart);
6159
+ require(52)(Chart);
6160
+ require(53)(Chart);
6161
+ require(55)(Chart);
6162
+ require(56)(Chart);
6163
+ require(57)(Chart);
6164
+
6165
+ // Controllers must be loaded after elements
6166
+ // See Chart.core.datasetController.dataElementType
6167
+ require(15)(Chart);
6168
+ require(16)(Chart);
6169
+ require(17)(Chart);
6170
+ require(18)(Chart);
6171
+ require(19)(Chart);
6172
+ require(20)(Chart);
6173
+ require(21)(Chart);
6174
+
6175
+ require(8)(Chart);
6176
+ require(9)(Chart);
6177
+ require(10)(Chart);
6178
+ require(11)(Chart);
6179
+ require(12)(Chart);
6180
+ require(13)(Chart);
6181
+ require(14)(Chart);
6182
+
6183
+ // Loading built-it plugins
6184
+ var plugins = [];
6185
+
6186
+ plugins.push(
6187
+ require(49)(Chart),
6188
+ require(50)(Chart),
6189
+ require(51)(Chart)
6190
+ );
6191
+
6192
+ Chart.plugins.register(plugins);
6193
+
6194
+ Chart.platform.initialize();
6195
+
6196
+ module.exports = Chart;
6197
+ if (typeof window !== 'undefined') {
6198
+ window.Chart = Chart;
6199
+ }
6200
+
6201
+ // DEPRECATIONS
6202
+
6203
+ /**
6204
+ * Provided for backward compatibility, use Chart.helpers.canvas instead.
6205
+ * @namespace Chart.canvasHelpers
6206
+ * @deprecated since version 2.6.0
6207
+ * @todo remove at version 3
6208
+ * @private
6209
+ */
6210
+ Chart.canvasHelpers = Chart.helpers.canvas;
6211
+
6212
+ },{"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16,"17":17,"18":18,"19":19,"20":20,"21":21,"22":22,"23":23,"24":24,"25":25,"26":26,"27":27,"28":28,"29":29,"30":30,"31":31,"32":32,"33":33,"35":35,"40":40,"45":45,"48":48,"49":49,"50":50,"51":51,"52":52,"53":53,"54":54,"55":55,"56":56,"57":57,"8":8,"9":9}],8:[function(require,module,exports){
6213
+ 'use strict';
6214
+
6215
+ module.exports = function(Chart) {
6216
+
6217
+ Chart.Bar = function(context, config) {
6218
+ config.type = 'bar';
6219
+
6220
+ return new Chart(context, config);
6221
+ };
6222
+
6223
+ };
6224
+
6225
+ },{}],9:[function(require,module,exports){
6226
+ 'use strict';
6227
+
6228
+ module.exports = function(Chart) {
6229
+
6230
+ Chart.Bubble = function(context, config) {
6231
+ config.type = 'bubble';
6232
+ return new Chart(context, config);
6233
+ };
6234
+
6235
+ };
6236
+
6237
+ },{}],10:[function(require,module,exports){
6238
+ 'use strict';
6239
+
6240
+ module.exports = function(Chart) {
6241
+
6242
+ Chart.Doughnut = function(context, config) {
6243
+ config.type = 'doughnut';
6244
+
6245
+ return new Chart(context, config);
6246
+ };
6247
+
6248
+ };
6249
+
6250
+ },{}],11:[function(require,module,exports){
6251
+ 'use strict';
6252
+
6253
+ module.exports = function(Chart) {
6254
+
6255
+ Chart.Line = function(context, config) {
6256
+ config.type = 'line';
6257
+
6258
+ return new Chart(context, config);
6259
+ };
6260
+
6261
+ };
6262
+
6263
+ },{}],12:[function(require,module,exports){
6264
+ 'use strict';
6265
+
6266
+ module.exports = function(Chart) {
6267
+
6268
+ Chart.PolarArea = function(context, config) {
6269
+ config.type = 'polarArea';
6270
+
6271
+ return new Chart(context, config);
6272
+ };
6273
+
6274
+ };
6275
+
6276
+ },{}],13:[function(require,module,exports){
6277
+ 'use strict';
6278
+
6279
+ module.exports = function(Chart) {
6280
+
6281
+ Chart.Radar = function(context, config) {
6282
+ config.type = 'radar';
6283
+
6284
+ return new Chart(context, config);
6285
+ };
6286
+
6287
+ };
6288
+
6289
+ },{}],14:[function(require,module,exports){
6290
+ 'use strict';
6291
+
6292
+ module.exports = function(Chart) {
6293
+ Chart.Scatter = function(context, config) {
6294
+ config.type = 'scatter';
6295
+ return new Chart(context, config);
6296
+ };
6297
+ };
6298
+
6299
+ },{}],15:[function(require,module,exports){
6300
+ 'use strict';
6301
+
6302
+ var defaults = require(25);
6303
+ var elements = require(40);
6304
+ var helpers = require(45);
6305
+
6306
+ defaults._set('bar', {
6307
+ hover: {
6308
+ mode: 'label'
6309
+ },
6310
+
6311
+ scales: {
6312
+ xAxes: [{
6313
+ type: 'category',
6314
+
6315
+ // Specific to Bar Controller
6316
+ categoryPercentage: 0.8,
6317
+ barPercentage: 0.9,
6318
+
6319
+ // offset settings
6320
+ offset: true,
6321
+
6322
+ // grid line settings
6323
+ gridLines: {
6324
+ offsetGridLines: true
6325
+ }
6326
+ }],
6327
+
6328
+ yAxes: [{
6329
+ type: 'linear'
6330
+ }]
6331
+ }
6332
+ });
6333
+
6334
+ defaults._set('horizontalBar', {
6335
+ hover: {
6336
+ mode: 'index',
6337
+ axis: 'y'
6338
+ },
6339
+
6340
+ scales: {
6341
+ xAxes: [{
6342
+ type: 'linear',
6343
+ position: 'bottom'
6344
+ }],
6345
+
6346
+ yAxes: [{
6347
+ position: 'left',
6348
+ type: 'category',
6349
+
6350
+ // Specific to Horizontal Bar Controller
6351
+ categoryPercentage: 0.8,
6352
+ barPercentage: 0.9,
6353
+
6354
+ // offset settings
6355
+ offset: true,
6356
+
6357
+ // grid line settings
6358
+ gridLines: {
6359
+ offsetGridLines: true
6360
+ }
6361
+ }]
6362
+ },
6363
+
6364
+ elements: {
6365
+ rectangle: {
6366
+ borderSkipped: 'left'
6367
+ }
6368
+ },
6369
+
6370
+ tooltips: {
6371
+ callbacks: {
6372
+ title: function(item, data) {
6373
+ // Pick first xLabel for now
6374
+ var title = '';
6375
+
6376
+ if (item.length > 0) {
6377
+ if (item[0].yLabel) {
6378
+ title = item[0].yLabel;
6379
+ } else if (data.labels.length > 0 && item[0].index < data.labels.length) {
6380
+ title = data.labels[item[0].index];
6381
+ }
6382
+ }
6383
+
6384
+ return title;
6385
+ },
6386
+
6387
+ label: function(item, data) {
6388
+ var datasetLabel = data.datasets[item.datasetIndex].label || '';
6389
+ return datasetLabel + ': ' + item.xLabel;
6390
+ }
6391
+ },
6392
+ mode: 'index',
6393
+ axis: 'y'
6394
+ }
6395
+ });
6396
+
6397
+ module.exports = function(Chart) {
6398
+
6399
+ Chart.controllers.bar = Chart.DatasetController.extend({
6400
+
6401
+ dataElementType: elements.Rectangle,
6402
+
6403
+ initialize: function() {
6404
+ var me = this;
6405
+ var meta;
6406
+
6407
+ Chart.DatasetController.prototype.initialize.apply(me, arguments);
6408
+
6409
+ meta = me.getMeta();
6410
+ meta.stack = me.getDataset().stack;
6411
+ meta.bar = true;
6412
+ },
6413
+
6414
+ update: function(reset) {
6415
+ var me = this;
6416
+ var rects = me.getMeta().data;
6417
+ var i, ilen;
6418
+
6419
+ me._ruler = me.getRuler();
6420
+
6421
+ for (i = 0, ilen = rects.length; i < ilen; ++i) {
6422
+ me.updateElement(rects[i], i, reset);
6423
+ }
6424
+ },
6425
+
6426
+ updateElement: function(rectangle, index, reset) {
6427
+ var me = this;
6428
+ var chart = me.chart;
6429
+ var meta = me.getMeta();
6430
+ var dataset = me.getDataset();
6431
+ var custom = rectangle.custom || {};
6432
+ var rectangleOptions = chart.options.elements.rectangle;
6433
+
6434
+ rectangle._xScale = me.getScaleForId(meta.xAxisID);
6435
+ rectangle._yScale = me.getScaleForId(meta.yAxisID);
6436
+ rectangle._datasetIndex = me.index;
6437
+ rectangle._index = index;
6438
+
6439
+ rectangle._model = {
6440
+ datasetLabel: dataset.label,
6441
+ label: chart.data.labels[index],
6442
+ borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleOptions.borderSkipped,
6443
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.backgroundColor, index, rectangleOptions.backgroundColor),
6444
+ borderColor: custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.borderColor, index, rectangleOptions.borderColor),
6445
+ borderWidth: custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.borderWidth, index, rectangleOptions.borderWidth)
6446
+ };
6447
+
6448
+ me.updateElementGeometry(rectangle, index, reset);
6449
+
6450
+ rectangle.pivot();
6451
+ },
6452
+
6453
+ /**
6454
+ * @private
6455
+ */
6456
+ updateElementGeometry: function(rectangle, index, reset) {
6457
+ var me = this;
6458
+ var model = rectangle._model;
6459
+ var vscale = me.getValueScale();
6460
+ var base = vscale.getBasePixel();
6461
+ var horizontal = vscale.isHorizontal();
6462
+ var ruler = me._ruler || me.getRuler();
6463
+ var vpixels = me.calculateBarValuePixels(me.index, index);
6464
+ var ipixels = me.calculateBarIndexPixels(me.index, index, ruler);
6465
+
6466
+ model.horizontal = horizontal;
6467
+ model.base = reset ? base : vpixels.base;
6468
+ model.x = horizontal ? reset ? base : vpixels.head : ipixels.center;
6469
+ model.y = horizontal ? ipixels.center : reset ? base : vpixels.head;
6470
+ model.height = horizontal ? ipixels.size : undefined;
6471
+ model.width = horizontal ? undefined : ipixels.size;
6472
+ },
6473
+
6474
+ /**
6475
+ * @private
6476
+ */
6477
+ getValueScaleId: function() {
6478
+ return this.getMeta().yAxisID;
6479
+ },
6480
+
6481
+ /**
6482
+ * @private
6483
+ */
6484
+ getIndexScaleId: function() {
6485
+ return this.getMeta().xAxisID;
6486
+ },
6487
+
6488
+ /**
6489
+ * @private
6490
+ */
6491
+ getValueScale: function() {
6492
+ return this.getScaleForId(this.getValueScaleId());
6493
+ },
6494
+
6495
+ /**
6496
+ * @private
6497
+ */
6498
+ getIndexScale: function() {
6499
+ return this.getScaleForId(this.getIndexScaleId());
6500
+ },
6501
+
6502
+ /**
6503
+ * Returns the effective number of stacks based on groups and bar visibility.
6504
+ * @private
6505
+ */
6506
+ getStackCount: function(last) {
6507
+ var me = this;
6508
+ var chart = me.chart;
6509
+ var scale = me.getIndexScale();
6510
+ var stacked = scale.options.stacked;
6511
+ var ilen = last === undefined ? chart.data.datasets.length : last + 1;
6512
+ var stacks = [];
6513
+ var i, meta;
6514
+
6515
+ for (i = 0; i < ilen; ++i) {
6516
+ meta = chart.getDatasetMeta(i);
6517
+ if (meta.bar && chart.isDatasetVisible(i) &&
6518
+ (stacked === false ||
6519
+ (stacked === true && stacks.indexOf(meta.stack) === -1) ||
6520
+ (stacked === undefined && (meta.stack === undefined || stacks.indexOf(meta.stack) === -1)))) {
6521
+ stacks.push(meta.stack);
6522
+ }
6523
+ }
6524
+
6525
+ return stacks.length;
6526
+ },
6527
+
6528
+ /**
6529
+ * Returns the stack index for the given dataset based on groups and bar visibility.
6530
+ * @private
6531
+ */
6532
+ getStackIndex: function(datasetIndex) {
6533
+ return this.getStackCount(datasetIndex) - 1;
6534
+ },
6535
+
6536
+ /**
6537
+ * @private
6538
+ */
6539
+ getRuler: function() {
6540
+ var me = this;
6541
+ var scale = me.getIndexScale();
6542
+ var stackCount = me.getStackCount();
6543
+ var datasetIndex = me.index;
6544
+ var pixels = [];
6545
+ var isHorizontal = scale.isHorizontal();
6546
+ var start = isHorizontal ? scale.left : scale.top;
6547
+ var end = start + (isHorizontal ? scale.width : scale.height);
6548
+ var i, ilen;
6549
+
6550
+ for (i = 0, ilen = me.getMeta().data.length; i < ilen; ++i) {
6551
+ pixels.push(scale.getPixelForValue(null, i, datasetIndex));
6552
+ }
6553
+
6554
+ return {
6555
+ pixels: pixels,
6556
+ start: start,
6557
+ end: end,
6558
+ stackCount: stackCount,
6559
+ scale: scale
6560
+ };
6561
+ },
6562
+
6563
+ /**
6564
+ * Note: pixel values are not clamped to the scale area.
6565
+ * @private
6566
+ */
6567
+ calculateBarValuePixels: function(datasetIndex, index) {
6568
+ var me = this;
6569
+ var chart = me.chart;
6570
+ var meta = me.getMeta();
6571
+ var scale = me.getValueScale();
6572
+ var datasets = chart.data.datasets;
6573
+ var value = scale.getRightValue(datasets[datasetIndex].data[index]);
6574
+ var stacked = scale.options.stacked;
6575
+ var stack = meta.stack;
6576
+ var start = 0;
6577
+ var i, imeta, ivalue, base, head, size;
6578
+
6579
+ if (stacked || (stacked === undefined && stack !== undefined)) {
6580
+ for (i = 0; i < datasetIndex; ++i) {
6581
+ imeta = chart.getDatasetMeta(i);
6582
+
6583
+ if (imeta.bar &&
6584
+ imeta.stack === stack &&
6585
+ imeta.controller.getValueScaleId() === scale.id &&
6586
+ chart.isDatasetVisible(i)) {
6587
+
6588
+ ivalue = scale.getRightValue(datasets[i].data[index]);
6589
+ if ((value < 0 && ivalue < 0) || (value >= 0 && ivalue > 0)) {
6590
+ start += ivalue;
6591
+ }
6592
+ }
6593
+ }
6594
+ }
6595
+
6596
+ base = scale.getPixelForValue(start);
6597
+ head = scale.getPixelForValue(start + value);
6598
+ size = (head - base) / 2;
6599
+
6600
+ return {
6601
+ size: size,
6602
+ base: base,
6603
+ head: head,
6604
+ center: head + size / 2
6605
+ };
6606
+ },
6607
+
6608
+ /**
6609
+ * @private
6610
+ */
6611
+ calculateBarIndexPixels: function(datasetIndex, index, ruler) {
6612
+ var me = this;
6613
+ var options = ruler.scale.options;
6614
+ var stackIndex = me.getStackIndex(datasetIndex);
6615
+ var pixels = ruler.pixels;
6616
+ var base = pixels[index];
6617
+ var length = pixels.length;
6618
+ var start = ruler.start;
6619
+ var end = ruler.end;
6620
+ var leftSampleSize, rightSampleSize, leftCategorySize, rightCategorySize, fullBarSize, size;
6621
+
6622
+ if (length === 1) {
6623
+ leftSampleSize = base > start ? base - start : end - base;
6624
+ rightSampleSize = base < end ? end - base : base - start;
6625
+ } else {
6626
+ if (index > 0) {
6627
+ leftSampleSize = (base - pixels[index - 1]) / 2;
6628
+ if (index === length - 1) {
6629
+ rightSampleSize = leftSampleSize;
6630
+ }
6631
+ }
6632
+ if (index < length - 1) {
6633
+ rightSampleSize = (pixels[index + 1] - base) / 2;
6634
+ if (index === 0) {
6635
+ leftSampleSize = rightSampleSize;
6636
+ }
6637
+ }
6638
+ }
6639
+
6640
+ leftCategorySize = leftSampleSize * options.categoryPercentage;
6641
+ rightCategorySize = rightSampleSize * options.categoryPercentage;
6642
+ fullBarSize = (leftCategorySize + rightCategorySize) / ruler.stackCount;
6643
+ size = fullBarSize * options.barPercentage;
6644
+
6645
+ size = Math.min(
6646
+ helpers.valueOrDefault(options.barThickness, size),
6647
+ helpers.valueOrDefault(options.maxBarThickness, Infinity));
6648
+
6649
+ base -= leftCategorySize;
6650
+ base += fullBarSize * stackIndex;
6651
+ base += (fullBarSize - size) / 2;
6652
+
6653
+ return {
6654
+ size: size,
6655
+ base: base,
6656
+ head: base + size,
6657
+ center: base + size / 2
6658
+ };
6659
+ },
6660
+
6661
+ draw: function() {
6662
+ var me = this;
6663
+ var chart = me.chart;
6664
+ var scale = me.getValueScale();
6665
+ var rects = me.getMeta().data;
6666
+ var dataset = me.getDataset();
6667
+ var ilen = rects.length;
6668
+ var i = 0;
6669
+
6670
+ helpers.canvas.clipArea(chart.ctx, chart.chartArea);
6671
+
6672
+ for (; i < ilen; ++i) {
6673
+ if (!isNaN(scale.getRightValue(dataset.data[i]))) {
6674
+ rects[i].draw();
6675
+ }
6676
+ }
6677
+
6678
+ helpers.canvas.unclipArea(chart.ctx);
6679
+ },
6680
+
6681
+ setHoverStyle: function(rectangle) {
6682
+ var dataset = this.chart.data.datasets[rectangle._datasetIndex];
6683
+ var index = rectangle._index;
6684
+ var custom = rectangle.custom || {};
6685
+ var model = rectangle._model;
6686
+
6687
+ model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.valueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
6688
+ model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.valueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));
6689
+ model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.valueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
6690
+ },
6691
+
6692
+ removeHoverStyle: function(rectangle) {
6693
+ var dataset = this.chart.data.datasets[rectangle._datasetIndex];
6694
+ var index = rectangle._index;
6695
+ var custom = rectangle.custom || {};
6696
+ var model = rectangle._model;
6697
+ var rectangleElementOptions = this.chart.options.elements.rectangle;
6698
+
6699
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor);
6700
+ model.borderColor = custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor);
6701
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth);
6702
+ }
6703
+ });
6704
+
6705
+ Chart.controllers.horizontalBar = Chart.controllers.bar.extend({
6706
+ /**
6707
+ * @private
6708
+ */
6709
+ getValueScaleId: function() {
6710
+ return this.getMeta().xAxisID;
6711
+ },
6712
+
6713
+ /**
6714
+ * @private
6715
+ */
6716
+ getIndexScaleId: function() {
6717
+ return this.getMeta().yAxisID;
6718
+ }
6719
+ });
6720
+ };
6721
+
6722
+ },{"25":25,"40":40,"45":45}],16:[function(require,module,exports){
6723
+ 'use strict';
6724
+
6725
+ var defaults = require(25);
6726
+ var elements = require(40);
6727
+ var helpers = require(45);
6728
+
6729
+ defaults._set('bubble', {
6730
+ hover: {
6731
+ mode: 'single'
6732
+ },
6733
+
6734
+ scales: {
6735
+ xAxes: [{
6736
+ type: 'linear', // bubble should probably use a linear scale by default
6737
+ position: 'bottom',
6738
+ id: 'x-axis-0' // need an ID so datasets can reference the scale
6739
+ }],
6740
+ yAxes: [{
6741
+ type: 'linear',
6742
+ position: 'left',
6743
+ id: 'y-axis-0'
6744
+ }]
6745
+ },
6746
+
6747
+ tooltips: {
6748
+ callbacks: {
6749
+ title: function() {
6750
+ // Title doesn't make sense for scatter since we format the data as a point
6751
+ return '';
6752
+ },
6753
+ label: function(item, data) {
6754
+ var datasetLabel = data.datasets[item.datasetIndex].label || '';
6755
+ var dataPoint = data.datasets[item.datasetIndex].data[item.index];
6756
+ return datasetLabel + ': (' + item.xLabel + ', ' + item.yLabel + ', ' + dataPoint.r + ')';
6757
+ }
6758
+ }
6759
+ }
6760
+ });
6761
+
6762
+
6763
+ module.exports = function(Chart) {
6764
+
6765
+ Chart.controllers.bubble = Chart.DatasetController.extend({
6766
+ /**
6767
+ * @protected
6768
+ */
6769
+ dataElementType: elements.Point,
6770
+
6771
+ /**
6772
+ * @protected
6773
+ */
6774
+ update: function(reset) {
6775
+ var me = this;
6776
+ var meta = me.getMeta();
6777
+ var points = meta.data;
6778
+
6779
+ // Update Points
6780
+ helpers.each(points, function(point, index) {
6781
+ me.updateElement(point, index, reset);
6782
+ });
6783
+ },
6784
+
6785
+ /**
6786
+ * @protected
6787
+ */
6788
+ updateElement: function(point, index, reset) {
6789
+ var me = this;
6790
+ var meta = me.getMeta();
6791
+ var custom = point.custom || {};
6792
+ var xScale = me.getScaleForId(meta.xAxisID);
6793
+ var yScale = me.getScaleForId(meta.yAxisID);
6794
+ var options = me._resolveElementOptions(point, index);
6795
+ var data = me.getDataset().data[index];
6796
+ var dsIndex = me.index;
6797
+
6798
+ var x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, index, dsIndex);
6799
+ var y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex);
6800
+
6801
+ point._xScale = xScale;
6802
+ point._yScale = yScale;
6803
+ point._options = options;
6804
+ point._datasetIndex = dsIndex;
6805
+ point._index = index;
6806
+ point._model = {
6807
+ backgroundColor: options.backgroundColor,
6808
+ borderColor: options.borderColor,
6809
+ borderWidth: options.borderWidth,
6810
+ hitRadius: options.hitRadius,
6811
+ pointStyle: options.pointStyle,
6812
+ radius: reset ? 0 : options.radius,
6813
+ skip: custom.skip || isNaN(x) || isNaN(y),
6814
+ x: x,
6815
+ y: y,
6816
+ };
6817
+
6818
+ point.pivot();
6819
+ },
6820
+
6821
+ /**
6822
+ * @protected
6823
+ */
6824
+ setHoverStyle: function(point) {
6825
+ var model = point._model;
6826
+ var options = point._options;
6827
+
6828
+ model.backgroundColor = helpers.valueOrDefault(options.hoverBackgroundColor, helpers.getHoverColor(options.backgroundColor));
6829
+ model.borderColor = helpers.valueOrDefault(options.hoverBorderColor, helpers.getHoverColor(options.borderColor));
6830
+ model.borderWidth = helpers.valueOrDefault(options.hoverBorderWidth, options.borderWidth);
6831
+ model.radius = options.radius + options.hoverRadius;
6832
+ },
6833
+
6834
+ /**
6835
+ * @protected
6836
+ */
6837
+ removeHoverStyle: function(point) {
6838
+ var model = point._model;
6839
+ var options = point._options;
6840
+
6841
+ model.backgroundColor = options.backgroundColor;
6842
+ model.borderColor = options.borderColor;
6843
+ model.borderWidth = options.borderWidth;
6844
+ model.radius = options.radius;
6845
+ },
6846
+
6847
+ /**
6848
+ * @private
6849
+ */
6850
+ _resolveElementOptions: function(point, index) {
6851
+ var me = this;
6852
+ var chart = me.chart;
6853
+ var datasets = chart.data.datasets;
6854
+ var dataset = datasets[me.index];
6855
+ var custom = point.custom || {};
6856
+ var options = chart.options.elements.point;
6857
+ var resolve = helpers.options.resolve;
6858
+ var data = dataset.data[index];
6859
+ var values = {};
6860
+ var i, ilen, key;
6861
+
6862
+ // Scriptable options
6863
+ var context = {
6864
+ chart: chart,
6865
+ dataIndex: index,
6866
+ dataset: dataset,
6867
+ datasetIndex: me.index
6868
+ };
6869
+
6870
+ var keys = [
6871
+ 'backgroundColor',
6872
+ 'borderColor',
6873
+ 'borderWidth',
6874
+ 'hoverBackgroundColor',
6875
+ 'hoverBorderColor',
6876
+ 'hoverBorderWidth',
6877
+ 'hoverRadius',
6878
+ 'hitRadius',
6879
+ 'pointStyle'
6880
+ ];
6881
+
6882
+ for (i = 0, ilen = keys.length; i < ilen; ++i) {
6883
+ key = keys[i];
6884
+ values[key] = resolve([
6885
+ custom[key],
6886
+ dataset[key],
6887
+ options[key]
6888
+ ], context, index);
6889
+ }
6890
+
6891
+ // Custom radius resolution
6892
+ values.radius = resolve([
6893
+ custom.radius,
6894
+ data ? data.r : undefined,
6895
+ dataset.radius,
6896
+ options.radius
6897
+ ], context, index);
6898
+
6899
+ return values;
6900
+ }
6901
+ });
6902
+ };
6903
+
6904
+ },{"25":25,"40":40,"45":45}],17:[function(require,module,exports){
6905
+ 'use strict';
6906
+
6907
+ var defaults = require(25);
6908
+ var elements = require(40);
6909
+ var helpers = require(45);
6910
+
6911
+ defaults._set('doughnut', {
6912
+ animation: {
6913
+ // Boolean - Whether we animate the rotation of the Doughnut
6914
+ animateRotate: true,
6915
+ // Boolean - Whether we animate scaling the Doughnut from the centre
6916
+ animateScale: false
6917
+ },
6918
+ hover: {
6919
+ mode: 'single'
6920
+ },
6921
+ legendCallback: function(chart) {
6922
+ var text = [];
6923
+ text.push('<ul class="' + chart.id + '-legend">');
6924
+
6925
+ var data = chart.data;
6926
+ var datasets = data.datasets;
6927
+ var labels = data.labels;
6928
+
6929
+ if (datasets.length) {
6930
+ for (var i = 0; i < datasets[0].data.length; ++i) {
6931
+ text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
6932
+ if (labels[i]) {
6933
+ text.push(labels[i]);
6934
+ }
6935
+ text.push('</li>');
6936
+ }
6937
+ }
6938
+
6939
+ text.push('</ul>');
6940
+ return text.join('');
6941
+ },
6942
+ legend: {
6943
+ labels: {
6944
+ generateLabels: function(chart) {
6945
+ var data = chart.data;
6946
+ if (data.labels.length && data.datasets.length) {
6947
+ return data.labels.map(function(label, i) {
6948
+ var meta = chart.getDatasetMeta(0);
6949
+ var ds = data.datasets[0];
6950
+ var arc = meta.data[i];
6951
+ var custom = arc && arc.custom || {};
6952
+ var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
6953
+ var arcOpts = chart.options.elements.arc;
6954
+ var fill = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
6955
+ var stroke = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
6956
+ var bw = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
6957
+
6958
+ return {
6959
+ text: label,
6960
+ fillStyle: fill,
6961
+ strokeStyle: stroke,
6962
+ lineWidth: bw,
6963
+ hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
6964
+
6965
+ // Extra data used for toggling the correct item
6966
+ index: i
6967
+ };
6968
+ });
6969
+ }
6970
+ return [];
6971
+ }
6972
+ },
6973
+
6974
+ onClick: function(e, legendItem) {
6975
+ var index = legendItem.index;
6976
+ var chart = this.chart;
6977
+ var i, ilen, meta;
6978
+
6979
+ for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
6980
+ meta = chart.getDatasetMeta(i);
6981
+ // toggle visibility of index if exists
6982
+ if (meta.data[index]) {
6983
+ meta.data[index].hidden = !meta.data[index].hidden;
6984
+ }
6985
+ }
6986
+
6987
+ chart.update();
6988
+ }
6989
+ },
6990
+
6991
+ // The percentage of the chart that we cut out of the middle.
6992
+ cutoutPercentage: 50,
6993
+
6994
+ // The rotation of the chart, where the first data arc begins.
6995
+ rotation: Math.PI * -0.5,
6996
+
6997
+ // The total circumference of the chart.
6998
+ circumference: Math.PI * 2.0,
6999
+
7000
+ // Need to override these to give a nice default
7001
+ tooltips: {
7002
+ callbacks: {
7003
+ title: function() {
7004
+ return '';
7005
+ },
7006
+ label: function(tooltipItem, data) {
7007
+ var dataLabel = data.labels[tooltipItem.index];
7008
+ var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
7009
+
7010
+ if (helpers.isArray(dataLabel)) {
7011
+ // show value on first line of multiline label
7012
+ // need to clone because we are changing the value
7013
+ dataLabel = dataLabel.slice();
7014
+ dataLabel[0] += value;
7015
+ } else {
7016
+ dataLabel += value;
7017
+ }
7018
+
7019
+ return dataLabel;
7020
+ }
7021
+ }
7022
+ }
7023
+ });
7024
+
7025
+ defaults._set('pie', helpers.clone(defaults.doughnut));
7026
+ defaults._set('pie', {
7027
+ cutoutPercentage: 0
7028
+ });
7029
+
7030
+ module.exports = function(Chart) {
7031
+
7032
+ Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({
7033
+
7034
+ dataElementType: elements.Arc,
7035
+
7036
+ linkScales: helpers.noop,
7037
+
7038
+ // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly
7039
+ getRingIndex: function(datasetIndex) {
7040
+ var ringIndex = 0;
7041
+
7042
+ for (var j = 0; j < datasetIndex; ++j) {
7043
+ if (this.chart.isDatasetVisible(j)) {
7044
+ ++ringIndex;
7045
+ }
7046
+ }
7047
+
7048
+ return ringIndex;
7049
+ },
7050
+
7051
+ update: function(reset) {
7052
+ var me = this;
7053
+ var chart = me.chart;
7054
+ var chartArea = chart.chartArea;
7055
+ var opts = chart.options;
7056
+ var arcOpts = opts.elements.arc;
7057
+ var availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth;
7058
+ var availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth;
7059
+ var minSize = Math.min(availableWidth, availableHeight);
7060
+ var offset = {x: 0, y: 0};
7061
+ var meta = me.getMeta();
7062
+ var cutoutPercentage = opts.cutoutPercentage;
7063
+ var circumference = opts.circumference;
7064
+
7065
+ // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc
7066
+ if (circumference < Math.PI * 2.0) {
7067
+ var startAngle = opts.rotation % (Math.PI * 2.0);
7068
+ startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);
7069
+ var endAngle = startAngle + circumference;
7070
+ var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};
7071
+ var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};
7072
+ var contains0 = (startAngle <= 0 && endAngle >= 0) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);
7073
+ var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);
7074
+ var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);
7075
+ var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);
7076
+ var cutout = cutoutPercentage / 100.0;
7077
+ var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))};
7078
+ var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))};
7079
+ var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};
7080
+ minSize = Math.min(availableWidth / size.width, availableHeight / size.height);
7081
+ offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};
7082
+ }
7083
+
7084
+ chart.borderWidth = me.getMaxBorderWidth(meta.data);
7085
+ chart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0);
7086
+ chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 0, 0);
7087
+ chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
7088
+ chart.offsetX = offset.x * chart.outerRadius;
7089
+ chart.offsetY = offset.y * chart.outerRadius;
7090
+
7091
+ meta.total = me.calculateTotal();
7092
+
7093
+ me.outerRadius = chart.outerRadius - (chart.radiusLength * me.getRingIndex(me.index));
7094
+ me.innerRadius = Math.max(me.outerRadius - chart.radiusLength, 0);
7095
+
7096
+ helpers.each(meta.data, function(arc, index) {
7097
+ me.updateElement(arc, index, reset);
7098
+ });
7099
+ },
7100
+
7101
+ updateElement: function(arc, index, reset) {
7102
+ var me = this;
7103
+ var chart = me.chart;
7104
+ var chartArea = chart.chartArea;
7105
+ var opts = chart.options;
7106
+ var animationOpts = opts.animation;
7107
+ var centerX = (chartArea.left + chartArea.right) / 2;
7108
+ var centerY = (chartArea.top + chartArea.bottom) / 2;
7109
+ var startAngle = opts.rotation; // non reset case handled later
7110
+ var endAngle = opts.rotation; // non reset case handled later
7111
+ var dataset = me.getDataset();
7112
+ var circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI));
7113
+ var innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius;
7114
+ var outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius;
7115
+ var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
7116
+
7117
+ helpers.extend(arc, {
7118
+ // Utility
7119
+ _datasetIndex: me.index,
7120
+ _index: index,
7121
+
7122
+ // Desired view properties
7123
+ _model: {
7124
+ x: centerX + chart.offsetX,
7125
+ y: centerY + chart.offsetY,
7126
+ startAngle: startAngle,
7127
+ endAngle: endAngle,
7128
+ circumference: circumference,
7129
+ outerRadius: outerRadius,
7130
+ innerRadius: innerRadius,
7131
+ label: valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index])
7132
+ }
7133
+ });
7134
+
7135
+ var model = arc._model;
7136
+ // Resets the visual styles
7137
+ this.removeHoverStyle(arc);
7138
+
7139
+ // Set correct angles if not resetting
7140
+ if (!reset || !animationOpts.animateRotate) {
7141
+ if (index === 0) {
7142
+ model.startAngle = opts.rotation;
7143
+ } else {
7144
+ model.startAngle = me.getMeta().data[index - 1]._model.endAngle;
7145
+ }
7146
+
7147
+ model.endAngle = model.startAngle + model.circumference;
7148
+ }
7149
+
7150
+ arc.pivot();
7151
+ },
7152
+
7153
+ removeHoverStyle: function(arc) {
7154
+ Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);
7155
+ },
7156
+
7157
+ calculateTotal: function() {
7158
+ var dataset = this.getDataset();
7159
+ var meta = this.getMeta();
7160
+ var total = 0;
7161
+ var value;
7162
+
7163
+ helpers.each(meta.data, function(element, index) {
7164
+ value = dataset.data[index];
7165
+ if (!isNaN(value) && !element.hidden) {
7166
+ total += Math.abs(value);
7167
+ }
7168
+ });
7169
+
7170
+ /* if (total === 0) {
7171
+ total = NaN;
7172
+ }*/
7173
+
7174
+ return total;
7175
+ },
7176
+
7177
+ calculateCircumference: function(value) {
7178
+ var total = this.getMeta().total;
7179
+ if (total > 0 && !isNaN(value)) {
7180
+ return (Math.PI * 2.0) * (value / total);
7181
+ }
7182
+ return 0;
7183
+ },
7184
+
7185
+ // gets the max border or hover width to properly scale pie charts
7186
+ getMaxBorderWidth: function(arcs) {
7187
+ var max = 0;
7188
+ var index = this.index;
7189
+ var length = arcs.length;
7190
+ var borderWidth;
7191
+ var hoverWidth;
7192
+
7193
+ for (var i = 0; i < length; i++) {
7194
+ borderWidth = arcs[i]._model ? arcs[i]._model.borderWidth : 0;
7195
+ hoverWidth = arcs[i]._chart ? arcs[i]._chart.config.data.datasets[index].hoverBorderWidth : 0;
7196
+
7197
+ max = borderWidth > max ? borderWidth : max;
7198
+ max = hoverWidth > max ? hoverWidth : max;
7199
+ }
7200
+ return max;
7201
+ }
7202
+ });
7203
+ };
7204
+
7205
+ },{"25":25,"40":40,"45":45}],18:[function(require,module,exports){
7206
+ 'use strict';
7207
+
7208
+ var defaults = require(25);
7209
+ var elements = require(40);
7210
+ var helpers = require(45);
7211
+
7212
+ defaults._set('line', {
7213
+ showLines: true,
7214
+ spanGaps: false,
7215
+
7216
+ hover: {
7217
+ mode: 'label'
7218
+ },
7219
+
7220
+ scales: {
7221
+ xAxes: [{
7222
+ type: 'category',
7223
+ id: 'x-axis-0'
7224
+ }],
7225
+ yAxes: [{
7226
+ type: 'linear',
7227
+ id: 'y-axis-0'
7228
+ }]
7229
+ }
7230
+ });
7231
+
7232
+ module.exports = function(Chart) {
7233
+
7234
+ function lineEnabled(dataset, options) {
7235
+ return helpers.valueOrDefault(dataset.showLine, options.showLines);
7236
+ }
7237
+
7238
+ Chart.controllers.line = Chart.DatasetController.extend({
7239
+
7240
+ datasetElementType: elements.Line,
7241
+
7242
+ dataElementType: elements.Point,
7243
+
7244
+ update: function(reset) {
7245
+ var me = this;
7246
+ var meta = me.getMeta();
7247
+ var line = meta.dataset;
7248
+ var points = meta.data || [];
7249
+ var options = me.chart.options;
7250
+ var lineElementOptions = options.elements.line;
7251
+ var scale = me.getScaleForId(meta.yAxisID);
7252
+ var i, ilen, custom;
7253
+ var dataset = me.getDataset();
7254
+ var showLine = lineEnabled(dataset, options);
7255
+
7256
+ // Update Line
7257
+ if (showLine) {
7258
+ custom = line.custom || {};
7259
+
7260
+ // Compatibility: If the properties are defined with only the old name, use those values
7261
+ if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
7262
+ dataset.lineTension = dataset.tension;
7263
+ }
7264
+
7265
+ // Utility
7266
+ line._scale = scale;
7267
+ line._datasetIndex = me.index;
7268
+ // Data
7269
+ line._children = points;
7270
+ // Model
7271
+ line._model = {
7272
+ // Appearance
7273
+ // The default behavior of lines is to break at null values, according
7274
+ // to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158
7275
+ // This option gives lines the ability to span gaps
7276
+ spanGaps: dataset.spanGaps ? dataset.spanGaps : options.spanGaps,
7277
+ tension: custom.tension ? custom.tension : helpers.valueOrDefault(dataset.lineTension, lineElementOptions.tension),
7278
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),
7279
+ borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
7280
+ borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),
7281
+ borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),
7282
+ borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
7283
+ borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),
7284
+ borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
7285
+ fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
7286
+ steppedLine: custom.steppedLine ? custom.steppedLine : helpers.valueOrDefault(dataset.steppedLine, lineElementOptions.stepped),
7287
+ cubicInterpolationMode: custom.cubicInterpolationMode ? custom.cubicInterpolationMode : helpers.valueOrDefault(dataset.cubicInterpolationMode, lineElementOptions.cubicInterpolationMode),
7288
+ };
7289
+
7290
+ line.pivot();
7291
+ }
7292
+
7293
+ // Update Points
7294
+ for (i = 0, ilen = points.length; i < ilen; ++i) {
7295
+ me.updateElement(points[i], i, reset);
7296
+ }
7297
+
7298
+ if (showLine && line._model.tension !== 0) {
7299
+ me.updateBezierControlPoints();
7300
+ }
7301
+
7302
+ // Now pivot the point for animation
7303
+ for (i = 0, ilen = points.length; i < ilen; ++i) {
7304
+ points[i].pivot();
7305
+ }
7306
+ },
7307
+
7308
+ getPointBackgroundColor: function(point, index) {
7309
+ var backgroundColor = this.chart.options.elements.point.backgroundColor;
7310
+ var dataset = this.getDataset();
7311
+ var custom = point.custom || {};
7312
+
7313
+ if (custom.backgroundColor) {
7314
+ backgroundColor = custom.backgroundColor;
7315
+ } else if (dataset.pointBackgroundColor) {
7316
+ backgroundColor = helpers.valueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor);
7317
+ } else if (dataset.backgroundColor) {
7318
+ backgroundColor = dataset.backgroundColor;
7319
+ }
7320
+
7321
+ return backgroundColor;
7322
+ },
7323
+
7324
+ getPointBorderColor: function(point, index) {
7325
+ var borderColor = this.chart.options.elements.point.borderColor;
7326
+ var dataset = this.getDataset();
7327
+ var custom = point.custom || {};
7328
+
7329
+ if (custom.borderColor) {
7330
+ borderColor = custom.borderColor;
7331
+ } else if (dataset.pointBorderColor) {
7332
+ borderColor = helpers.valueAtIndexOrDefault(dataset.pointBorderColor, index, borderColor);
7333
+ } else if (dataset.borderColor) {
7334
+ borderColor = dataset.borderColor;
7335
+ }
7336
+
7337
+ return borderColor;
7338
+ },
7339
+
7340
+ getPointBorderWidth: function(point, index) {
7341
+ var borderWidth = this.chart.options.elements.point.borderWidth;
7342
+ var dataset = this.getDataset();
7343
+ var custom = point.custom || {};
7344
+
7345
+ if (!isNaN(custom.borderWidth)) {
7346
+ borderWidth = custom.borderWidth;
7347
+ } else if (!isNaN(dataset.pointBorderWidth) || helpers.isArray(dataset.pointBorderWidth)) {
7348
+ borderWidth = helpers.valueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth);
7349
+ } else if (!isNaN(dataset.borderWidth)) {
7350
+ borderWidth = dataset.borderWidth;
7351
+ }
7352
+
7353
+ return borderWidth;
7354
+ },
7355
+
7356
+ updateElement: function(point, index, reset) {
7357
+ var me = this;
7358
+ var meta = me.getMeta();
7359
+ var custom = point.custom || {};
7360
+ var dataset = me.getDataset();
7361
+ var datasetIndex = me.index;
7362
+ var value = dataset.data[index];
7363
+ var yScale = me.getScaleForId(meta.yAxisID);
7364
+ var xScale = me.getScaleForId(meta.xAxisID);
7365
+ var pointOptions = me.chart.options.elements.point;
7366
+ var x, y;
7367
+
7368
+ // Compatibility: If the properties are defined with only the old name, use those values
7369
+ if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
7370
+ dataset.pointRadius = dataset.radius;
7371
+ }
7372
+ if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) {
7373
+ dataset.pointHitRadius = dataset.hitRadius;
7374
+ }
7375
+
7376
+ x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex);
7377
+ y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex);
7378
+
7379
+ // Utility
7380
+ point._xScale = xScale;
7381
+ point._yScale = yScale;
7382
+ point._datasetIndex = datasetIndex;
7383
+ point._index = index;
7384
+
7385
+ // Desired view properties
7386
+ point._model = {
7387
+ x: x,
7388
+ y: y,
7389
+ skip: custom.skip || isNaN(x) || isNaN(y),
7390
+ // Appearance
7391
+ radius: custom.radius || helpers.valueAtIndexOrDefault(dataset.pointRadius, index, pointOptions.radius),
7392
+ pointStyle: custom.pointStyle || helpers.valueAtIndexOrDefault(dataset.pointStyle, index, pointOptions.pointStyle),
7393
+ backgroundColor: me.getPointBackgroundColor(point, index),
7394
+ borderColor: me.getPointBorderColor(point, index),
7395
+ borderWidth: me.getPointBorderWidth(point, index),
7396
+ tension: meta.dataset._model ? meta.dataset._model.tension : 0,
7397
+ steppedLine: meta.dataset._model ? meta.dataset._model.steppedLine : false,
7398
+ // Tooltip
7399
+ hitRadius: custom.hitRadius || helpers.valueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius)
7400
+ };
7401
+ },
7402
+
7403
+ calculatePointY: function(value, index, datasetIndex) {
7404
+ var me = this;
7405
+ var chart = me.chart;
7406
+ var meta = me.getMeta();
7407
+ var yScale = me.getScaleForId(meta.yAxisID);
7408
+ var sumPos = 0;
7409
+ var sumNeg = 0;
7410
+ var i, ds, dsMeta;
7411
+
7412
+ if (yScale.options.stacked) {
7413
+ for (i = 0; i < datasetIndex; i++) {
7414
+ ds = chart.data.datasets[i];
7415
+ dsMeta = chart.getDatasetMeta(i);
7416
+ if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
7417
+ var stackedRightValue = Number(yScale.getRightValue(ds.data[index]));
7418
+ if (stackedRightValue < 0) {
7419
+ sumNeg += stackedRightValue || 0;
7420
+ } else {
7421
+ sumPos += stackedRightValue || 0;
7422
+ }
7423
+ }
7424
+ }
7425
+
7426
+ var rightValue = Number(yScale.getRightValue(value));
7427
+ if (rightValue < 0) {
7428
+ return yScale.getPixelForValue(sumNeg + rightValue);
7429
+ }
7430
+ return yScale.getPixelForValue(sumPos + rightValue);
7431
+ }
7432
+
7433
+ return yScale.getPixelForValue(value);
7434
+ },
7435
+
7436
+ updateBezierControlPoints: function() {
7437
+ var me = this;
7438
+ var meta = me.getMeta();
7439
+ var area = me.chart.chartArea;
7440
+ var points = (meta.data || []);
7441
+ var i, ilen, point, model, controlPoints;
7442
+
7443
+ // Only consider points that are drawn in case the spanGaps option is used
7444
+ if (meta.dataset._model.spanGaps) {
7445
+ points = points.filter(function(pt) {
7446
+ return !pt._model.skip;
7447
+ });
7448
+ }
7449
+
7450
+ function capControlPoint(pt, min, max) {
7451
+ return Math.max(Math.min(pt, max), min);
7452
+ }
7453
+
7454
+ if (meta.dataset._model.cubicInterpolationMode === 'monotone') {
7455
+ helpers.splineCurveMonotone(points);
7456
+ } else {
7457
+ for (i = 0, ilen = points.length; i < ilen; ++i) {
7458
+ point = points[i];
7459
+ model = point._model;
7460
+ controlPoints = helpers.splineCurve(
7461
+ helpers.previousItem(points, i)._model,
7462
+ model,
7463
+ helpers.nextItem(points, i)._model,
7464
+ meta.dataset._model.tension
7465
+ );
7466
+ model.controlPointPreviousX = controlPoints.previous.x;
7467
+ model.controlPointPreviousY = controlPoints.previous.y;
7468
+ model.controlPointNextX = controlPoints.next.x;
7469
+ model.controlPointNextY = controlPoints.next.y;
7470
+ }
7471
+ }
7472
+
7473
+ if (me.chart.options.elements.line.capBezierPoints) {
7474
+ for (i = 0, ilen = points.length; i < ilen; ++i) {
7475
+ model = points[i]._model;
7476
+ model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right);
7477
+ model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom);
7478
+ model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right);
7479
+ model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom);
7480
+ }
7481
+ }
7482
+ },
7483
+
7484
+ draw: function() {
7485
+ var me = this;
7486
+ var chart = me.chart;
7487
+ var meta = me.getMeta();
7488
+ var points = meta.data || [];
7489
+ var area = chart.chartArea;
7490
+ var ilen = points.length;
7491
+ var i = 0;
7492
+
7493
+ helpers.canvas.clipArea(chart.ctx, area);
7494
+
7495
+ if (lineEnabled(me.getDataset(), chart.options)) {
7496
+ meta.dataset.draw();
7497
+ }
7498
+
7499
+ helpers.canvas.unclipArea(chart.ctx);
7500
+
7501
+ // Draw the points
7502
+ for (; i < ilen; ++i) {
7503
+ points[i].draw(area);
7504
+ }
7505
+ },
7506
+
7507
+ setHoverStyle: function(point) {
7508
+ // Point
7509
+ var dataset = this.chart.data.datasets[point._datasetIndex];
7510
+ var index = point._index;
7511
+ var custom = point.custom || {};
7512
+ var model = point._model;
7513
+
7514
+ model.radius = custom.hoverRadius || helpers.valueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
7515
+ model.backgroundColor = custom.hoverBackgroundColor || helpers.valueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
7516
+ model.borderColor = custom.hoverBorderColor || helpers.valueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));
7517
+ model.borderWidth = custom.hoverBorderWidth || helpers.valueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);
7518
+ },
7519
+
7520
+ removeHoverStyle: function(point) {
7521
+ var me = this;
7522
+ var dataset = me.chart.data.datasets[point._datasetIndex];
7523
+ var index = point._index;
7524
+ var custom = point.custom || {};
7525
+ var model = point._model;
7526
+
7527
+ // Compatibility: If the properties are defined with only the old name, use those values
7528
+ if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
7529
+ dataset.pointRadius = dataset.radius;
7530
+ }
7531
+
7532
+ model.radius = custom.radius || helpers.valueAtIndexOrDefault(dataset.pointRadius, index, me.chart.options.elements.point.radius);
7533
+ model.backgroundColor = me.getPointBackgroundColor(point, index);
7534
+ model.borderColor = me.getPointBorderColor(point, index);
7535
+ model.borderWidth = me.getPointBorderWidth(point, index);
7536
+ }
7537
+ });
7538
+ };
7539
+
7540
+ },{"25":25,"40":40,"45":45}],19:[function(require,module,exports){
7541
+ 'use strict';
7542
+
7543
+ var defaults = require(25);
7544
+ var elements = require(40);
7545
+ var helpers = require(45);
7546
+
7547
+ defaults._set('polarArea', {
7548
+ scale: {
7549
+ type: 'radialLinear',
7550
+ angleLines: {
7551
+ display: false
7552
+ },
7553
+ gridLines: {
7554
+ circular: true
7555
+ },
7556
+ pointLabels: {
7557
+ display: false
7558
+ },
7559
+ ticks: {
7560
+ beginAtZero: true
7561
+ }
7562
+ },
7563
+
7564
+ // Boolean - Whether to animate the rotation of the chart
7565
+ animation: {
7566
+ animateRotate: true,
7567
+ animateScale: true
7568
+ },
7569
+
7570
+ startAngle: -0.5 * Math.PI,
7571
+ legendCallback: function(chart) {
7572
+ var text = [];
7573
+ text.push('<ul class="' + chart.id + '-legend">');
7574
+
7575
+ var data = chart.data;
7576
+ var datasets = data.datasets;
7577
+ var labels = data.labels;
7578
+
7579
+ if (datasets.length) {
7580
+ for (var i = 0; i < datasets[0].data.length; ++i) {
7581
+ text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
7582
+ if (labels[i]) {
7583
+ text.push(labels[i]);
7584
+ }
7585
+ text.push('</li>');
7586
+ }
7587
+ }
7588
+
7589
+ text.push('</ul>');
7590
+ return text.join('');
7591
+ },
7592
+ legend: {
7593
+ labels: {
7594
+ generateLabels: function(chart) {
7595
+ var data = chart.data;
7596
+ if (data.labels.length && data.datasets.length) {
7597
+ return data.labels.map(function(label, i) {
7598
+ var meta = chart.getDatasetMeta(0);
7599
+ var ds = data.datasets[0];
7600
+ var arc = meta.data[i];
7601
+ var custom = arc.custom || {};
7602
+ var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
7603
+ var arcOpts = chart.options.elements.arc;
7604
+ var fill = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
7605
+ var stroke = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
7606
+ var bw = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
7607
+
7608
+ return {
7609
+ text: label,
7610
+ fillStyle: fill,
7611
+ strokeStyle: stroke,
7612
+ lineWidth: bw,
7613
+ hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
7614
+
7615
+ // Extra data used for toggling the correct item
7616
+ index: i
7617
+ };
7618
+ });
7619
+ }
7620
+ return [];
7621
+ }
7622
+ },
7623
+
7624
+ onClick: function(e, legendItem) {
7625
+ var index = legendItem.index;
7626
+ var chart = this.chart;
7627
+ var i, ilen, meta;
7628
+
7629
+ for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
7630
+ meta = chart.getDatasetMeta(i);
7631
+ meta.data[index].hidden = !meta.data[index].hidden;
7632
+ }
7633
+
7634
+ chart.update();
7635
+ }
7636
+ },
7637
+
7638
+ // Need to override these to give a nice default
7639
+ tooltips: {
7640
+ callbacks: {
7641
+ title: function() {
7642
+ return '';
7643
+ },
7644
+ label: function(item, data) {
7645
+ return data.labels[item.index] + ': ' + item.yLabel;
7646
+ }
7647
+ }
7648
+ }
7649
+ });
7650
+
7651
+ module.exports = function(Chart) {
7652
+
7653
+ Chart.controllers.polarArea = Chart.DatasetController.extend({
7654
+
7655
+ dataElementType: elements.Arc,
7656
+
7657
+ linkScales: helpers.noop,
7658
+
7659
+ update: function(reset) {
7660
+ var me = this;
7661
+ var chart = me.chart;
7662
+ var chartArea = chart.chartArea;
7663
+ var meta = me.getMeta();
7664
+ var opts = chart.options;
7665
+ var arcOpts = opts.elements.arc;
7666
+ var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
7667
+ chart.outerRadius = Math.max((minSize - arcOpts.borderWidth / 2) / 2, 0);
7668
+ chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);
7669
+ chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
7670
+
7671
+ me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index);
7672
+ me.innerRadius = me.outerRadius - chart.radiusLength;
7673
+
7674
+ meta.count = me.countVisibleElements();
7675
+
7676
+ helpers.each(meta.data, function(arc, index) {
7677
+ me.updateElement(arc, index, reset);
7678
+ });
7679
+ },
7680
+
7681
+ updateElement: function(arc, index, reset) {
7682
+ var me = this;
7683
+ var chart = me.chart;
7684
+ var dataset = me.getDataset();
7685
+ var opts = chart.options;
7686
+ var animationOpts = opts.animation;
7687
+ var scale = chart.scale;
7688
+ var labels = chart.data.labels;
7689
+
7690
+ var circumference = me.calculateCircumference(dataset.data[index]);
7691
+ var centerX = scale.xCenter;
7692
+ var centerY = scale.yCenter;
7693
+
7694
+ // If there is NaN data before us, we need to calculate the starting angle correctly.
7695
+ // We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data
7696
+ var visibleCount = 0;
7697
+ var meta = me.getMeta();
7698
+ for (var i = 0; i < index; ++i) {
7699
+ if (!isNaN(dataset.data[i]) && !meta.data[i].hidden) {
7700
+ ++visibleCount;
7701
+ }
7702
+ }
7703
+
7704
+ // var negHalfPI = -0.5 * Math.PI;
7705
+ var datasetStartAngle = opts.startAngle;
7706
+ var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
7707
+ var startAngle = datasetStartAngle + (circumference * visibleCount);
7708
+ var endAngle = startAngle + (arc.hidden ? 0 : circumference);
7709
+
7710
+ var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
7711
+
7712
+ helpers.extend(arc, {
7713
+ // Utility
7714
+ _datasetIndex: me.index,
7715
+ _index: index,
7716
+ _scale: scale,
7717
+
7718
+ // Desired view properties
7719
+ _model: {
7720
+ x: centerX,
7721
+ y: centerY,
7722
+ innerRadius: 0,
7723
+ outerRadius: reset ? resetRadius : distance,
7724
+ startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle,
7725
+ endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle,
7726
+ label: helpers.valueAtIndexOrDefault(labels, index, labels[index])
7727
+ }
7728
+ });
7729
+
7730
+ // Apply border and fill style
7731
+ me.removeHoverStyle(arc);
7732
+
7733
+ arc.pivot();
7734
+ },
7735
+
7736
+ removeHoverStyle: function(arc) {
7737
+ Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);
7738
+ },
7739
+
7740
+ countVisibleElements: function() {
7741
+ var dataset = this.getDataset();
7742
+ var meta = this.getMeta();
7743
+ var count = 0;
7744
+
7745
+ helpers.each(meta.data, function(element, index) {
7746
+ if (!isNaN(dataset.data[index]) && !element.hidden) {
7747
+ count++;
7748
+ }
7749
+ });
7750
+
7751
+ return count;
7752
+ },
7753
+
7754
+ calculateCircumference: function(value) {
7755
+ var count = this.getMeta().count;
7756
+ if (count > 0 && !isNaN(value)) {
7757
+ return (2 * Math.PI) / count;
7758
+ }
7759
+ return 0;
7760
+ }
7761
+ });
7762
+ };
7763
+
7764
+ },{"25":25,"40":40,"45":45}],20:[function(require,module,exports){
7765
+ 'use strict';
7766
+
7767
+ var defaults = require(25);
7768
+ var elements = require(40);
7769
+ var helpers = require(45);
7770
+
7771
+ defaults._set('radar', {
7772
+ scale: {
7773
+ type: 'radialLinear'
7774
+ },
7775
+ elements: {
7776
+ line: {
7777
+ tension: 0 // no bezier in radar
7778
+ }
7779
+ }
7780
+ });
7781
+
7782
+ module.exports = function(Chart) {
7783
+
7784
+ Chart.controllers.radar = Chart.DatasetController.extend({
7785
+
7786
+ datasetElementType: elements.Line,
7787
+
7788
+ dataElementType: elements.Point,
7789
+
7790
+ linkScales: helpers.noop,
7791
+
7792
+ update: function(reset) {
7793
+ var me = this;
7794
+ var meta = me.getMeta();
7795
+ var line = meta.dataset;
7796
+ var points = meta.data;
7797
+ var custom = line.custom || {};
7798
+ var dataset = me.getDataset();
7799
+ var lineElementOptions = me.chart.options.elements.line;
7800
+ var scale = me.chart.scale;
7801
+
7802
+ // Compatibility: If the properties are defined with only the old name, use those values
7803
+ if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
7804
+ dataset.lineTension = dataset.tension;
7805
+ }
7806
+
7807
+ helpers.extend(meta.dataset, {
7808
+ // Utility
7809
+ _datasetIndex: me.index,
7810
+ _scale: scale,
7811
+ // Data
7812
+ _children: points,
7813
+ _loop: true,
7814
+ // Model
7815
+ _model: {
7816
+ // Appearance
7817
+ tension: custom.tension ? custom.tension : helpers.valueOrDefault(dataset.lineTension, lineElementOptions.tension),
7818
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),
7819
+ borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
7820
+ borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),
7821
+ fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
7822
+ borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),
7823
+ borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
7824
+ borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),
7825
+ borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
7826
+ }
7827
+ });
7828
+
7829
+ meta.dataset.pivot();
7830
+
7831
+ // Update Points
7832
+ helpers.each(points, function(point, index) {
7833
+ me.updateElement(point, index, reset);
7834
+ }, me);
7835
+
7836
+ // Update bezier control points
7837
+ me.updateBezierControlPoints();
7838
+ },
7839
+ updateElement: function(point, index, reset) {
7840
+ var me = this;
7841
+ var custom = point.custom || {};
7842
+ var dataset = me.getDataset();
7843
+ var scale = me.chart.scale;
7844
+ var pointElementOptions = me.chart.options.elements.point;
7845
+ var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);
7846
+
7847
+ // Compatibility: If the properties are defined with only the old name, use those values
7848
+ if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
7849
+ dataset.pointRadius = dataset.radius;
7850
+ }
7851
+ if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) {
7852
+ dataset.pointHitRadius = dataset.hitRadius;
7853
+ }
7854
+
7855
+ helpers.extend(point, {
7856
+ // Utility
7857
+ _datasetIndex: me.index,
7858
+ _index: index,
7859
+ _scale: scale,
7860
+
7861
+ // Desired view properties
7862
+ _model: {
7863
+ x: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales
7864
+ y: reset ? scale.yCenter : pointPosition.y,
7865
+
7866
+ // Appearance
7867
+ tension: custom.tension ? custom.tension : helpers.valueOrDefault(dataset.lineTension, me.chart.options.elements.line.tension),
7868
+ radius: custom.radius ? custom.radius : helpers.valueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius),
7869
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor),
7870
+ borderColor: custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor),
7871
+ borderWidth: custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth),
7872
+ pointStyle: custom.pointStyle ? custom.pointStyle : helpers.valueAtIndexOrDefault(dataset.pointStyle, index, pointElementOptions.pointStyle),
7873
+
7874
+ // Tooltip
7875
+ hitRadius: custom.hitRadius ? custom.hitRadius : helpers.valueAtIndexOrDefault(dataset.pointHitRadius, index, pointElementOptions.hitRadius)
7876
+ }
7877
+ });
7878
+
7879
+ point._model.skip = custom.skip ? custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
7880
+ },
7881
+ updateBezierControlPoints: function() {
7882
+ var chartArea = this.chart.chartArea;
7883
+ var meta = this.getMeta();
7884
+
7885
+ helpers.each(meta.data, function(point, index) {
7886
+ var model = point._model;
7887
+ var controlPoints = helpers.splineCurve(
7888
+ helpers.previousItem(meta.data, index, true)._model,
7889
+ model,
7890
+ helpers.nextItem(meta.data, index, true)._model,
7891
+ model.tension
7892
+ );
7893
+
7894
+ // Prevent the bezier going outside of the bounds of the graph
7895
+ model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left);
7896
+ model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top);
7897
+
7898
+ model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left);
7899
+ model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top);
7900
+
7901
+ // Now pivot the point for animation
7902
+ point.pivot();
7903
+ });
7904
+ },
7905
+
7906
+ setHoverStyle: function(point) {
7907
+ // Point
7908
+ var dataset = this.chart.data.datasets[point._datasetIndex];
7909
+ var custom = point.custom || {};
7910
+ var index = point._index;
7911
+ var model = point._model;
7912
+
7913
+ model.radius = custom.hoverRadius ? custom.hoverRadius : helpers.valueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
7914
+ model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.valueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
7915
+ model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.valueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));
7916
+ model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.valueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);
7917
+ },
7918
+
7919
+ removeHoverStyle: function(point) {
7920
+ var dataset = this.chart.data.datasets[point._datasetIndex];
7921
+ var custom = point.custom || {};
7922
+ var index = point._index;
7923
+ var model = point._model;
7924
+ var pointElementOptions = this.chart.options.elements.point;
7925
+
7926
+ model.radius = custom.radius ? custom.radius : helpers.valueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius);
7927
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor);
7928
+ model.borderColor = custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor);
7929
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth);
7930
+ }
7931
+ });
7932
+ };
7933
+
7934
+ },{"25":25,"40":40,"45":45}],21:[function(require,module,exports){
7935
+ 'use strict';
7936
+
7937
+ var defaults = require(25);
7938
+
7939
+ defaults._set('scatter', {
7940
+ hover: {
7941
+ mode: 'single'
7942
+ },
7943
+
7944
+ scales: {
7945
+ xAxes: [{
7946
+ id: 'x-axis-1', // need an ID so datasets can reference the scale
7947
+ type: 'linear', // scatter should not use a category axis
7948
+ position: 'bottom'
7949
+ }],
7950
+ yAxes: [{
7951
+ id: 'y-axis-1',
7952
+ type: 'linear',
7953
+ position: 'left'
7954
+ }]
7955
+ },
7956
+
7957
+ showLines: false,
7958
+
7959
+ tooltips: {
7960
+ callbacks: {
7961
+ title: function() {
7962
+ return ''; // doesn't make sense for scatter since data are formatted as a point
7963
+ },
7964
+ label: function(item) {
7965
+ return '(' + item.xLabel + ', ' + item.yLabel + ')';
7966
+ }
7967
+ }
7968
+ }
7969
+ });
7970
+
7971
+ module.exports = function(Chart) {
7972
+
7973
+ // Scatter charts use line controllers
7974
+ Chart.controllers.scatter = Chart.controllers.line;
7975
+
7976
+ };
7977
+
7978
+ },{"25":25}],22:[function(require,module,exports){
7979
+ /* global window: false */
7980
+ 'use strict';
7981
+
7982
+ var defaults = require(25);
7983
+ var Element = require(26);
7984
+ var helpers = require(45);
7985
+
7986
+ defaults._set('global', {
7987
+ animation: {
7988
+ duration: 1000,
7989
+ easing: 'easeOutQuart',
7990
+ onProgress: helpers.noop,
7991
+ onComplete: helpers.noop
7992
+ }
7993
+ });
7994
+
7995
+ module.exports = function(Chart) {
7996
+
7997
+ Chart.Animation = Element.extend({
7998
+ chart: null, // the animation associated chart instance
7999
+ currentStep: 0, // the current animation step
8000
+ numSteps: 60, // default number of steps
8001
+ easing: '', // the easing to use for this animation
8002
+ render: null, // render function used by the animation service
8003
+
8004
+ onAnimationProgress: null, // user specified callback to fire on each step of the animation
8005
+ onAnimationComplete: null, // user specified callback to fire when the animation finishes
8006
+ });
8007
+
8008
+ Chart.animationService = {
8009
+ frameDuration: 17,
8010
+ animations: [],
8011
+ dropFrames: 0,
8012
+ request: null,
8013
+
8014
+ /**
8015
+ * @param {Chart} chart - The chart to animate.
8016
+ * @param {Chart.Animation} animation - The animation that we will animate.
8017
+ * @param {Number} duration - The animation duration in ms.
8018
+ * @param {Boolean} lazy - if true, the chart is not marked as animating to enable more responsive interactions
8019
+ */
8020
+ addAnimation: function(chart, animation, duration, lazy) {
8021
+ var animations = this.animations;
8022
+ var i, ilen;
8023
+
8024
+ animation.chart = chart;
8025
+
8026
+ if (!lazy) {
8027
+ chart.animating = true;
8028
+ }
8029
+
8030
+ for (i = 0, ilen = animations.length; i < ilen; ++i) {
8031
+ if (animations[i].chart === chart) {
8032
+ animations[i] = animation;
8033
+ return;
8034
+ }
8035
+ }
8036
+
8037
+ animations.push(animation);
8038
+
8039
+ // If there are no animations queued, manually kickstart a digest, for lack of a better word
8040
+ if (animations.length === 1) {
8041
+ this.requestAnimationFrame();
8042
+ }
8043
+ },
8044
+
8045
+ cancelAnimation: function(chart) {
8046
+ var index = helpers.findIndex(this.animations, function(animation) {
8047
+ return animation.chart === chart;
8048
+ });
8049
+
8050
+ if (index !== -1) {
8051
+ this.animations.splice(index, 1);
8052
+ chart.animating = false;
8053
+ }
8054
+ },
8055
+
8056
+ requestAnimationFrame: function() {
8057
+ var me = this;
8058
+ if (me.request === null) {
8059
+ // Skip animation frame requests until the active one is executed.
8060
+ // This can happen when processing mouse events, e.g. 'mousemove'
8061
+ // and 'mouseout' events will trigger multiple renders.
8062
+ me.request = helpers.requestAnimFrame.call(window, function() {
8063
+ me.request = null;
8064
+ me.startDigest();
8065
+ });
8066
+ }
8067
+ },
8068
+
8069
+ /**
8070
+ * @private
8071
+ */
8072
+ startDigest: function() {
8073
+ var me = this;
8074
+ var startTime = Date.now();
8075
+ var framesToDrop = 0;
8076
+
8077
+ if (me.dropFrames > 1) {
8078
+ framesToDrop = Math.floor(me.dropFrames);
8079
+ me.dropFrames = me.dropFrames % 1;
8080
+ }
8081
+
8082
+ me.advance(1 + framesToDrop);
8083
+
8084
+ var endTime = Date.now();
8085
+
8086
+ me.dropFrames += (endTime - startTime) / me.frameDuration;
8087
+
8088
+ // Do we have more stuff to animate?
8089
+ if (me.animations.length > 0) {
8090
+ me.requestAnimationFrame();
8091
+ }
8092
+ },
8093
+
8094
+ /**
8095
+ * @private
8096
+ */
8097
+ advance: function(count) {
8098
+ var animations = this.animations;
8099
+ var animation, chart;
8100
+ var i = 0;
8101
+
8102
+ while (i < animations.length) {
8103
+ animation = animations[i];
8104
+ chart = animation.chart;
8105
+
8106
+ animation.currentStep = (animation.currentStep || 0) + count;
8107
+ animation.currentStep = Math.min(animation.currentStep, animation.numSteps);
8108
+
8109
+ helpers.callback(animation.render, [chart, animation], chart);
8110
+ helpers.callback(animation.onAnimationProgress, [animation], chart);
8111
+
8112
+ if (animation.currentStep >= animation.numSteps) {
8113
+ helpers.callback(animation.onAnimationComplete, [animation], chart);
8114
+ chart.animating = false;
8115
+ animations.splice(i, 1);
8116
+ } else {
8117
+ ++i;
8118
+ }
8119
+ }
8120
+ }
8121
+ };
8122
+
8123
+ /**
8124
+ * Provided for backward compatibility, use Chart.Animation instead
8125
+ * @prop Chart.Animation#animationObject
8126
+ * @deprecated since version 2.6.0
8127
+ * @todo remove at version 3
8128
+ */
8129
+ Object.defineProperty(Chart.Animation.prototype, 'animationObject', {
8130
+ get: function() {
8131
+ return this;
8132
+ }
8133
+ });
8134
+
8135
+ /**
8136
+ * Provided for backward compatibility, use Chart.Animation#chart instead
8137
+ * @prop Chart.Animation#chartInstance
8138
+ * @deprecated since version 2.6.0
8139
+ * @todo remove at version 3
8140
+ */
8141
+ Object.defineProperty(Chart.Animation.prototype, 'chartInstance', {
8142
+ get: function() {
8143
+ return this.chart;
8144
+ },
8145
+ set: function(value) {
8146
+ this.chart = value;
8147
+ }
8148
+ });
8149
+
8150
+ };
8151
+
8152
+ },{"25":25,"26":26,"45":45}],23:[function(require,module,exports){
8153
+ 'use strict';
8154
+
8155
+ var defaults = require(25);
8156
+ var helpers = require(45);
8157
+ var Interaction = require(28);
8158
+ var platform = require(48);
8159
+
8160
+ module.exports = function(Chart) {
8161
+ var plugins = Chart.plugins;
8162
+
8163
+ // Create a dictionary of chart types, to allow for extension of existing types
8164
+ Chart.types = {};
8165
+
8166
+ // Store a reference to each instance - allowing us to globally resize chart instances on window resize.
8167
+ // Destroy method on the chart will remove the instance of the chart from this reference.
8168
+ Chart.instances = {};
8169
+
8170
+ // Controllers available for dataset visualization eg. bar, line, slice, etc.
8171
+ Chart.controllers = {};
8172
+
8173
+ /**
8174
+ * Initializes the given config with global and chart default values.
8175
+ */
8176
+ function initConfig(config) {
8177
+ config = config || {};
8178
+
8179
+ // Do NOT use configMerge() for the data object because this method merges arrays
8180
+ // and so would change references to labels and datasets, preventing data updates.
8181
+ var data = config.data = config.data || {};
8182
+ data.datasets = data.datasets || [];
8183
+ data.labels = data.labels || [];
8184
+
8185
+ config.options = helpers.configMerge(
8186
+ defaults.global,
8187
+ defaults[config.type],
8188
+ config.options || {});
8189
+
8190
+ return config;
8191
+ }
8192
+
8193
+ /**
8194
+ * Updates the config of the chart
8195
+ * @param chart {Chart} chart to update the options for
8196
+ */
8197
+ function updateConfig(chart) {
8198
+ var newOptions = chart.options;
8199
+
8200
+ // Update Scale(s) with options
8201
+ if (newOptions.scale) {
8202
+ chart.scale.options = newOptions.scale;
8203
+ } else if (newOptions.scales) {
8204
+ newOptions.scales.xAxes.concat(newOptions.scales.yAxes).forEach(function(scaleOptions) {
8205
+ chart.scales[scaleOptions.id].options = scaleOptions;
8206
+ });
8207
+ }
8208
+
8209
+ // Tooltip
8210
+ chart.tooltip._options = newOptions.tooltips;
8211
+ }
8212
+
8213
+ function positionIsHorizontal(position) {
8214
+ return position === 'top' || position === 'bottom';
8215
+ }
8216
+
8217
+ helpers.extend(Chart.prototype, /** @lends Chart */ {
8218
+ /**
8219
+ * @private
8220
+ */
8221
+ construct: function(item, config) {
8222
+ var me = this;
8223
+
8224
+ config = initConfig(config);
8225
+
8226
+ var context = platform.acquireContext(item, config);
8227
+ var canvas = context && context.canvas;
8228
+ var height = canvas && canvas.height;
8229
+ var width = canvas && canvas.width;
8230
+
8231
+ me.id = helpers.uid();
8232
+ me.ctx = context;
8233
+ me.canvas = canvas;
8234
+ me.config = config;
8235
+ me.width = width;
8236
+ me.height = height;
8237
+ me.aspectRatio = height ? width / height : null;
8238
+ me.options = config.options;
8239
+ me._bufferedRender = false;
8240
+
8241
+ /**
8242
+ * Provided for backward compatibility, Chart and Chart.Controller have been merged,
8243
+ * the "instance" still need to be defined since it might be called from plugins.
8244
+ * @prop Chart#chart
8245
+ * @deprecated since version 2.6.0
8246
+ * @todo remove at version 3
8247
+ * @private
8248
+ */
8249
+ me.chart = me;
8250
+ me.controller = me; // chart.chart.controller #inception
8251
+
8252
+ // Add the chart instance to the global namespace
8253
+ Chart.instances[me.id] = me;
8254
+
8255
+ // Define alias to the config data: `chart.data === chart.config.data`
8256
+ Object.defineProperty(me, 'data', {
8257
+ get: function() {
8258
+ return me.config.data;
8259
+ },
8260
+ set: function(value) {
8261
+ me.config.data = value;
8262
+ }
8263
+ });
8264
+
8265
+ if (!context || !canvas) {
8266
+ // The given item is not a compatible context2d element, let's return before finalizing
8267
+ // the chart initialization but after setting basic chart / controller properties that
8268
+ // can help to figure out that the chart is not valid (e.g chart.canvas !== null);
8269
+ // https://github.com/chartjs/Chart.js/issues/2807
8270
+ console.error("Failed to create chart: can't acquire context from the given item");
8271
+ return;
8272
+ }
8273
+
8274
+ me.initialize();
8275
+ me.update();
8276
+ },
8277
+
8278
+ /**
8279
+ * @private
8280
+ */
8281
+ initialize: function() {
8282
+ var me = this;
8283
+
8284
+ // Before init plugin notification
8285
+ plugins.notify(me, 'beforeInit');
8286
+
8287
+ helpers.retinaScale(me, me.options.devicePixelRatio);
8288
+
8289
+ me.bindEvents();
8290
+
8291
+ if (me.options.responsive) {
8292
+ // Initial resize before chart draws (must be silent to preserve initial animations).
8293
+ me.resize(true);
8294
+ }
8295
+
8296
+ // Make sure scales have IDs and are built before we build any controllers.
8297
+ me.ensureScalesHaveIDs();
8298
+ me.buildScales();
8299
+ me.initToolTip();
8300
+
8301
+ // After init plugin notification
8302
+ plugins.notify(me, 'afterInit');
8303
+
8304
+ return me;
8305
+ },
8306
+
8307
+ clear: function() {
8308
+ helpers.canvas.clear(this);
8309
+ return this;
8310
+ },
8311
+
8312
+ stop: function() {
8313
+ // Stops any current animation loop occurring
8314
+ Chart.animationService.cancelAnimation(this);
8315
+ return this;
8316
+ },
8317
+
8318
+ resize: function(silent) {
8319
+ var me = this;
8320
+ var options = me.options;
8321
+ var canvas = me.canvas;
8322
+ var aspectRatio = (options.maintainAspectRatio && me.aspectRatio) || null;
8323
+
8324
+ // the canvas render width and height will be casted to integers so make sure that
8325
+ // the canvas display style uses the same integer values to avoid blurring effect.
8326
+
8327
+ // Set to 0 instead of canvas.size because the size defaults to 300x150 if the element is collased
8328
+ var newWidth = Math.max(0, Math.floor(helpers.getMaximumWidth(canvas)));
8329
+ var newHeight = Math.max(0, Math.floor(aspectRatio ? newWidth / aspectRatio : helpers.getMaximumHeight(canvas)));
8330
+
8331
+ if (me.width === newWidth && me.height === newHeight) {
8332
+ return;
8333
+ }
8334
+
8335
+ canvas.width = me.width = newWidth;
8336
+ canvas.height = me.height = newHeight;
8337
+ canvas.style.width = newWidth + 'px';
8338
+ canvas.style.height = newHeight + 'px';
8339
+
8340
+ helpers.retinaScale(me, options.devicePixelRatio);
8341
+
8342
+ if (!silent) {
8343
+ // Notify any plugins about the resize
8344
+ var newSize = {width: newWidth, height: newHeight};
8345
+ plugins.notify(me, 'resize', [newSize]);
8346
+
8347
+ // Notify of resize
8348
+ if (me.options.onResize) {
8349
+ me.options.onResize(me, newSize);
8350
+ }
8351
+
8352
+ me.stop();
8353
+ me.update(me.options.responsiveAnimationDuration);
8354
+ }
8355
+ },
8356
+
8357
+ ensureScalesHaveIDs: function() {
8358
+ var options = this.options;
8359
+ var scalesOptions = options.scales || {};
8360
+ var scaleOptions = options.scale;
8361
+
8362
+ helpers.each(scalesOptions.xAxes, function(xAxisOptions, index) {
8363
+ xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index);
8364
+ });
8365
+
8366
+ helpers.each(scalesOptions.yAxes, function(yAxisOptions, index) {
8367
+ yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index);
8368
+ });
8369
+
8370
+ if (scaleOptions) {
8371
+ scaleOptions.id = scaleOptions.id || 'scale';
8372
+ }
8373
+ },
8374
+
8375
+ /**
8376
+ * Builds a map of scale ID to scale object for future lookup.
8377
+ */
8378
+ buildScales: function() {
8379
+ var me = this;
8380
+ var options = me.options;
8381
+ var scales = me.scales = {};
8382
+ var items = [];
8383
+
8384
+ if (options.scales) {
8385
+ items = items.concat(
8386
+ (options.scales.xAxes || []).map(function(xAxisOptions) {
8387
+ return {options: xAxisOptions, dtype: 'category', dposition: 'bottom'};
8388
+ }),
8389
+ (options.scales.yAxes || []).map(function(yAxisOptions) {
8390
+ return {options: yAxisOptions, dtype: 'linear', dposition: 'left'};
8391
+ })
8392
+ );
8393
+ }
8394
+
8395
+ if (options.scale) {
8396
+ items.push({
8397
+ options: options.scale,
8398
+ dtype: 'radialLinear',
8399
+ isDefault: true,
8400
+ dposition: 'chartArea'
8401
+ });
8402
+ }
8403
+
8404
+ helpers.each(items, function(item) {
8405
+ var scaleOptions = item.options;
8406
+ var scaleType = helpers.valueOrDefault(scaleOptions.type, item.dtype);
8407
+ var scaleClass = Chart.scaleService.getScaleConstructor(scaleType);
8408
+ if (!scaleClass) {
8409
+ return;
8410
+ }
8411
+
8412
+ if (positionIsHorizontal(scaleOptions.position) !== positionIsHorizontal(item.dposition)) {
8413
+ scaleOptions.position = item.dposition;
8414
+ }
8415
+
8416
+ var scale = new scaleClass({
8417
+ id: scaleOptions.id,
8418
+ options: scaleOptions,
8419
+ ctx: me.ctx,
8420
+ chart: me
8421
+ });
8422
+
8423
+ scales[scale.id] = scale;
8424
+ scale.mergeTicksOptions();
8425
+
8426
+ // TODO(SB): I think we should be able to remove this custom case (options.scale)
8427
+ // and consider it as a regular scale part of the "scales"" map only! This would
8428
+ // make the logic easier and remove some useless? custom code.
8429
+ if (item.isDefault) {
8430
+ me.scale = scale;
8431
+ }
8432
+ });
8433
+
8434
+ Chart.scaleService.addScalesToLayout(this);
8435
+ },
8436
+
8437
+ buildOrUpdateControllers: function() {
8438
+ var me = this;
8439
+ var types = [];
8440
+ var newControllers = [];
8441
+
8442
+ helpers.each(me.data.datasets, function(dataset, datasetIndex) {
8443
+ var meta = me.getDatasetMeta(datasetIndex);
8444
+ var type = dataset.type || me.config.type;
8445
+
8446
+ if (meta.type && meta.type !== type) {
8447
+ me.destroyDatasetMeta(datasetIndex);
8448
+ meta = me.getDatasetMeta(datasetIndex);
8449
+ }
8450
+ meta.type = type;
8451
+
8452
+ types.push(meta.type);
8453
+
8454
+ if (meta.controller) {
8455
+ meta.controller.updateIndex(datasetIndex);
8456
+ } else {
8457
+ var ControllerClass = Chart.controllers[meta.type];
8458
+ if (ControllerClass === undefined) {
8459
+ throw new Error('"' + meta.type + '" is not a chart type.');
8460
+ }
8461
+
8462
+ meta.controller = new ControllerClass(me, datasetIndex);
8463
+ newControllers.push(meta.controller);
8464
+ }
8465
+ }, me);
8466
+
8467
+ return newControllers;
8468
+ },
8469
+
8470
+ /**
8471
+ * Reset the elements of all datasets
8472
+ * @private
8473
+ */
8474
+ resetElements: function() {
8475
+ var me = this;
8476
+ helpers.each(me.data.datasets, function(dataset, datasetIndex) {
8477
+ me.getDatasetMeta(datasetIndex).controller.reset();
8478
+ }, me);
8479
+ },
8480
+
8481
+ /**
8482
+ * Resets the chart back to it's state before the initial animation
8483
+ */
8484
+ reset: function() {
8485
+ this.resetElements();
8486
+ this.tooltip.initialize();
8487
+ },
8488
+
8489
+ update: function(config) {
8490
+ var me = this;
8491
+
8492
+ if (!config || typeof config !== 'object') {
8493
+ // backwards compatibility
8494
+ config = {
8495
+ duration: config,
8496
+ lazy: arguments[1]
8497
+ };
8498
+ }
8499
+
8500
+ updateConfig(me);
8501
+
8502
+ if (plugins.notify(me, 'beforeUpdate') === false) {
8503
+ return;
8504
+ }
8505
+
8506
+ // In case the entire data object changed
8507
+ me.tooltip._data = me.data;
8508
+
8509
+ // Make sure dataset controllers are updated and new controllers are reset
8510
+ var newControllers = me.buildOrUpdateControllers();
8511
+
8512
+ // Make sure all dataset controllers have correct meta data counts
8513
+ helpers.each(me.data.datasets, function(dataset, datasetIndex) {
8514
+ me.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements();
8515
+ }, me);
8516
+
8517
+ me.updateLayout();
8518
+
8519
+ // Can only reset the new controllers after the scales have been updated
8520
+ helpers.each(newControllers, function(controller) {
8521
+ controller.reset();
8522
+ });
8523
+
8524
+ me.updateDatasets();
8525
+
8526
+ // Do this before render so that any plugins that need final scale updates can use it
8527
+ plugins.notify(me, 'afterUpdate');
8528
+
8529
+ if (me._bufferedRender) {
8530
+ me._bufferedRequest = {
8531
+ duration: config.duration,
8532
+ easing: config.easing,
8533
+ lazy: config.lazy
8534
+ };
8535
+ } else {
8536
+ me.render(config);
8537
+ }
8538
+ },
8539
+
8540
+ /**
8541
+ * Updates the chart layout unless a plugin returns `false` to the `beforeLayout`
8542
+ * hook, in which case, plugins will not be called on `afterLayout`.
8543
+ * @private
8544
+ */
8545
+ updateLayout: function() {
8546
+ var me = this;
8547
+
8548
+ if (plugins.notify(me, 'beforeLayout') === false) {
8549
+ return;
8550
+ }
8551
+
8552
+ Chart.layoutService.update(this, this.width, this.height);
8553
+
8554
+ /**
8555
+ * Provided for backward compatibility, use `afterLayout` instead.
8556
+ * @method IPlugin#afterScaleUpdate
8557
+ * @deprecated since version 2.5.0
8558
+ * @todo remove at version 3
8559
+ * @private
8560
+ */
8561
+ plugins.notify(me, 'afterScaleUpdate');
8562
+ plugins.notify(me, 'afterLayout');
8563
+ },
8564
+
8565
+ /**
8566
+ * Updates all datasets unless a plugin returns `false` to the `beforeDatasetsUpdate`
8567
+ * hook, in which case, plugins will not be called on `afterDatasetsUpdate`.
8568
+ * @private
8569
+ */
8570
+ updateDatasets: function() {
8571
+ var me = this;
8572
+
8573
+ if (plugins.notify(me, 'beforeDatasetsUpdate') === false) {
8574
+ return;
8575
+ }
8576
+
8577
+ for (var i = 0, ilen = me.data.datasets.length; i < ilen; ++i) {
8578
+ me.updateDataset(i);
8579
+ }
8580
+
8581
+ plugins.notify(me, 'afterDatasetsUpdate');
8582
+ },
8583
+
8584
+ /**
8585
+ * Updates dataset at index unless a plugin returns `false` to the `beforeDatasetUpdate`
8586
+ * hook, in which case, plugins will not be called on `afterDatasetUpdate`.
8587
+ * @private
8588
+ */
8589
+ updateDataset: function(index) {
8590
+ var me = this;
8591
+ var meta = me.getDatasetMeta(index);
8592
+ var args = {
8593
+ meta: meta,
8594
+ index: index
8595
+ };
8596
+
8597
+ if (plugins.notify(me, 'beforeDatasetUpdate', [args]) === false) {
8598
+ return;
8599
+ }
8600
+
8601
+ meta.controller.update();
8602
+
8603
+ plugins.notify(me, 'afterDatasetUpdate', [args]);
8604
+ },
8605
+
8606
+ render: function(config) {
8607
+ var me = this;
8608
+
8609
+ if (!config || typeof config !== 'object') {
8610
+ // backwards compatibility
8611
+ config = {
8612
+ duration: config,
8613
+ lazy: arguments[1]
8614
+ };
8615
+ }
8616
+
8617
+ var duration = config.duration;
8618
+ var lazy = config.lazy;
8619
+
8620
+ if (plugins.notify(me, 'beforeRender') === false) {
8621
+ return;
8622
+ }
8623
+
8624
+ var animationOptions = me.options.animation;
8625
+ var onComplete = function(animation) {
8626
+ plugins.notify(me, 'afterRender');
8627
+ helpers.callback(animationOptions && animationOptions.onComplete, [animation], me);
8628
+ };
8629
+
8630
+ if (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) {
8631
+ var animation = new Chart.Animation({
8632
+ numSteps: (duration || animationOptions.duration) / 16.66, // 60 fps
8633
+ easing: config.easing || animationOptions.easing,
8634
+
8635
+ render: function(chart, animationObject) {
8636
+ var easingFunction = helpers.easing.effects[animationObject.easing];
8637
+ var currentStep = animationObject.currentStep;
8638
+ var stepDecimal = currentStep / animationObject.numSteps;
8639
+
8640
+ chart.draw(easingFunction(stepDecimal), stepDecimal, currentStep);
8641
+ },
8642
+
8643
+ onAnimationProgress: animationOptions.onProgress,
8644
+ onAnimationComplete: onComplete
8645
+ });
8646
+
8647
+ Chart.animationService.addAnimation(me, animation, duration, lazy);
8648
+ } else {
8649
+ me.draw();
8650
+
8651
+ // See https://github.com/chartjs/Chart.js/issues/3781
8652
+ onComplete(new Chart.Animation({numSteps: 0, chart: me}));
8653
+ }
8654
+
8655
+ return me;
8656
+ },
8657
+
8658
+ draw: function(easingValue) {
8659
+ var me = this;
8660
+
8661
+ me.clear();
8662
+
8663
+ if (helpers.isNullOrUndef(easingValue)) {
8664
+ easingValue = 1;
8665
+ }
8666
+
8667
+ me.transition(easingValue);
8668
+
8669
+ if (plugins.notify(me, 'beforeDraw', [easingValue]) === false) {
8670
+ return;
8671
+ }
8672
+
8673
+ // Draw all the scales
8674
+ helpers.each(me.boxes, function(box) {
8675
+ box.draw(me.chartArea);
8676
+ }, me);
8677
+
8678
+ if (me.scale) {
8679
+ me.scale.draw();
8680
+ }
8681
+
8682
+ me.drawDatasets(easingValue);
8683
+
8684
+ // Finally draw the tooltip
8685
+ me.tooltip.draw();
8686
+
8687
+ plugins.notify(me, 'afterDraw', [easingValue]);
8688
+ },
8689
+
8690
+ /**
8691
+ * @private
8692
+ */
8693
+ transition: function(easingValue) {
8694
+ var me = this;
8695
+
8696
+ for (var i = 0, ilen = (me.data.datasets || []).length; i < ilen; ++i) {
8697
+ if (me.isDatasetVisible(i)) {
8698
+ me.getDatasetMeta(i).controller.transition(easingValue);
8699
+ }
8700
+ }
8701
+
8702
+ me.tooltip.transition(easingValue);
8703
+ },
8704
+
8705
+ /**
8706
+ * Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw`
8707
+ * hook, in which case, plugins will not be called on `afterDatasetsDraw`.
8708
+ * @private
8709
+ */
8710
+ drawDatasets: function(easingValue) {
8711
+ var me = this;
8712
+
8713
+ if (plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) {
8714
+ return;
8715
+ }
8716
+
8717
+ // Draw datasets reversed to support proper line stacking
8718
+ for (var i = (me.data.datasets || []).length - 1; i >= 0; --i) {
8719
+ if (me.isDatasetVisible(i)) {
8720
+ me.drawDataset(i, easingValue);
8721
+ }
8722
+ }
8723
+
8724
+ plugins.notify(me, 'afterDatasetsDraw', [easingValue]);
8725
+ },
8726
+
8727
+ /**
8728
+ * Draws dataset at index unless a plugin returns `false` to the `beforeDatasetDraw`
8729
+ * hook, in which case, plugins will not be called on `afterDatasetDraw`.
8730
+ * @private
8731
+ */
8732
+ drawDataset: function(index, easingValue) {
8733
+ var me = this;
8734
+ var meta = me.getDatasetMeta(index);
8735
+ var args = {
8736
+ meta: meta,
8737
+ index: index,
8738
+ easingValue: easingValue
8739
+ };
8740
+
8741
+ if (plugins.notify(me, 'beforeDatasetDraw', [args]) === false) {
8742
+ return;
8743
+ }
8744
+
8745
+ meta.controller.draw(easingValue);
8746
+
8747
+ plugins.notify(me, 'afterDatasetDraw', [args]);
8748
+ },
8749
+
8750
+ // Get the single element that was clicked on
8751
+ // @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw
8752
+ getElementAtEvent: function(e) {
8753
+ return Interaction.modes.single(this, e);
8754
+ },
8755
+
8756
+ getElementsAtEvent: function(e) {
8757
+ return Interaction.modes.label(this, e, {intersect: true});
8758
+ },
8759
+
8760
+ getElementsAtXAxis: function(e) {
8761
+ return Interaction.modes['x-axis'](this, e, {intersect: true});
8762
+ },
8763
+
8764
+ getElementsAtEventForMode: function(e, mode, options) {
8765
+ var method = Interaction.modes[mode];
8766
+ if (typeof method === 'function') {
8767
+ return method(this, e, options);
8768
+ }
8769
+
8770
+ return [];
8771
+ },
8772
+
8773
+ getDatasetAtEvent: function(e) {
8774
+ return Interaction.modes.dataset(this, e, {intersect: true});
8775
+ },
8776
+
8777
+ getDatasetMeta: function(datasetIndex) {
8778
+ var me = this;
8779
+ var dataset = me.data.datasets[datasetIndex];
8780
+ if (!dataset._meta) {
8781
+ dataset._meta = {};
8782
+ }
8783
+
8784
+ var meta = dataset._meta[me.id];
8785
+ if (!meta) {
8786
+ meta = dataset._meta[me.id] = {
8787
+ type: null,
8788
+ data: [],
8789
+ dataset: null,
8790
+ controller: null,
8791
+ hidden: null, // See isDatasetVisible() comment
8792
+ xAxisID: null,
8793
+ yAxisID: null
8794
+ };
8795
+ }
8796
+
8797
+ return meta;
8798
+ },
8799
+
8800
+ getVisibleDatasetCount: function() {
8801
+ var count = 0;
8802
+ for (var i = 0, ilen = this.data.datasets.length; i < ilen; ++i) {
8803
+ if (this.isDatasetVisible(i)) {
8804
+ count++;
8805
+ }
8806
+ }
8807
+ return count;
8808
+ },
8809
+
8810
+ isDatasetVisible: function(datasetIndex) {
8811
+ var meta = this.getDatasetMeta(datasetIndex);
8812
+
8813
+ // meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false,
8814
+ // the dataset.hidden value is ignored, else if null, the dataset hidden state is returned.
8815
+ return typeof meta.hidden === 'boolean' ? !meta.hidden : !this.data.datasets[datasetIndex].hidden;
8816
+ },
8817
+
8818
+ generateLegend: function() {
8819
+ return this.options.legendCallback(this);
8820
+ },
8821
+
8822
+ /**
8823
+ * @private
8824
+ */
8825
+ destroyDatasetMeta: function(datasetIndex) {
8826
+ var id = this.id;
8827
+ var dataset = this.data.datasets[datasetIndex];
8828
+ var meta = dataset._meta && dataset._meta[id];
8829
+
8830
+ if (meta) {
8831
+ meta.controller.destroy();
8832
+ delete dataset._meta[id];
8833
+ }
8834
+ },
8835
+
8836
+ destroy: function() {
8837
+ var me = this;
8838
+ var canvas = me.canvas;
8839
+ var i, ilen;
8840
+
8841
+ me.stop();
8842
+
8843
+ // dataset controllers need to cleanup associated data
8844
+ for (i = 0, ilen = me.data.datasets.length; i < ilen; ++i) {
8845
+ me.destroyDatasetMeta(i);
8846
+ }
8847
+
8848
+ if (canvas) {
8849
+ me.unbindEvents();
8850
+ helpers.canvas.clear(me);
8851
+ platform.releaseContext(me.ctx);
8852
+ me.canvas = null;
8853
+ me.ctx = null;
8854
+ }
8855
+
8856
+ plugins.notify(me, 'destroy');
8857
+
8858
+ delete Chart.instances[me.id];
8859
+ },
8860
+
8861
+ toBase64Image: function() {
8862
+ return this.canvas.toDataURL.apply(this.canvas, arguments);
8863
+ },
8864
+
8865
+ initToolTip: function() {
8866
+ var me = this;
8867
+ me.tooltip = new Chart.Tooltip({
8868
+ _chart: me,
8869
+ _chartInstance: me, // deprecated, backward compatibility
8870
+ _data: me.data,
8871
+ _options: me.options.tooltips
8872
+ }, me);
8873
+ },
8874
+
8875
+ /**
8876
+ * @private
8877
+ */
8878
+ bindEvents: function() {
8879
+ var me = this;
8880
+ var listeners = me._listeners = {};
8881
+ var listener = function() {
8882
+ me.eventHandler.apply(me, arguments);
8883
+ };
8884
+
8885
+ helpers.each(me.options.events, function(type) {
8886
+ platform.addEventListener(me, type, listener);
8887
+ listeners[type] = listener;
8888
+ });
8889
+
8890
+ // Elements used to detect size change should not be injected for non responsive charts.
8891
+ // See https://github.com/chartjs/Chart.js/issues/2210
8892
+ if (me.options.responsive) {
8893
+ listener = function() {
8894
+ me.resize();
8895
+ };
8896
+
8897
+ platform.addEventListener(me, 'resize', listener);
8898
+ listeners.resize = listener;
8899
+ }
8900
+ },
8901
+
8902
+ /**
8903
+ * @private
8904
+ */
8905
+ unbindEvents: function() {
8906
+ var me = this;
8907
+ var listeners = me._listeners;
8908
+ if (!listeners) {
8909
+ return;
8910
+ }
8911
+
8912
+ delete me._listeners;
8913
+ helpers.each(listeners, function(listener, type) {
8914
+ platform.removeEventListener(me, type, listener);
8915
+ });
8916
+ },
8917
+
8918
+ updateHoverStyle: function(elements, mode, enabled) {
8919
+ var method = enabled ? 'setHoverStyle' : 'removeHoverStyle';
8920
+ var element, i, ilen;
8921
+
8922
+ for (i = 0, ilen = elements.length; i < ilen; ++i) {
8923
+ element = elements[i];
8924
+ if (element) {
8925
+ this.getDatasetMeta(element._datasetIndex).controller[method](element);
8926
+ }
8927
+ }
8928
+ },
8929
+
8930
+ /**
8931
+ * @private
8932
+ */
8933
+ eventHandler: function(e) {
8934
+ var me = this;
8935
+ var tooltip = me.tooltip;
8936
+
8937
+ if (plugins.notify(me, 'beforeEvent', [e]) === false) {
8938
+ return;
8939
+ }
8940
+
8941
+ // Buffer any update calls so that renders do not occur
8942
+ me._bufferedRender = true;
8943
+ me._bufferedRequest = null;
8944
+
8945
+ var changed = me.handleEvent(e);
8946
+ changed |= tooltip && tooltip.handleEvent(e);
8947
+
8948
+ plugins.notify(me, 'afterEvent', [e]);
8949
+
8950
+ var bufferedRequest = me._bufferedRequest;
8951
+ if (bufferedRequest) {
8952
+ // If we have an update that was triggered, we need to do a normal render
8953
+ me.render(bufferedRequest);
8954
+ } else if (changed && !me.animating) {
8955
+ // If entering, leaving, or changing elements, animate the change via pivot
8956
+ me.stop();
8957
+
8958
+ // We only need to render at this point. Updating will cause scales to be
8959
+ // recomputed generating flicker & using more memory than necessary.
8960
+ me.render(me.options.hover.animationDuration, true);
8961
+ }
8962
+
8963
+ me._bufferedRender = false;
8964
+ me._bufferedRequest = null;
8965
+
8966
+ return me;
8967
+ },
8968
+
8969
+ /**
8970
+ * Handle an event
8971
+ * @private
8972
+ * @param {IEvent} event the event to handle
8973
+ * @return {Boolean} true if the chart needs to re-render
8974
+ */
8975
+ handleEvent: function(e) {
8976
+ var me = this;
8977
+ var options = me.options || {};
8978
+ var hoverOptions = options.hover;
8979
+ var changed = false;
8980
+
8981
+ me.lastActive = me.lastActive || [];
8982
+
8983
+ // Find Active Elements for hover and tooltips
8984
+ if (e.type === 'mouseout') {
8985
+ me.active = [];
8986
+ } else {
8987
+ me.active = me.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions);
8988
+ }
8989
+
8990
+ // Invoke onHover hook
8991
+ // Need to call with native event here to not break backwards compatibility
8992
+ helpers.callback(options.onHover || options.hover.onHover, [e.native, me.active], me);
8993
+
8994
+ if (e.type === 'mouseup' || e.type === 'click') {
8995
+ if (options.onClick) {
8996
+ // Use e.native here for backwards compatibility
8997
+ options.onClick.call(me, e.native, me.active);
8998
+ }
8999
+ }
9000
+
9001
+ // Remove styling for last active (even if it may still be active)
9002
+ if (me.lastActive.length) {
9003
+ me.updateHoverStyle(me.lastActive, hoverOptions.mode, false);
9004
+ }
9005
+
9006
+ // Built in hover styling
9007
+ if (me.active.length && hoverOptions.mode) {
9008
+ me.updateHoverStyle(me.active, hoverOptions.mode, true);
9009
+ }
9010
+
9011
+ changed = !helpers.arrayEquals(me.active, me.lastActive);
9012
+
9013
+ // Remember Last Actives
9014
+ me.lastActive = me.active;
9015
+
9016
+ return changed;
9017
+ }
9018
+ });
9019
+
9020
+ /**
9021
+ * Provided for backward compatibility, use Chart instead.
9022
+ * @class Chart.Controller
9023
+ * @deprecated since version 2.6.0
9024
+ * @todo remove at version 3
9025
+ * @private
9026
+ */
9027
+ Chart.Controller = Chart;
9028
+ };
9029
+
9030
+ },{"25":25,"28":28,"45":45,"48":48}],24:[function(require,module,exports){
9031
+ 'use strict';
9032
+
9033
+ var helpers = require(45);
9034
+
9035
+ module.exports = function(Chart) {
9036
+
9037
+ var arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift'];
9038
+
9039
+ /**
9040
+ * Hooks the array methods that add or remove values ('push', pop', 'shift', 'splice',
9041
+ * 'unshift') and notify the listener AFTER the array has been altered. Listeners are
9042
+ * called on the 'onData*' callbacks (e.g. onDataPush, etc.) with same arguments.
9043
+ */
9044
+ function listenArrayEvents(array, listener) {
9045
+ if (array._chartjs) {
9046
+ array._chartjs.listeners.push(listener);
9047
+ return;
9048
+ }
9049
+
9050
+ Object.defineProperty(array, '_chartjs', {
9051
+ configurable: true,
9052
+ enumerable: false,
9053
+ value: {
9054
+ listeners: [listener]
9055
+ }
9056
+ });
9057
+
9058
+ arrayEvents.forEach(function(key) {
9059
+ var method = 'onData' + key.charAt(0).toUpperCase() + key.slice(1);
9060
+ var base = array[key];
9061
+
9062
+ Object.defineProperty(array, key, {
9063
+ configurable: true,
9064
+ enumerable: false,
9065
+ value: function() {
9066
+ var args = Array.prototype.slice.call(arguments);
9067
+ var res = base.apply(this, args);
9068
+
9069
+ helpers.each(array._chartjs.listeners, function(object) {
9070
+ if (typeof object[method] === 'function') {
9071
+ object[method].apply(object, args);
9072
+ }
9073
+ });
9074
+
9075
+ return res;
9076
+ }
9077
+ });
9078
+ });
9079
+ }
9080
+
9081
+ /**
9082
+ * Removes the given array event listener and cleanup extra attached properties (such as
9083
+ * the _chartjs stub and overridden methods) if array doesn't have any more listeners.
9084
+ */
9085
+ function unlistenArrayEvents(array, listener) {
9086
+ var stub = array._chartjs;
9087
+ if (!stub) {
9088
+ return;
9089
+ }
9090
+
9091
+ var listeners = stub.listeners;
9092
+ var index = listeners.indexOf(listener);
9093
+ if (index !== -1) {
9094
+ listeners.splice(index, 1);
9095
+ }
9096
+
9097
+ if (listeners.length > 0) {
9098
+ return;
9099
+ }
9100
+
9101
+ arrayEvents.forEach(function(key) {
9102
+ delete array[key];
9103
+ });
9104
+
9105
+ delete array._chartjs;
9106
+ }
9107
+
9108
+ // Base class for all dataset controllers (line, bar, etc)
9109
+ Chart.DatasetController = function(chart, datasetIndex) {
9110
+ this.initialize(chart, datasetIndex);
9111
+ };
9112
+
9113
+ helpers.extend(Chart.DatasetController.prototype, {
9114
+
9115
+ /**
9116
+ * Element type used to generate a meta dataset (e.g. Chart.element.Line).
9117
+ * @type {Chart.core.element}
9118
+ */
9119
+ datasetElementType: null,
9120
+
9121
+ /**
9122
+ * Element type used to generate a meta data (e.g. Chart.element.Point).
9123
+ * @type {Chart.core.element}
9124
+ */
9125
+ dataElementType: null,
9126
+
9127
+ initialize: function(chart, datasetIndex) {
9128
+ var me = this;
9129
+ me.chart = chart;
9130
+ me.index = datasetIndex;
9131
+ me.linkScales();
9132
+ me.addElements();
9133
+ },
9134
+
9135
+ updateIndex: function(datasetIndex) {
9136
+ this.index = datasetIndex;
9137
+ },
9138
+
9139
+ linkScales: function() {
9140
+ var me = this;
9141
+ var meta = me.getMeta();
9142
+ var dataset = me.getDataset();
9143
+
9144
+ if (meta.xAxisID === null) {
9145
+ meta.xAxisID = dataset.xAxisID || me.chart.options.scales.xAxes[0].id;
9146
+ }
9147
+ if (meta.yAxisID === null) {
9148
+ meta.yAxisID = dataset.yAxisID || me.chart.options.scales.yAxes[0].id;
9149
+ }
9150
+ },
9151
+
9152
+ getDataset: function() {
9153
+ return this.chart.data.datasets[this.index];
9154
+ },
9155
+
9156
+ getMeta: function() {
9157
+ return this.chart.getDatasetMeta(this.index);
9158
+ },
9159
+
9160
+ getScaleForId: function(scaleID) {
9161
+ return this.chart.scales[scaleID];
9162
+ },
9163
+
9164
+ reset: function() {
9165
+ this.update(true);
9166
+ },
9167
+
9168
+ /**
9169
+ * @private
9170
+ */
9171
+ destroy: function() {
9172
+ if (this._data) {
9173
+ unlistenArrayEvents(this._data, this);
9174
+ }
9175
+ },
9176
+
9177
+ createMetaDataset: function() {
9178
+ var me = this;
9179
+ var type = me.datasetElementType;
9180
+ return type && new type({
9181
+ _chart: me.chart,
9182
+ _datasetIndex: me.index
9183
+ });
9184
+ },
9185
+
9186
+ createMetaData: function(index) {
9187
+ var me = this;
9188
+ var type = me.dataElementType;
9189
+ return type && new type({
9190
+ _chart: me.chart,
9191
+ _datasetIndex: me.index,
9192
+ _index: index
9193
+ });
9194
+ },
9195
+
9196
+ addElements: function() {
9197
+ var me = this;
9198
+ var meta = me.getMeta();
9199
+ var data = me.getDataset().data || [];
9200
+ var metaData = meta.data;
9201
+ var i, ilen;
9202
+
9203
+ for (i = 0, ilen = data.length; i < ilen; ++i) {
9204
+ metaData[i] = metaData[i] || me.createMetaData(i);
9205
+ }
9206
+
9207
+ meta.dataset = meta.dataset || me.createMetaDataset();
9208
+ },
9209
+
9210
+ addElementAndReset: function(index) {
9211
+ var element = this.createMetaData(index);
9212
+ this.getMeta().data.splice(index, 0, element);
9213
+ this.updateElement(element, index, true);
9214
+ },
9215
+
9216
+ buildOrUpdateElements: function() {
9217
+ var me = this;
9218
+ var dataset = me.getDataset();
9219
+ var data = dataset.data || (dataset.data = []);
9220
+
9221
+ // In order to correctly handle data addition/deletion animation (an thus simulate
9222
+ // real-time charts), we need to monitor these data modifications and synchronize
9223
+ // the internal meta data accordingly.
9224
+ if (me._data !== data) {
9225
+ if (me._data) {
9226
+ // This case happens when the user replaced the data array instance.
9227
+ unlistenArrayEvents(me._data, me);
9228
+ }
9229
+
9230
+ listenArrayEvents(data, me);
9231
+ me._data = data;
9232
+ }
9233
+
9234
+ // Re-sync meta data in case the user replaced the data array or if we missed
9235
+ // any updates and so make sure that we handle number of datapoints changing.
9236
+ me.resyncElements();
9237
+ },
9238
+
9239
+ update: helpers.noop,
9240
+
9241
+ transition: function(easingValue) {
9242
+ var meta = this.getMeta();
9243
+ var elements = meta.data || [];
9244
+ var ilen = elements.length;
9245
+ var i = 0;
9246
+
9247
+ for (; i < ilen; ++i) {
9248
+ elements[i].transition(easingValue);
9249
+ }
9250
+
9251
+ if (meta.dataset) {
9252
+ meta.dataset.transition(easingValue);
9253
+ }
9254
+ },
9255
+
9256
+ draw: function() {
9257
+ var meta = this.getMeta();
9258
+ var elements = meta.data || [];
9259
+ var ilen = elements.length;
9260
+ var i = 0;
9261
+
9262
+ if (meta.dataset) {
9263
+ meta.dataset.draw();
9264
+ }
9265
+
9266
+ for (; i < ilen; ++i) {
9267
+ elements[i].draw();
9268
+ }
9269
+ },
9270
+
9271
+ removeHoverStyle: function(element, elementOpts) {
9272
+ var dataset = this.chart.data.datasets[element._datasetIndex];
9273
+ var index = element._index;
9274
+ var custom = element.custom || {};
9275
+ var valueOrDefault = helpers.valueAtIndexOrDefault;
9276
+ var model = element._model;
9277
+
9278
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, elementOpts.backgroundColor);
9279
+ model.borderColor = custom.borderColor ? custom.borderColor : valueOrDefault(dataset.borderColor, index, elementOpts.borderColor);
9280
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : valueOrDefault(dataset.borderWidth, index, elementOpts.borderWidth);
9281
+ },
9282
+
9283
+ setHoverStyle: function(element) {
9284
+ var dataset = this.chart.data.datasets[element._datasetIndex];
9285
+ var index = element._index;
9286
+ var custom = element.custom || {};
9287
+ var valueOrDefault = helpers.valueAtIndexOrDefault;
9288
+ var getHoverColor = helpers.getHoverColor;
9289
+ var model = element._model;
9290
+
9291
+ model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueOrDefault(dataset.hoverBackgroundColor, index, getHoverColor(model.backgroundColor));
9292
+ model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : valueOrDefault(dataset.hoverBorderColor, index, getHoverColor(model.borderColor));
9293
+ model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : valueOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
9294
+ },
9295
+
9296
+ /**
9297
+ * @private
9298
+ */
9299
+ resyncElements: function() {
9300
+ var me = this;
9301
+ var meta = me.getMeta();
9302
+ var data = me.getDataset().data;
9303
+ var numMeta = meta.data.length;
9304
+ var numData = data.length;
9305
+
9306
+ if (numData < numMeta) {
9307
+ meta.data.splice(numData, numMeta - numData);
9308
+ } else if (numData > numMeta) {
9309
+ me.insertElements(numMeta, numData - numMeta);
9310
+ }
9311
+ },
9312
+
9313
+ /**
9314
+ * @private
9315
+ */
9316
+ insertElements: function(start, count) {
9317
+ for (var i = 0; i < count; ++i) {
9318
+ this.addElementAndReset(start + i);
9319
+ }
9320
+ },
9321
+
9322
+ /**
9323
+ * @private
9324
+ */
9325
+ onDataPush: function() {
9326
+ this.insertElements(this.getDataset().data.length - 1, arguments.length);
9327
+ },
9328
+
9329
+ /**
9330
+ * @private
9331
+ */
9332
+ onDataPop: function() {
9333
+ this.getMeta().data.pop();
9334
+ },
9335
+
9336
+ /**
9337
+ * @private
9338
+ */
9339
+ onDataShift: function() {
9340
+ this.getMeta().data.shift();
9341
+ },
9342
+
9343
+ /**
9344
+ * @private
9345
+ */
9346
+ onDataSplice: function(start, count) {
9347
+ this.getMeta().data.splice(start, count);
9348
+ this.insertElements(start, arguments.length - 2);
9349
+ },
9350
+
9351
+ /**
9352
+ * @private
9353
+ */
9354
+ onDataUnshift: function() {
9355
+ this.insertElements(0, arguments.length);
9356
+ }
9357
+ });
9358
+
9359
+ Chart.DatasetController.extend = helpers.inherits;
9360
+ };
9361
+
9362
+ },{"45":45}],25:[function(require,module,exports){
9363
+ 'use strict';
9364
+
9365
+ var helpers = require(45);
9366
+
9367
+ module.exports = {
9368
+ /**
9369
+ * @private
9370
+ */
9371
+ _set: function(scope, values) {
9372
+ return helpers.merge(this[scope] || (this[scope] = {}), values);
9373
+ }
9374
+ };
9375
+
9376
+ },{"45":45}],26:[function(require,module,exports){
9377
+ 'use strict';
9378
+
9379
+ var color = require(2);
9380
+ var helpers = require(45);
9381
+
9382
+ function interpolate(start, view, model, ease) {
9383
+ var keys = Object.keys(model);
9384
+ var i, ilen, key, actual, origin, target, type, c0, c1;
9385
+
9386
+ for (i = 0, ilen = keys.length; i < ilen; ++i) {
9387
+ key = keys[i];
9388
+
9389
+ target = model[key];
9390
+
9391
+ // if a value is added to the model after pivot() has been called, the view
9392
+ // doesn't contain it, so let's initialize the view to the target value.
9393
+ if (!view.hasOwnProperty(key)) {
9394
+ view[key] = target;
9395
+ }
9396
+
9397
+ actual = view[key];
9398
+
9399
+ if (actual === target || key[0] === '_') {
9400
+ continue;
9401
+ }
9402
+
9403
+ if (!start.hasOwnProperty(key)) {
9404
+ start[key] = actual;
9405
+ }
9406
+
9407
+ origin = start[key];
9408
+
9409
+ type = typeof target;
9410
+
9411
+ if (type === typeof origin) {
9412
+ if (type === 'string') {
9413
+ c0 = color(origin);
9414
+ if (c0.valid) {
9415
+ c1 = color(target);
9416
+ if (c1.valid) {
9417
+ view[key] = c1.mix(c0, ease).rgbString();
9418
+ continue;
9419
+ }
9420
+ }
9421
+ } else if (type === 'number' && isFinite(origin) && isFinite(target)) {
9422
+ view[key] = origin + (target - origin) * ease;
9423
+ continue;
9424
+ }
9425
+ }
9426
+
9427
+ view[key] = target;
9428
+ }
9429
+ }
9430
+
9431
+ var Element = function(configuration) {
9432
+ helpers.extend(this, configuration);
9433
+ this.initialize.apply(this, arguments);
9434
+ };
9435
+
9436
+ helpers.extend(Element.prototype, {
9437
+
9438
+ initialize: function() {
9439
+ this.hidden = false;
9440
+ },
9441
+
9442
+ pivot: function() {
9443
+ var me = this;
9444
+ if (!me._view) {
9445
+ me._view = helpers.clone(me._model);
9446
+ }
9447
+ me._start = {};
9448
+ return me;
9449
+ },
9450
+
9451
+ transition: function(ease) {
9452
+ var me = this;
9453
+ var model = me._model;
9454
+ var start = me._start;
9455
+ var view = me._view;
9456
+
9457
+ // No animation -> No Transition
9458
+ if (!model || ease === 1) {
9459
+ me._view = model;
9460
+ me._start = null;
9461
+ return me;
9462
+ }
9463
+
9464
+ if (!view) {
9465
+ view = me._view = {};
9466
+ }
9467
+
9468
+ if (!start) {
9469
+ start = me._start = {};
9470
+ }
9471
+
9472
+ interpolate(start, view, model, ease);
9473
+
9474
+ return me;
9475
+ },
9476
+
9477
+ tooltipPosition: function() {
9478
+ return {
9479
+ x: this._model.x,
9480
+ y: this._model.y
9481
+ };
9482
+ },
9483
+
9484
+ hasValue: function() {
9485
+ return helpers.isNumber(this._model.x) && helpers.isNumber(this._model.y);
9486
+ }
9487
+ });
9488
+
9489
+ Element.extend = helpers.inherits;
9490
+
9491
+ module.exports = Element;
9492
+
9493
+ },{"2":2,"45":45}],27:[function(require,module,exports){
9494
+ /* global window: false */
9495
+ /* global document: false */
9496
+ 'use strict';
9497
+
9498
+ var color = require(2);
9499
+ var defaults = require(25);
9500
+ var helpers = require(45);
9501
+
9502
+ module.exports = function(Chart) {
9503
+
9504
+ // -- Basic js utility methods
9505
+
9506
+ helpers.extend = function(base) {
9507
+ var setFn = function(value, key) {
9508
+ base[key] = value;
9509
+ };
9510
+ for (var i = 1, ilen = arguments.length; i < ilen; i++) {
9511
+ helpers.each(arguments[i], setFn);
9512
+ }
9513
+ return base;
9514
+ };
9515
+
9516
+ helpers.configMerge = function(/* objects ... */) {
9517
+ return helpers.merge(helpers.clone(arguments[0]), [].slice.call(arguments, 1), {
9518
+ merger: function(key, target, source, options) {
9519
+ var tval = target[key] || {};
9520
+ var sval = source[key];
9521
+
9522
+ if (key === 'scales') {
9523
+ // scale config merging is complex. Add our own function here for that
9524
+ target[key] = helpers.scaleMerge(tval, sval);
9525
+ } else if (key === 'scale') {
9526
+ // used in polar area & radar charts since there is only one scale
9527
+ target[key] = helpers.merge(tval, [Chart.scaleService.getScaleDefaults(sval.type), sval]);
9528
+ } else {
9529
+ helpers._merger(key, target, source, options);
9530
+ }
9531
+ }
9532
+ });
9533
+ };
9534
+
9535
+ helpers.scaleMerge = function(/* objects ... */) {
9536
+ return helpers.merge(helpers.clone(arguments[0]), [].slice.call(arguments, 1), {
9537
+ merger: function(key, target, source, options) {
9538
+ if (key === 'xAxes' || key === 'yAxes') {
9539
+ var slen = source[key].length;
9540
+ var i, type, scale;
9541
+
9542
+ if (!target[key]) {
9543
+ target[key] = [];
9544
+ }
9545
+
9546
+ for (i = 0; i < slen; ++i) {
9547
+ scale = source[key][i];
9548
+ type = helpers.valueOrDefault(scale.type, key === 'xAxes' ? 'category' : 'linear');
9549
+
9550
+ if (i >= target[key].length) {
9551
+ target[key].push({});
9552
+ }
9553
+
9554
+ if (!target[key][i].type || (scale.type && scale.type !== target[key][i].type)) {
9555
+ // new/untyped scale or type changed: let's apply the new defaults
9556
+ // then merge source scale to correctly overwrite the defaults.
9557
+ helpers.merge(target[key][i], [Chart.scaleService.getScaleDefaults(type), scale]);
9558
+ } else {
9559
+ // scales type are the same
9560
+ helpers.merge(target[key][i], scale);
9561
+ }
9562
+ }
9563
+ } else {
9564
+ helpers._merger(key, target, source, options);
9565
+ }
9566
+ }
9567
+ });
9568
+ };
9569
+
9570
+ helpers.where = function(collection, filterCallback) {
9571
+ if (helpers.isArray(collection) && Array.prototype.filter) {
9572
+ return collection.filter(filterCallback);
9573
+ }
9574
+ var filtered = [];
9575
+
9576
+ helpers.each(collection, function(item) {
9577
+ if (filterCallback(item)) {
9578
+ filtered.push(item);
9579
+ }
9580
+ });
9581
+
9582
+ return filtered;
9583
+ };
9584
+ helpers.findIndex = Array.prototype.findIndex ?
9585
+ function(array, callback, scope) {
9586
+ return array.findIndex(callback, scope);
9587
+ } :
9588
+ function(array, callback, scope) {
9589
+ scope = scope === undefined ? array : scope;
9590
+ for (var i = 0, ilen = array.length; i < ilen; ++i) {
9591
+ if (callback.call(scope, array[i], i, array)) {
9592
+ return i;
9593
+ }
9594
+ }
9595
+ return -1;
9596
+ };
9597
+ helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex) {
9598
+ // Default to start of the array
9599
+ if (helpers.isNullOrUndef(startIndex)) {
9600
+ startIndex = -1;
9601
+ }
9602
+ for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
9603
+ var currentItem = arrayToSearch[i];
9604
+ if (filterCallback(currentItem)) {
9605
+ return currentItem;
9606
+ }
9607
+ }
9608
+ };
9609
+ helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) {
9610
+ // Default to end of the array
9611
+ if (helpers.isNullOrUndef(startIndex)) {
9612
+ startIndex = arrayToSearch.length;
9613
+ }
9614
+ for (var i = startIndex - 1; i >= 0; i--) {
9615
+ var currentItem = arrayToSearch[i];
9616
+ if (filterCallback(currentItem)) {
9617
+ return currentItem;
9618
+ }
9619
+ }
9620
+ };
9621
+ helpers.inherits = function(extensions) {
9622
+ // Basic javascript inheritance based on the model created in Backbone.js
9623
+ var me = this;
9624
+ var ChartElement = (extensions && extensions.hasOwnProperty('constructor')) ? extensions.constructor : function() {
9625
+ return me.apply(this, arguments);
9626
+ };
9627
+
9628
+ var Surrogate = function() {
9629
+ this.constructor = ChartElement;
9630
+ };
9631
+ Surrogate.prototype = me.prototype;
9632
+ ChartElement.prototype = new Surrogate();
9633
+
9634
+ ChartElement.extend = helpers.inherits;
9635
+
9636
+ if (extensions) {
9637
+ helpers.extend(ChartElement.prototype, extensions);
9638
+ }
9639
+
9640
+ ChartElement.__super__ = me.prototype;
9641
+
9642
+ return ChartElement;
9643
+ };
9644
+ // -- Math methods
9645
+ helpers.isNumber = function(n) {
9646
+ return !isNaN(parseFloat(n)) && isFinite(n);
9647
+ };
9648
+ helpers.almostEquals = function(x, y, epsilon) {
9649
+ return Math.abs(x - y) < epsilon;
9650
+ };
9651
+ helpers.almostWhole = function(x, epsilon) {
9652
+ var rounded = Math.round(x);
9653
+ return (((rounded - epsilon) < x) && ((rounded + epsilon) > x));
9654
+ };
9655
+ helpers.max = function(array) {
9656
+ return array.reduce(function(max, value) {
9657
+ if (!isNaN(value)) {
9658
+ return Math.max(max, value);
9659
+ }
9660
+ return max;
9661
+ }, Number.NEGATIVE_INFINITY);
9662
+ };
9663
+ helpers.min = function(array) {
9664
+ return array.reduce(function(min, value) {
9665
+ if (!isNaN(value)) {
9666
+ return Math.min(min, value);
9667
+ }
9668
+ return min;
9669
+ }, Number.POSITIVE_INFINITY);
9670
+ };
9671
+ helpers.sign = Math.sign ?
9672
+ function(x) {
9673
+ return Math.sign(x);
9674
+ } :
9675
+ function(x) {
9676
+ x = +x; // convert to a number
9677
+ if (x === 0 || isNaN(x)) {
9678
+ return x;
9679
+ }
9680
+ return x > 0 ? 1 : -1;
9681
+ };
9682
+ helpers.log10 = Math.log10 ?
9683
+ function(x) {
9684
+ return Math.log10(x);
9685
+ } :
9686
+ function(x) {
9687
+ return Math.log(x) / Math.LN10;
9688
+ };
9689
+ helpers.toRadians = function(degrees) {
9690
+ return degrees * (Math.PI / 180);
9691
+ };
9692
+ helpers.toDegrees = function(radians) {
9693
+ return radians * (180 / Math.PI);
9694
+ };
9695
+ // Gets the angle from vertical upright to the point about a centre.
9696
+ helpers.getAngleFromPoint = function(centrePoint, anglePoint) {
9697
+ var distanceFromXCenter = anglePoint.x - centrePoint.x;
9698
+ var distanceFromYCenter = anglePoint.y - centrePoint.y;
9699
+ var radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
9700
+
9701
+ var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);
9702
+
9703
+ if (angle < (-0.5 * Math.PI)) {
9704
+ angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2]
9705
+ }
9706
+
9707
+ return {
9708
+ angle: angle,
9709
+ distance: radialDistanceFromCenter
9710
+ };
9711
+ };
9712
+ helpers.distanceBetweenPoints = function(pt1, pt2) {
9713
+ return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2));
9714
+ };
9715
+ helpers.aliasPixel = function(pixelWidth) {
9716
+ return (pixelWidth % 2 === 0) ? 0 : 0.5;
9717
+ };
9718
+ helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) {
9719
+ // Props to Rob Spencer at scaled innovation for his post on splining between points
9720
+ // http://scaledinnovation.com/analytics/splines/aboutSplines.html
9721
+
9722
+ // This function must also respect "skipped" points
9723
+
9724
+ var previous = firstPoint.skip ? middlePoint : firstPoint;
9725
+ var current = middlePoint;
9726
+ var next = afterPoint.skip ? middlePoint : afterPoint;
9727
+
9728
+ var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2));
9729
+ var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2));
9730
+
9731
+ var s01 = d01 / (d01 + d12);
9732
+ var s12 = d12 / (d01 + d12);
9733
+
9734
+ // If all points are the same, s01 & s02 will be inf
9735
+ s01 = isNaN(s01) ? 0 : s01;
9736
+ s12 = isNaN(s12) ? 0 : s12;
9737
+
9738
+ var fa = t * s01; // scaling factor for triangle Ta
9739
+ var fb = t * s12;
9740
+
9741
+ return {
9742
+ previous: {
9743
+ x: current.x - fa * (next.x - previous.x),
9744
+ y: current.y - fa * (next.y - previous.y)
9745
+ },
9746
+ next: {
9747
+ x: current.x + fb * (next.x - previous.x),
9748
+ y: current.y + fb * (next.y - previous.y)
9749
+ }
9750
+ };
9751
+ };
9752
+ helpers.EPSILON = Number.EPSILON || 1e-14;
9753
+ helpers.splineCurveMonotone = function(points) {
9754
+ // This function calculates Bézier control points in a similar way than |splineCurve|,
9755
+ // but preserves monotonicity of the provided data and ensures no local extremums are added
9756
+ // between the dataset discrete points due to the interpolation.
9757
+ // See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation
9758
+
9759
+ var pointsWithTangents = (points || []).map(function(point) {
9760
+ return {
9761
+ model: point._model,
9762
+ deltaK: 0,
9763
+ mK: 0
9764
+ };
9765
+ });
9766
+
9767
+ // Calculate slopes (deltaK) and initialize tangents (mK)
9768
+ var pointsLen = pointsWithTangents.length;
9769
+ var i, pointBefore, pointCurrent, pointAfter;
9770
+ for (i = 0; i < pointsLen; ++i) {
9771
+ pointCurrent = pointsWithTangents[i];
9772
+ if (pointCurrent.model.skip) {
9773
+ continue;
9774
+ }
9775
+
9776
+ pointBefore = i > 0 ? pointsWithTangents[i - 1] : null;
9777
+ pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null;
9778
+ if (pointAfter && !pointAfter.model.skip) {
9779
+ var slopeDeltaX = (pointAfter.model.x - pointCurrent.model.x);
9780
+
9781
+ // In the case of two points that appear at the same x pixel, slopeDeltaX is 0
9782
+ pointCurrent.deltaK = slopeDeltaX !== 0 ? (pointAfter.model.y - pointCurrent.model.y) / slopeDeltaX : 0;
9783
+ }
9784
+
9785
+ if (!pointBefore || pointBefore.model.skip) {
9786
+ pointCurrent.mK = pointCurrent.deltaK;
9787
+ } else if (!pointAfter || pointAfter.model.skip) {
9788
+ pointCurrent.mK = pointBefore.deltaK;
9789
+ } else if (this.sign(pointBefore.deltaK) !== this.sign(pointCurrent.deltaK)) {
9790
+ pointCurrent.mK = 0;
9791
+ } else {
9792
+ pointCurrent.mK = (pointBefore.deltaK + pointCurrent.deltaK) / 2;
9793
+ }
9794
+ }
9795
+
9796
+ // Adjust tangents to ensure monotonic properties
9797
+ var alphaK, betaK, tauK, squaredMagnitude;
9798
+ for (i = 0; i < pointsLen - 1; ++i) {
9799
+ pointCurrent = pointsWithTangents[i];
9800
+ pointAfter = pointsWithTangents[i + 1];
9801
+ if (pointCurrent.model.skip || pointAfter.model.skip) {
9802
+ continue;
9803
+ }
9804
+
9805
+ if (helpers.almostEquals(pointCurrent.deltaK, 0, this.EPSILON)) {
9806
+ pointCurrent.mK = pointAfter.mK = 0;
9807
+ continue;
9808
+ }
9809
+
9810
+ alphaK = pointCurrent.mK / pointCurrent.deltaK;
9811
+ betaK = pointAfter.mK / pointCurrent.deltaK;
9812
+ squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2);
9813
+ if (squaredMagnitude <= 9) {
9814
+ continue;
9815
+ }
9816
+
9817
+ tauK = 3 / Math.sqrt(squaredMagnitude);
9818
+ pointCurrent.mK = alphaK * tauK * pointCurrent.deltaK;
9819
+ pointAfter.mK = betaK * tauK * pointCurrent.deltaK;
9820
+ }
9821
+
9822
+ // Compute control points
9823
+ var deltaX;
9824
+ for (i = 0; i < pointsLen; ++i) {
9825
+ pointCurrent = pointsWithTangents[i];
9826
+ if (pointCurrent.model.skip) {
9827
+ continue;
9828
+ }
9829
+
9830
+ pointBefore = i > 0 ? pointsWithTangents[i - 1] : null;
9831
+ pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null;
9832
+ if (pointBefore && !pointBefore.model.skip) {
9833
+ deltaX = (pointCurrent.model.x - pointBefore.model.x) / 3;
9834
+ pointCurrent.model.controlPointPreviousX = pointCurrent.model.x - deltaX;
9835
+ pointCurrent.model.controlPointPreviousY = pointCurrent.model.y - deltaX * pointCurrent.mK;
9836
+ }
9837
+ if (pointAfter && !pointAfter.model.skip) {
9838
+ deltaX = (pointAfter.model.x - pointCurrent.model.x) / 3;
9839
+ pointCurrent.model.controlPointNextX = pointCurrent.model.x + deltaX;
9840
+ pointCurrent.model.controlPointNextY = pointCurrent.model.y + deltaX * pointCurrent.mK;
9841
+ }
9842
+ }
9843
+ };
9844
+ helpers.nextItem = function(collection, index, loop) {
9845
+ if (loop) {
9846
+ return index >= collection.length - 1 ? collection[0] : collection[index + 1];
9847
+ }
9848
+ return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1];
9849
+ };
9850
+ helpers.previousItem = function(collection, index, loop) {
9851
+ if (loop) {
9852
+ return index <= 0 ? collection[collection.length - 1] : collection[index - 1];
9853
+ }
9854
+ return index <= 0 ? collection[0] : collection[index - 1];
9855
+ };
9856
+ // Implementation of the nice number algorithm used in determining where axis labels will go
9857
+ helpers.niceNum = function(range, round) {
9858
+ var exponent = Math.floor(helpers.log10(range));
9859
+ var fraction = range / Math.pow(10, exponent);
9860
+ var niceFraction;
9861
+
9862
+ if (round) {
9863
+ if (fraction < 1.5) {
9864
+ niceFraction = 1;
9865
+ } else if (fraction < 3) {
9866
+ niceFraction = 2;
9867
+ } else if (fraction < 7) {
9868
+ niceFraction = 5;
9869
+ } else {
9870
+ niceFraction = 10;
9871
+ }
9872
+ } else if (fraction <= 1.0) {
9873
+ niceFraction = 1;
9874
+ } else if (fraction <= 2) {
9875
+ niceFraction = 2;
9876
+ } else if (fraction <= 5) {
9877
+ niceFraction = 5;
9878
+ } else {
9879
+ niceFraction = 10;
9880
+ }
9881
+
9882
+ return niceFraction * Math.pow(10, exponent);
9883
+ };
9884
+ // Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
9885
+ helpers.requestAnimFrame = (function() {
9886
+ if (typeof window === 'undefined') {
9887
+ return function(callback) {
9888
+ callback();
9889
+ };
9890
+ }
9891
+ return window.requestAnimationFrame ||
9892
+ window.webkitRequestAnimationFrame ||
9893
+ window.mozRequestAnimationFrame ||
9894
+ window.oRequestAnimationFrame ||
9895
+ window.msRequestAnimationFrame ||
9896
+ function(callback) {
9897
+ return window.setTimeout(callback, 1000 / 60);
9898
+ };
9899
+ }());
9900
+ // -- DOM methods
9901
+ helpers.getRelativePosition = function(evt, chart) {
9902
+ var mouseX, mouseY;
9903
+ var e = evt.originalEvent || evt;
9904
+ var canvas = evt.currentTarget || evt.srcElement;
9905
+ var boundingRect = canvas.getBoundingClientRect();
9906
+
9907
+ var touches = e.touches;
9908
+ if (touches && touches.length > 0) {
9909
+ mouseX = touches[0].clientX;
9910
+ mouseY = touches[0].clientY;
9911
+
9912
+ } else {
9913
+ mouseX = e.clientX;
9914
+ mouseY = e.clientY;
9915
+ }
9916
+
9917
+ // Scale mouse coordinates into canvas coordinates
9918
+ // by following the pattern laid out by 'jerryj' in the comments of
9919
+ // http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/
9920
+ var paddingLeft = parseFloat(helpers.getStyle(canvas, 'padding-left'));
9921
+ var paddingTop = parseFloat(helpers.getStyle(canvas, 'padding-top'));
9922
+ var paddingRight = parseFloat(helpers.getStyle(canvas, 'padding-right'));
9923
+ var paddingBottom = parseFloat(helpers.getStyle(canvas, 'padding-bottom'));
9924
+ var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight;
9925
+ var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom;
9926
+
9927
+ // We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However
9928
+ // the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here
9929
+ mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio);
9930
+ mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio);
9931
+
9932
+ return {
9933
+ x: mouseX,
9934
+ y: mouseY
9935
+ };
9936
+
9937
+ };
9938
+
9939
+ // Private helper function to convert max-width/max-height values that may be percentages into a number
9940
+ function parseMaxStyle(styleValue, node, parentProperty) {
9941
+ var valueInPixels;
9942
+ if (typeof styleValue === 'string') {
9943
+ valueInPixels = parseInt(styleValue, 10);
9944
+
9945
+ if (styleValue.indexOf('%') !== -1) {
9946
+ // percentage * size in dimension
9947
+ valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];
9948
+ }
9949
+ } else {
9950
+ valueInPixels = styleValue;
9951
+ }
9952
+
9953
+ return valueInPixels;
9954
+ }
9955
+
9956
+ /**
9957
+ * Returns if the given value contains an effective constraint.
9958
+ * @private
9959
+ */
9960
+ function isConstrainedValue(value) {
9961
+ return value !== undefined && value !== null && value !== 'none';
9962
+ }
9963
+
9964
+ // Private helper to get a constraint dimension
9965
+ // @param domNode : the node to check the constraint on
9966
+ // @param maxStyle : the style that defines the maximum for the direction we are using (maxWidth / maxHeight)
9967
+ // @param percentageProperty : property of parent to use when calculating width as a percentage
9968
+ // @see http://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser
9969
+ function getConstraintDimension(domNode, maxStyle, percentageProperty) {
9970
+ var view = document.defaultView;
9971
+ var parentNode = domNode.parentNode;
9972
+ var constrainedNode = view.getComputedStyle(domNode)[maxStyle];
9973
+ var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle];
9974
+ var hasCNode = isConstrainedValue(constrainedNode);
9975
+ var hasCContainer = isConstrainedValue(constrainedContainer);
9976
+ var infinity = Number.POSITIVE_INFINITY;
9977
+
9978
+ if (hasCNode || hasCContainer) {
9979
+ return Math.min(
9980
+ hasCNode ? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity,
9981
+ hasCContainer ? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity);
9982
+ }
9983
+
9984
+ return 'none';
9985
+ }
9986
+ // returns Number or undefined if no constraint
9987
+ helpers.getConstraintWidth = function(domNode) {
9988
+ return getConstraintDimension(domNode, 'max-width', 'clientWidth');
9989
+ };
9990
+ // returns Number or undefined if no constraint
9991
+ helpers.getConstraintHeight = function(domNode) {
9992
+ return getConstraintDimension(domNode, 'max-height', 'clientHeight');
9993
+ };
9994
+ helpers.getMaximumWidth = function(domNode) {
9995
+ var container = domNode.parentNode;
9996
+ if (!container) {
9997
+ return domNode.clientWidth;
9998
+ }
9999
+
10000
+ var paddingLeft = parseInt(helpers.getStyle(container, 'padding-left'), 10);
10001
+ var paddingRight = parseInt(helpers.getStyle(container, 'padding-right'), 10);
10002
+ var w = container.clientWidth - paddingLeft - paddingRight;
10003
+ var cw = helpers.getConstraintWidth(domNode);
10004
+ return isNaN(cw) ? w : Math.min(w, cw);
10005
+ };
10006
+ helpers.getMaximumHeight = function(domNode) {
10007
+ var container = domNode.parentNode;
10008
+ if (!container) {
10009
+ return domNode.clientHeight;
10010
+ }
10011
+
10012
+ var paddingTop = parseInt(helpers.getStyle(container, 'padding-top'), 10);
10013
+ var paddingBottom = parseInt(helpers.getStyle(container, 'padding-bottom'), 10);
10014
+ var h = container.clientHeight - paddingTop - paddingBottom;
10015
+ var ch = helpers.getConstraintHeight(domNode);
10016
+ return isNaN(ch) ? h : Math.min(h, ch);
10017
+ };
10018
+ helpers.getStyle = function(el, property) {
10019
+ return el.currentStyle ?
10020
+ el.currentStyle[property] :
10021
+ document.defaultView.getComputedStyle(el, null).getPropertyValue(property);
10022
+ };
10023
+ helpers.retinaScale = function(chart, forceRatio) {
10024
+ var pixelRatio = chart.currentDevicePixelRatio = forceRatio || window.devicePixelRatio || 1;
10025
+ if (pixelRatio === 1) {
10026
+ return;
10027
+ }
10028
+
10029
+ var canvas = chart.canvas;
10030
+ var height = chart.height;
10031
+ var width = chart.width;
10032
+
10033
+ canvas.height = height * pixelRatio;
10034
+ canvas.width = width * pixelRatio;
10035
+ chart.ctx.scale(pixelRatio, pixelRatio);
10036
+
10037
+ // If no style has been set on the canvas, the render size is used as display size,
10038
+ // making the chart visually bigger, so let's enforce it to the "correct" values.
10039
+ // See https://github.com/chartjs/Chart.js/issues/3575
10040
+ canvas.style.height = height + 'px';
10041
+ canvas.style.width = width + 'px';
10042
+ };
10043
+ // -- Canvas methods
10044
+ helpers.fontString = function(pixelSize, fontStyle, fontFamily) {
10045
+ return fontStyle + ' ' + pixelSize + 'px ' + fontFamily;
10046
+ };
10047
+ helpers.longestText = function(ctx, font, arrayOfThings, cache) {
10048
+ cache = cache || {};
10049
+ var data = cache.data = cache.data || {};
10050
+ var gc = cache.garbageCollect = cache.garbageCollect || [];
10051
+
10052
+ if (cache.font !== font) {
10053
+ data = cache.data = {};
10054
+ gc = cache.garbageCollect = [];
10055
+ cache.font = font;
10056
+ }
10057
+
10058
+ ctx.font = font;
10059
+ var longest = 0;
10060
+ helpers.each(arrayOfThings, function(thing) {
10061
+ // Undefined strings and arrays should not be measured
10062
+ if (thing !== undefined && thing !== null && helpers.isArray(thing) !== true) {
10063
+ longest = helpers.measureText(ctx, data, gc, longest, thing);
10064
+ } else if (helpers.isArray(thing)) {
10065
+ // if it is an array lets measure each element
10066
+ // to do maybe simplify this function a bit so we can do this more recursively?
10067
+ helpers.each(thing, function(nestedThing) {
10068
+ // Undefined strings and arrays should not be measured
10069
+ if (nestedThing !== undefined && nestedThing !== null && !helpers.isArray(nestedThing)) {
10070
+ longest = helpers.measureText(ctx, data, gc, longest, nestedThing);
10071
+ }
10072
+ });
10073
+ }
10074
+ });
10075
+
10076
+ var gcLen = gc.length / 2;
10077
+ if (gcLen > arrayOfThings.length) {
10078
+ for (var i = 0; i < gcLen; i++) {
10079
+ delete data[gc[i]];
10080
+ }
10081
+ gc.splice(0, gcLen);
10082
+ }
10083
+ return longest;
10084
+ };
10085
+ helpers.measureText = function(ctx, data, gc, longest, string) {
10086
+ var textWidth = data[string];
10087
+ if (!textWidth) {
10088
+ textWidth = data[string] = ctx.measureText(string).width;
10089
+ gc.push(string);
10090
+ }
10091
+ if (textWidth > longest) {
10092
+ longest = textWidth;
10093
+ }
10094
+ return longest;
10095
+ };
10096
+ helpers.numberOfLabelLines = function(arrayOfThings) {
10097
+ var numberOfLines = 1;
10098
+ helpers.each(arrayOfThings, function(thing) {
10099
+ if (helpers.isArray(thing)) {
10100
+ if (thing.length > numberOfLines) {
10101
+ numberOfLines = thing.length;
10102
+ }
10103
+ }
10104
+ });
10105
+ return numberOfLines;
10106
+ };
10107
+
10108
+ helpers.color = !color ?
10109
+ function(value) {
10110
+ console.error('Color.js not found!');
10111
+ return value;
10112
+ } :
10113
+ function(value) {
10114
+ /* global CanvasGradient */
10115
+ if (value instanceof CanvasGradient) {
10116
+ value = defaults.global.defaultColor;
10117
+ }
10118
+
10119
+ return color(value);
10120
+ };
10121
+
10122
+ helpers.getHoverColor = function(colorValue) {
10123
+ /* global CanvasPattern */
10124
+ return (colorValue instanceof CanvasPattern) ?
10125
+ colorValue :
10126
+ helpers.color(colorValue).saturate(0.5).darken(0.1).rgbString();
10127
+ };
10128
+ };
10129
+
10130
+ },{"2":2,"25":25,"45":45}],28:[function(require,module,exports){
10131
+ 'use strict';
10132
+
10133
+ var helpers = require(45);
10134
+
10135
+ /**
10136
+ * Helper function to get relative position for an event
10137
+ * @param {Event|IEvent} event - The event to get the position for
10138
+ * @param {Chart} chart - The chart
10139
+ * @returns {Point} the event position
10140
+ */
10141
+ function getRelativePosition(e, chart) {
10142
+ if (e.native) {
10143
+ return {
10144
+ x: e.x,
10145
+ y: e.y
10146
+ };
10147
+ }
10148
+
10149
+ return helpers.getRelativePosition(e, chart);
10150
+ }
10151
+
10152
+ /**
10153
+ * Helper function to traverse all of the visible elements in the chart
10154
+ * @param chart {chart} the chart
10155
+ * @param handler {Function} the callback to execute for each visible item
10156
+ */
10157
+ function parseVisibleItems(chart, handler) {
10158
+ var datasets = chart.data.datasets;
10159
+ var meta, i, j, ilen, jlen;
10160
+
10161
+ for (i = 0, ilen = datasets.length; i < ilen; ++i) {
10162
+ if (!chart.isDatasetVisible(i)) {
10163
+ continue;
10164
+ }
10165
+
10166
+ meta = chart.getDatasetMeta(i);
10167
+ for (j = 0, jlen = meta.data.length; j < jlen; ++j) {
10168
+ var element = meta.data[j];
10169
+ if (!element._view.skip) {
10170
+ handler(element);
10171
+ }
10172
+ }
10173
+ }
10174
+ }
10175
+
10176
+ /**
10177
+ * Helper function to get the items that intersect the event position
10178
+ * @param items {ChartElement[]} elements to filter
10179
+ * @param position {Point} the point to be nearest to
10180
+ * @return {ChartElement[]} the nearest items
10181
+ */
10182
+ function getIntersectItems(chart, position) {
10183
+ var elements = [];
10184
+
10185
+ parseVisibleItems(chart, function(element) {
10186
+ if (element.inRange(position.x, position.y)) {
10187
+ elements.push(element);
10188
+ }
10189
+ });
10190
+
10191
+ return elements;
10192
+ }
10193
+
10194
+ /**
10195
+ * Helper function to get the items nearest to the event position considering all visible items in teh chart
10196
+ * @param chart {Chart} the chart to look at elements from
10197
+ * @param position {Point} the point to be nearest to
10198
+ * @param intersect {Boolean} if true, only consider items that intersect the position
10199
+ * @param distanceMetric {Function} function to provide the distance between points
10200
+ * @return {ChartElement[]} the nearest items
10201
+ */
10202
+ function getNearestItems(chart, position, intersect, distanceMetric) {
10203
+ var minDistance = Number.POSITIVE_INFINITY;
10204
+ var nearestItems = [];
10205
+
10206
+ parseVisibleItems(chart, function(element) {
10207
+ if (intersect && !element.inRange(position.x, position.y)) {
10208
+ return;
10209
+ }
10210
+
10211
+ var center = element.getCenterPoint();
10212
+ var distance = distanceMetric(position, center);
10213
+
10214
+ if (distance < minDistance) {
10215
+ nearestItems = [element];
10216
+ minDistance = distance;
10217
+ } else if (distance === minDistance) {
10218
+ // Can have multiple items at the same distance in which case we sort by size
10219
+ nearestItems.push(element);
10220
+ }
10221
+ });
10222
+
10223
+ return nearestItems;
10224
+ }
10225
+
10226
+ /**
10227
+ * Get a distance metric function for two points based on the
10228
+ * axis mode setting
10229
+ * @param {String} axis the axis mode. x|y|xy
10230
+ */
10231
+ function getDistanceMetricForAxis(axis) {
10232
+ var useX = axis.indexOf('x') !== -1;
10233
+ var useY = axis.indexOf('y') !== -1;
10234
+
10235
+ return function(pt1, pt2) {
10236
+ var deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0;
10237
+ var deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0;
10238
+ return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
10239
+ };
10240
+ }
10241
+
10242
+ function indexMode(chart, e, options) {
10243
+ var position = getRelativePosition(e, chart);
10244
+ // Default axis for index mode is 'x' to match old behaviour
10245
+ options.axis = options.axis || 'x';
10246
+ var distanceMetric = getDistanceMetricForAxis(options.axis);
10247
+ var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);
10248
+ var elements = [];
10249
+
10250
+ if (!items.length) {
10251
+ return [];
10252
+ }
10253
+
10254
+ chart.data.datasets.forEach(function(dataset, datasetIndex) {
10255
+ if (chart.isDatasetVisible(datasetIndex)) {
10256
+ var meta = chart.getDatasetMeta(datasetIndex);
10257
+ var element = meta.data[items[0]._index];
10258
+
10259
+ // don't count items that are skipped (null data)
10260
+ if (element && !element._view.skip) {
10261
+ elements.push(element);
10262
+ }
10263
+ }
10264
+ });
10265
+
10266
+ return elements;
10267
+ }
10268
+
10269
+ /**
10270
+ * @interface IInteractionOptions
10271
+ */
10272
+ /**
10273
+ * If true, only consider items that intersect the point
10274
+ * @name IInterfaceOptions#boolean
10275
+ * @type Boolean
10276
+ */
10277
+
10278
+ /**
10279
+ * Contains interaction related functions
10280
+ * @namespace Chart.Interaction
10281
+ */
10282
+ module.exports = {
10283
+ // Helper function for different modes
10284
+ modes: {
10285
+ single: function(chart, e) {
10286
+ var position = getRelativePosition(e, chart);
10287
+ var elements = [];
10288
+
10289
+ parseVisibleItems(chart, function(element) {
10290
+ if (element.inRange(position.x, position.y)) {
10291
+ elements.push(element);
10292
+ return elements;
10293
+ }
10294
+ });
10295
+
10296
+ return elements.slice(0, 1);
10297
+ },
10298
+
10299
+ /**
10300
+ * @function Chart.Interaction.modes.label
10301
+ * @deprecated since version 2.4.0
10302
+ * @todo remove at version 3
10303
+ * @private
10304
+ */
10305
+ label: indexMode,
10306
+
10307
+ /**
10308
+ * Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something
10309
+ * If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item
10310
+ * @function Chart.Interaction.modes.index
10311
+ * @since v2.4.0
10312
+ * @param chart {chart} the chart we are returning items from
10313
+ * @param e {Event} the event we are find things at
10314
+ * @param options {IInteractionOptions} options to use during interaction
10315
+ * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
10316
+ */
10317
+ index: indexMode,
10318
+
10319
+ /**
10320
+ * Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something
10321
+ * If the options.intersect is false, we find the nearest item and return the items in that dataset
10322
+ * @function Chart.Interaction.modes.dataset
10323
+ * @param chart {chart} the chart we are returning items from
10324
+ * @param e {Event} the event we are find things at
10325
+ * @param options {IInteractionOptions} options to use during interaction
10326
+ * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
10327
+ */
10328
+ dataset: function(chart, e, options) {
10329
+ var position = getRelativePosition(e, chart);
10330
+ options.axis = options.axis || 'xy';
10331
+ var distanceMetric = getDistanceMetricForAxis(options.axis);
10332
+ var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);
10333
+
10334
+ if (items.length > 0) {
10335
+ items = chart.getDatasetMeta(items[0]._datasetIndex).data;
10336
+ }
10337
+
10338
+ return items;
10339
+ },
10340
+
10341
+ /**
10342
+ * @function Chart.Interaction.modes.x-axis
10343
+ * @deprecated since version 2.4.0. Use index mode and intersect == true
10344
+ * @todo remove at version 3
10345
+ * @private
10346
+ */
10347
+ 'x-axis': function(chart, e) {
10348
+ return indexMode(chart, e, {intersect: true});
10349
+ },
10350
+
10351
+ /**
10352
+ * Point mode returns all elements that hit test based on the event position
10353
+ * of the event
10354
+ * @function Chart.Interaction.modes.intersect
10355
+ * @param chart {chart} the chart we are returning items from
10356
+ * @param e {Event} the event we are find things at
10357
+ * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
10358
+ */
10359
+ point: function(chart, e) {
10360
+ var position = getRelativePosition(e, chart);
10361
+ return getIntersectItems(chart, position);
10362
+ },
10363
+
10364
+ /**
10365
+ * nearest mode returns the element closest to the point
10366
+ * @function Chart.Interaction.modes.intersect
10367
+ * @param chart {chart} the chart we are returning items from
10368
+ * @param e {Event} the event we are find things at
10369
+ * @param options {IInteractionOptions} options to use
10370
+ * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
10371
+ */
10372
+ nearest: function(chart, e, options) {
10373
+ var position = getRelativePosition(e, chart);
10374
+ options.axis = options.axis || 'xy';
10375
+ var distanceMetric = getDistanceMetricForAxis(options.axis);
10376
+ var nearestItems = getNearestItems(chart, position, options.intersect, distanceMetric);
10377
+
10378
+ // We have multiple items at the same distance from the event. Now sort by smallest
10379
+ if (nearestItems.length > 1) {
10380
+ nearestItems.sort(function(a, b) {
10381
+ var sizeA = a.getArea();
10382
+ var sizeB = b.getArea();
10383
+ var ret = sizeA - sizeB;
10384
+
10385
+ if (ret === 0) {
10386
+ // if equal sort by dataset index
10387
+ ret = a._datasetIndex - b._datasetIndex;
10388
+ }
10389
+
10390
+ return ret;
10391
+ });
10392
+ }
10393
+
10394
+ // Return only 1 item
10395
+ return nearestItems.slice(0, 1);
10396
+ },
10397
+
10398
+ /**
10399
+ * x mode returns the elements that hit-test at the current x coordinate
10400
+ * @function Chart.Interaction.modes.x
10401
+ * @param chart {chart} the chart we are returning items from
10402
+ * @param e {Event} the event we are find things at
10403
+ * @param options {IInteractionOptions} options to use
10404
+ * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
10405
+ */
10406
+ x: function(chart, e, options) {
10407
+ var position = getRelativePosition(e, chart);
10408
+ var items = [];
10409
+ var intersectsItem = false;
10410
+
10411
+ parseVisibleItems(chart, function(element) {
10412
+ if (element.inXRange(position.x)) {
10413
+ items.push(element);
10414
+ }
10415
+
10416
+ if (element.inRange(position.x, position.y)) {
10417
+ intersectsItem = true;
10418
+ }
10419
+ });
10420
+
10421
+ // If we want to trigger on an intersect and we don't have any items
10422
+ // that intersect the position, return nothing
10423
+ if (options.intersect && !intersectsItem) {
10424
+ items = [];
10425
+ }
10426
+ return items;
10427
+ },
10428
+
10429
+ /**
10430
+ * y mode returns the elements that hit-test at the current y coordinate
10431
+ * @function Chart.Interaction.modes.y
10432
+ * @param chart {chart} the chart we are returning items from
10433
+ * @param e {Event} the event we are find things at
10434
+ * @param options {IInteractionOptions} options to use
10435
+ * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
10436
+ */
10437
+ y: function(chart, e, options) {
10438
+ var position = getRelativePosition(e, chart);
10439
+ var items = [];
10440
+ var intersectsItem = false;
10441
+
10442
+ parseVisibleItems(chart, function(element) {
10443
+ if (element.inYRange(position.y)) {
10444
+ items.push(element);
10445
+ }
10446
+
10447
+ if (element.inRange(position.x, position.y)) {
10448
+ intersectsItem = true;
10449
+ }
10450
+ });
10451
+
10452
+ // If we want to trigger on an intersect and we don't have any items
10453
+ // that intersect the position, return nothing
10454
+ if (options.intersect && !intersectsItem) {
10455
+ items = [];
10456
+ }
10457
+ return items;
10458
+ }
10459
+ }
10460
+ };
10461
+
10462
+ },{"45":45}],29:[function(require,module,exports){
10463
+ 'use strict';
10464
+
10465
+ var defaults = require(25);
10466
+
10467
+ defaults._set('global', {
10468
+ responsive: true,
10469
+ responsiveAnimationDuration: 0,
10470
+ maintainAspectRatio: true,
10471
+ events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
10472
+ hover: {
10473
+ onHover: null,
10474
+ mode: 'nearest',
10475
+ intersect: true,
10476
+ animationDuration: 400
10477
+ },
10478
+ onClick: null,
10479
+ defaultColor: 'rgba(0,0,0,0.1)',
10480
+ defaultFontColor: '#666',
10481
+ defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
10482
+ defaultFontSize: 12,
10483
+ defaultFontStyle: 'normal',
10484
+ showLines: true,
10485
+
10486
+ // Element defaults defined in element extensions
10487
+ elements: {},
10488
+
10489
+ // Layout options such as padding
10490
+ layout: {
10491
+ padding: {
10492
+ top: 0,
10493
+ right: 0,
10494
+ bottom: 0,
10495
+ left: 0
10496
+ }
10497
+ }
10498
+ });
10499
+
10500
+ module.exports = function() {
10501
+
10502
+ // Occupy the global variable of Chart, and create a simple base class
10503
+ var Chart = function(item, config) {
10504
+ this.construct(item, config);
10505
+ return this;
10506
+ };
10507
+
10508
+ Chart.Chart = Chart;
10509
+
10510
+ return Chart;
10511
+ };
10512
+
10513
+ },{"25":25}],30:[function(require,module,exports){
10514
+ 'use strict';
10515
+
10516
+ var helpers = require(45);
10517
+
10518
+ module.exports = function(Chart) {
10519
+
10520
+ function filterByPosition(array, position) {
10521
+ return helpers.where(array, function(v) {
10522
+ return v.position === position;
10523
+ });
10524
+ }
10525
+
10526
+ function sortByWeight(array, reverse) {
10527
+ array.forEach(function(v, i) {
10528
+ v._tmpIndex_ = i;
10529
+ return v;
10530
+ });
10531
+ array.sort(function(a, b) {
10532
+ var v0 = reverse ? b : a;
10533
+ var v1 = reverse ? a : b;
10534
+ return v0.weight === v1.weight ?
10535
+ v0._tmpIndex_ - v1._tmpIndex_ :
10536
+ v0.weight - v1.weight;
10537
+ });
10538
+ array.forEach(function(v) {
10539
+ delete v._tmpIndex_;
10540
+ });
10541
+ }
10542
+
10543
+ /**
10544
+ * @interface ILayoutItem
10545
+ * @prop {String} position - The position of the item in the chart layout. Possible values are
10546
+ * 'left', 'top', 'right', 'bottom', and 'chartArea'
10547
+ * @prop {Number} weight - The weight used to sort the item. Higher weights are further away from the chart area
10548
+ * @prop {Boolean} fullWidth - if true, and the item is horizontal, then push vertical boxes down
10549
+ * @prop {Function} isHorizontal - returns true if the layout item is horizontal (ie. top or bottom)
10550
+ * @prop {Function} update - Takes two parameters: width and height. Returns size of item
10551
+ * @prop {Function} getPadding - Returns an object with padding on the edges
10552
+ * @prop {Number} width - Width of item. Must be valid after update()
10553
+ * @prop {Number} height - Height of item. Must be valid after update()
10554
+ * @prop {Number} left - Left edge of the item. Set by layout system and cannot be used in update
10555
+ * @prop {Number} top - Top edge of the item. Set by layout system and cannot be used in update
10556
+ * @prop {Number} right - Right edge of the item. Set by layout system and cannot be used in update
10557
+ * @prop {Number} bottom - Bottom edge of the item. Set by layout system and cannot be used in update
10558
+ */
10559
+
10560
+ // The layout service is very self explanatory. It's responsible for the layout within a chart.
10561
+ // Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need
10562
+ // It is this service's responsibility of carrying out that layout.
10563
+ Chart.layoutService = {
10564
+ defaults: {},
10565
+
10566
+ /**
10567
+ * Register a box to a chart.
10568
+ * A box is simply a reference to an object that requires layout. eg. Scales, Legend, Title.
10569
+ * @param {Chart} chart - the chart to use
10570
+ * @param {ILayoutItem} item - the item to add to be layed out
10571
+ */
10572
+ addBox: function(chart, item) {
10573
+ if (!chart.boxes) {
10574
+ chart.boxes = [];
10575
+ }
10576
+
10577
+ // initialize item with default values
10578
+ item.fullWidth = item.fullWidth || false;
10579
+ item.position = item.position || 'top';
10580
+ item.weight = item.weight || 0;
10581
+
10582
+ chart.boxes.push(item);
10583
+ },
10584
+
10585
+ /**
10586
+ * Remove a layoutItem from a chart
10587
+ * @param {Chart} chart - the chart to remove the box from
10588
+ * @param {Object} layoutItem - the item to remove from the layout
10589
+ */
10590
+ removeBox: function(chart, layoutItem) {
10591
+ var index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1;
10592
+ if (index !== -1) {
10593
+ chart.boxes.splice(index, 1);
10594
+ }
10595
+ },
10596
+
10597
+ /**
10598
+ * Sets (or updates) options on the given `item`.
10599
+ * @param {Chart} chart - the chart in which the item lives (or will be added to)
10600
+ * @param {Object} item - the item to configure with the given options
10601
+ * @param {Object} options - the new item options.
10602
+ */
10603
+ configure: function(chart, item, options) {
10604
+ var props = ['fullWidth', 'position', 'weight'];
10605
+ var ilen = props.length;
10606
+ var i = 0;
10607
+ var prop;
10608
+
10609
+ for (; i < ilen; ++i) {
10610
+ prop = props[i];
10611
+ if (options.hasOwnProperty(prop)) {
10612
+ item[prop] = options[prop];
10613
+ }
10614
+ }
10615
+ },
10616
+
10617
+ /**
10618
+ * Fits boxes of the given chart into the given size by having each box measure itself
10619
+ * then running a fitting algorithm
10620
+ * @param {Chart} chart - the chart
10621
+ * @param {Number} width - the width to fit into
10622
+ * @param {Number} height - the height to fit into
10623
+ */
10624
+ update: function(chart, width, height) {
10625
+ if (!chart) {
10626
+ return;
10627
+ }
10628
+
10629
+ var layoutOptions = chart.options.layout || {};
10630
+ var padding = helpers.options.toPadding(layoutOptions.padding);
10631
+ var leftPadding = padding.left;
10632
+ var rightPadding = padding.right;
10633
+ var topPadding = padding.top;
10634
+ var bottomPadding = padding.bottom;
10635
+
10636
+ var leftBoxes = filterByPosition(chart.boxes, 'left');
10637
+ var rightBoxes = filterByPosition(chart.boxes, 'right');
10638
+ var topBoxes = filterByPosition(chart.boxes, 'top');
10639
+ var bottomBoxes = filterByPosition(chart.boxes, 'bottom');
10640
+ var chartAreaBoxes = filterByPosition(chart.boxes, 'chartArea');
10641
+
10642
+ // Sort boxes by weight. A higher weight is further away from the chart area
10643
+ sortByWeight(leftBoxes, true);
10644
+ sortByWeight(rightBoxes, false);
10645
+ sortByWeight(topBoxes, true);
10646
+ sortByWeight(bottomBoxes, false);
10647
+
10648
+ // Essentially we now have any number of boxes on each of the 4 sides.
10649
+ // Our canvas looks like the following.
10650
+ // The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and
10651
+ // B1 is the bottom axis
10652
+ // There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays
10653
+ // These locations are single-box locations only, when trying to register a chartArea location that is already taken,
10654
+ // an error will be thrown.
10655
+ //
10656
+ // |----------------------------------------------------|
10657
+ // | T1 (Full Width) |
10658
+ // |----------------------------------------------------|
10659
+ // | | | T2 | |
10660
+ // | |----|-------------------------------------|----|
10661
+ // | | | C1 | | C2 | |
10662
+ // | | |----| |----| |
10663
+ // | | | | |
10664
+ // | L1 | L2 | ChartArea (C0) | R1 |
10665
+ // | | | | |
10666
+ // | | |----| |----| |
10667
+ // | | | C3 | | C4 | |
10668
+ // | |----|-------------------------------------|----|
10669
+ // | | | B1 | |
10670
+ // |----------------------------------------------------|
10671
+ // | B2 (Full Width) |
10672
+ // |----------------------------------------------------|
10673
+ //
10674
+ // What we do to find the best sizing, we do the following
10675
+ // 1. Determine the minimum size of the chart area.
10676
+ // 2. Split the remaining width equally between each vertical axis
10677
+ // 3. Split the remaining height equally between each horizontal axis
10678
+ // 4. Give each layout the maximum size it can be. The layout will return it's minimum size
10679
+ // 5. Adjust the sizes of each axis based on it's minimum reported size.
10680
+ // 6. Refit each axis
10681
+ // 7. Position each axis in the final location
10682
+ // 8. Tell the chart the final location of the chart area
10683
+ // 9. Tell any axes that overlay the chart area the positions of the chart area
10684
+
10685
+ // Step 1
10686
+ var chartWidth = width - leftPadding - rightPadding;
10687
+ var chartHeight = height - topPadding - bottomPadding;
10688
+ var chartAreaWidth = chartWidth / 2; // min 50%
10689
+ var chartAreaHeight = chartHeight / 2; // min 50%
10690
+
10691
+ // Step 2
10692
+ var verticalBoxWidth = (width - chartAreaWidth) / (leftBoxes.length + rightBoxes.length);
10693
+
10694
+ // Step 3
10695
+ var horizontalBoxHeight = (height - chartAreaHeight) / (topBoxes.length + bottomBoxes.length);
10696
+
10697
+ // Step 4
10698
+ var maxChartAreaWidth = chartWidth;
10699
+ var maxChartAreaHeight = chartHeight;
10700
+ var minBoxSizes = [];
10701
+
10702
+ function getMinimumBoxSize(box) {
10703
+ var minSize;
10704
+ var isHorizontal = box.isHorizontal();
10705
+
10706
+ if (isHorizontal) {
10707
+ minSize = box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, horizontalBoxHeight);
10708
+ maxChartAreaHeight -= minSize.height;
10709
+ } else {
10710
+ minSize = box.update(verticalBoxWidth, chartAreaHeight);
10711
+ maxChartAreaWidth -= minSize.width;
10712
+ }
10713
+
10714
+ minBoxSizes.push({
10715
+ horizontal: isHorizontal,
10716
+ minSize: minSize,
10717
+ box: box,
10718
+ });
10719
+ }
10720
+
10721
+ helpers.each(leftBoxes.concat(rightBoxes, topBoxes, bottomBoxes), getMinimumBoxSize);
10722
+
10723
+ // If a horizontal box has padding, we move the left boxes over to avoid ugly charts (see issue #2478)
10724
+ var maxHorizontalLeftPadding = 0;
10725
+ var maxHorizontalRightPadding = 0;
10726
+ var maxVerticalTopPadding = 0;
10727
+ var maxVerticalBottomPadding = 0;
10728
+
10729
+ helpers.each(topBoxes.concat(bottomBoxes), function(horizontalBox) {
10730
+ if (horizontalBox.getPadding) {
10731
+ var boxPadding = horizontalBox.getPadding();
10732
+ maxHorizontalLeftPadding = Math.max(maxHorizontalLeftPadding, boxPadding.left);
10733
+ maxHorizontalRightPadding = Math.max(maxHorizontalRightPadding, boxPadding.right);
10734
+ }
10735
+ });
10736
+
10737
+ helpers.each(leftBoxes.concat(rightBoxes), function(verticalBox) {
10738
+ if (verticalBox.getPadding) {
10739
+ var boxPadding = verticalBox.getPadding();
10740
+ maxVerticalTopPadding = Math.max(maxVerticalTopPadding, boxPadding.top);
10741
+ maxVerticalBottomPadding = Math.max(maxVerticalBottomPadding, boxPadding.bottom);
10742
+ }
10743
+ });
10744
+
10745
+ // At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could
10746
+ // be if the axes are drawn at their minimum sizes.
10747
+ // Steps 5 & 6
10748
+ var totalLeftBoxesWidth = leftPadding;
10749
+ var totalRightBoxesWidth = rightPadding;
10750
+ var totalTopBoxesHeight = topPadding;
10751
+ var totalBottomBoxesHeight = bottomPadding;
10752
+
10753
+ // Function to fit a box
10754
+ function fitBox(box) {
10755
+ var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBox) {
10756
+ return minBox.box === box;
10757
+ });
10758
+
10759
+ if (minBoxSize) {
10760
+ if (box.isHorizontal()) {
10761
+ var scaleMargin = {
10762
+ left: Math.max(totalLeftBoxesWidth, maxHorizontalLeftPadding),
10763
+ right: Math.max(totalRightBoxesWidth, maxHorizontalRightPadding),
10764
+ top: 0,
10765
+ bottom: 0
10766
+ };
10767
+
10768
+ // Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends
10769
+ // on the margin. Sometimes they need to increase in size slightly
10770
+ box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin);
10771
+ } else {
10772
+ box.update(minBoxSize.minSize.width, maxChartAreaHeight);
10773
+ }
10774
+ }
10775
+ }
10776
+
10777
+ // Update, and calculate the left and right margins for the horizontal boxes
10778
+ helpers.each(leftBoxes.concat(rightBoxes), fitBox);
10779
+
10780
+ helpers.each(leftBoxes, function(box) {
10781
+ totalLeftBoxesWidth += box.width;
10782
+ });
10783
+
10784
+ helpers.each(rightBoxes, function(box) {
10785
+ totalRightBoxesWidth += box.width;
10786
+ });
10787
+
10788
+ // Set the Left and Right margins for the horizontal boxes
10789
+ helpers.each(topBoxes.concat(bottomBoxes), fitBox);
10790
+
10791
+ // Figure out how much margin is on the top and bottom of the vertical boxes
10792
+ helpers.each(topBoxes, function(box) {
10793
+ totalTopBoxesHeight += box.height;
10794
+ });
10795
+
10796
+ helpers.each(bottomBoxes, function(box) {
10797
+ totalBottomBoxesHeight += box.height;
10798
+ });
10799
+
10800
+ function finalFitVerticalBox(box) {
10801
+ var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minSize) {
10802
+ return minSize.box === box;
10803
+ });
10804
+
10805
+ var scaleMargin = {
10806
+ left: 0,
10807
+ right: 0,
10808
+ top: totalTopBoxesHeight,
10809
+ bottom: totalBottomBoxesHeight
10810
+ };
10811
+
10812
+ if (minBoxSize) {
10813
+ box.update(minBoxSize.minSize.width, maxChartAreaHeight, scaleMargin);
10814
+ }
10815
+ }
10816
+
10817
+ // Let the left layout know the final margin
10818
+ helpers.each(leftBoxes.concat(rightBoxes), finalFitVerticalBox);
10819
+
10820
+ // Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance)
10821
+ totalLeftBoxesWidth = leftPadding;
10822
+ totalRightBoxesWidth = rightPadding;
10823
+ totalTopBoxesHeight = topPadding;
10824
+ totalBottomBoxesHeight = bottomPadding;
10825
+
10826
+ helpers.each(leftBoxes, function(box) {
10827
+ totalLeftBoxesWidth += box.width;
10828
+ });
10829
+
10830
+ helpers.each(rightBoxes, function(box) {
10831
+ totalRightBoxesWidth += box.width;
10832
+ });
10833
+
10834
+ helpers.each(topBoxes, function(box) {
10835
+ totalTopBoxesHeight += box.height;
10836
+ });
10837
+ helpers.each(bottomBoxes, function(box) {
10838
+ totalBottomBoxesHeight += box.height;
10839
+ });
10840
+
10841
+ // We may be adding some padding to account for rotated x axis labels
10842
+ var leftPaddingAddition = Math.max(maxHorizontalLeftPadding - totalLeftBoxesWidth, 0);
10843
+ totalLeftBoxesWidth += leftPaddingAddition;
10844
+ totalRightBoxesWidth += Math.max(maxHorizontalRightPadding - totalRightBoxesWidth, 0);
10845
+
10846
+ var topPaddingAddition = Math.max(maxVerticalTopPadding - totalTopBoxesHeight, 0);
10847
+ totalTopBoxesHeight += topPaddingAddition;
10848
+ totalBottomBoxesHeight += Math.max(maxVerticalBottomPadding - totalBottomBoxesHeight, 0);
10849
+
10850
+ // Figure out if our chart area changed. This would occur if the dataset layout label rotation
10851
+ // changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do
10852
+ // without calling `fit` again
10853
+ var newMaxChartAreaHeight = height - totalTopBoxesHeight - totalBottomBoxesHeight;
10854
+ var newMaxChartAreaWidth = width - totalLeftBoxesWidth - totalRightBoxesWidth;
10855
+
10856
+ if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) {
10857
+ helpers.each(leftBoxes, function(box) {
10858
+ box.height = newMaxChartAreaHeight;
10859
+ });
10860
+
10861
+ helpers.each(rightBoxes, function(box) {
10862
+ box.height = newMaxChartAreaHeight;
10863
+ });
10864
+
10865
+ helpers.each(topBoxes, function(box) {
10866
+ if (!box.fullWidth) {
10867
+ box.width = newMaxChartAreaWidth;
10868
+ }
10869
+ });
10870
+
10871
+ helpers.each(bottomBoxes, function(box) {
10872
+ if (!box.fullWidth) {
10873
+ box.width = newMaxChartAreaWidth;
10874
+ }
10875
+ });
10876
+
10877
+ maxChartAreaHeight = newMaxChartAreaHeight;
10878
+ maxChartAreaWidth = newMaxChartAreaWidth;
10879
+ }
10880
+
10881
+ // Step 7 - Position the boxes
10882
+ var left = leftPadding + leftPaddingAddition;
10883
+ var top = topPadding + topPaddingAddition;
10884
+
10885
+ function placeBox(box) {
10886
+ if (box.isHorizontal()) {
10887
+ box.left = box.fullWidth ? leftPadding : totalLeftBoxesWidth;
10888
+ box.right = box.fullWidth ? width - rightPadding : totalLeftBoxesWidth + maxChartAreaWidth;
10889
+ box.top = top;
10890
+ box.bottom = top + box.height;
10891
+
10892
+ // Move to next point
10893
+ top = box.bottom;
10894
+
10895
+ } else {
10896
+
10897
+ box.left = left;
10898
+ box.right = left + box.width;
10899
+ box.top = totalTopBoxesHeight;
10900
+ box.bottom = totalTopBoxesHeight + maxChartAreaHeight;
10901
+
10902
+ // Move to next point
10903
+ left = box.right;
10904
+ }
10905
+ }
10906
+
10907
+ helpers.each(leftBoxes.concat(topBoxes), placeBox);
10908
+
10909
+ // Account for chart width and height
10910
+ left += maxChartAreaWidth;
10911
+ top += maxChartAreaHeight;
10912
+
10913
+ helpers.each(rightBoxes, placeBox);
10914
+ helpers.each(bottomBoxes, placeBox);
10915
+
10916
+ // Step 8
10917
+ chart.chartArea = {
10918
+ left: totalLeftBoxesWidth,
10919
+ top: totalTopBoxesHeight,
10920
+ right: totalLeftBoxesWidth + maxChartAreaWidth,
10921
+ bottom: totalTopBoxesHeight + maxChartAreaHeight
10922
+ };
10923
+
10924
+ // Step 9
10925
+ helpers.each(chartAreaBoxes, function(box) {
10926
+ box.left = chart.chartArea.left;
10927
+ box.top = chart.chartArea.top;
10928
+ box.right = chart.chartArea.right;
10929
+ box.bottom = chart.chartArea.bottom;
10930
+
10931
+ box.update(maxChartAreaWidth, maxChartAreaHeight);
10932
+ });
10933
+ }
10934
+ };
10935
+ };
10936
+
10937
+ },{"45":45}],31:[function(require,module,exports){
10938
+ 'use strict';
10939
+
10940
+ var defaults = require(25);
10941
+ var Element = require(26);
10942
+ var helpers = require(45);
10943
+
10944
+ defaults._set('global', {
10945
+ plugins: {}
10946
+ });
10947
+
10948
+ module.exports = function(Chart) {
10949
+
10950
+ /**
10951
+ * The plugin service singleton
10952
+ * @namespace Chart.plugins
10953
+ * @since 2.1.0
10954
+ */
10955
+ Chart.plugins = {
10956
+ /**
10957
+ * Globally registered plugins.
10958
+ * @private
10959
+ */
10960
+ _plugins: [],
10961
+
10962
+ /**
10963
+ * This identifier is used to invalidate the descriptors cache attached to each chart
10964
+ * when a global plugin is registered or unregistered. In this case, the cache ID is
10965
+ * incremented and descriptors are regenerated during following API calls.
10966
+ * @private
10967
+ */
10968
+ _cacheId: 0,
10969
+
10970
+ /**
10971
+ * Registers the given plugin(s) if not already registered.
10972
+ * @param {Array|Object} plugins plugin instance(s).
10973
+ */
10974
+ register: function(plugins) {
10975
+ var p = this._plugins;
10976
+ ([]).concat(plugins).forEach(function(plugin) {
10977
+ if (p.indexOf(plugin) === -1) {
10978
+ p.push(plugin);
10979
+ }
10980
+ });
10981
+
10982
+ this._cacheId++;
10983
+ },
10984
+
10985
+ /**
10986
+ * Unregisters the given plugin(s) only if registered.
10987
+ * @param {Array|Object} plugins plugin instance(s).
10988
+ */
10989
+ unregister: function(plugins) {
10990
+ var p = this._plugins;
10991
+ ([]).concat(plugins).forEach(function(plugin) {
10992
+ var idx = p.indexOf(plugin);
10993
+ if (idx !== -1) {
10994
+ p.splice(idx, 1);
10995
+ }
10996
+ });
10997
+
10998
+ this._cacheId++;
10999
+ },
11000
+
11001
+ /**
11002
+ * Remove all registered plugins.
11003
+ * @since 2.1.5
11004
+ */
11005
+ clear: function() {
11006
+ this._plugins = [];
11007
+ this._cacheId++;
11008
+ },
11009
+
11010
+ /**
11011
+ * Returns the number of registered plugins?
11012
+ * @returns {Number}
11013
+ * @since 2.1.5
11014
+ */
11015
+ count: function() {
11016
+ return this._plugins.length;
11017
+ },
11018
+
11019
+ /**
11020
+ * Returns all registered plugin instances.
11021
+ * @returns {Array} array of plugin objects.
11022
+ * @since 2.1.5
11023
+ */
11024
+ getAll: function() {
11025
+ return this._plugins;
11026
+ },
11027
+
11028
+ /**
11029
+ * Calls enabled plugins for `chart` on the specified hook and with the given args.
11030
+ * This method immediately returns as soon as a plugin explicitly returns false. The
11031
+ * returned value can be used, for instance, to interrupt the current action.
11032
+ * @param {Object} chart - The chart instance for which plugins should be called.
11033
+ * @param {String} hook - The name of the plugin method to call (e.g. 'beforeUpdate').
11034
+ * @param {Array} [args] - Extra arguments to apply to the hook call.
11035
+ * @returns {Boolean} false if any of the plugins return false, else returns true.
11036
+ */
11037
+ notify: function(chart, hook, args) {
11038
+ var descriptors = this.descriptors(chart);
11039
+ var ilen = descriptors.length;
11040
+ var i, descriptor, plugin, params, method;
11041
+
11042
+ for (i = 0; i < ilen; ++i) {
11043
+ descriptor = descriptors[i];
11044
+ plugin = descriptor.plugin;
11045
+ method = plugin[hook];
11046
+ if (typeof method === 'function') {
11047
+ params = [chart].concat(args || []);
11048
+ params.push(descriptor.options);
11049
+ if (method.apply(plugin, params) === false) {
11050
+ return false;
11051
+ }
11052
+ }
11053
+ }
11054
+
11055
+ return true;
11056
+ },
11057
+
11058
+ /**
11059
+ * Returns descriptors of enabled plugins for the given chart.
11060
+ * @returns {Array} [{ plugin, options }]
11061
+ * @private
11062
+ */
11063
+ descriptors: function(chart) {
11064
+ var cache = chart._plugins || (chart._plugins = {});
11065
+ if (cache.id === this._cacheId) {
11066
+ return cache.descriptors;
11067
+ }
11068
+
11069
+ var plugins = [];
11070
+ var descriptors = [];
11071
+ var config = (chart && chart.config) || {};
11072
+ var options = (config.options && config.options.plugins) || {};
11073
+
11074
+ this._plugins.concat(config.plugins || []).forEach(function(plugin) {
11075
+ var idx = plugins.indexOf(plugin);
11076
+ if (idx !== -1) {
11077
+ return;
11078
+ }
11079
+
11080
+ var id = plugin.id;
11081
+ var opts = options[id];
11082
+ if (opts === false) {
11083
+ return;
11084
+ }
11085
+
11086
+ if (opts === true) {
11087
+ opts = helpers.clone(defaults.global.plugins[id]);
11088
+ }
11089
+
11090
+ plugins.push(plugin);
11091
+ descriptors.push({
11092
+ plugin: plugin,
11093
+ options: opts || {}
11094
+ });
11095
+ });
11096
+
11097
+ cache.descriptors = descriptors;
11098
+ cache.id = this._cacheId;
11099
+ return descriptors;
11100
+ }
11101
+ };
11102
+
11103
+ /**
11104
+ * Plugin extension hooks.
11105
+ * @interface IPlugin
11106
+ * @since 2.1.0
11107
+ */
11108
+ /**
11109
+ * @method IPlugin#beforeInit
11110
+ * @desc Called before initializing `chart`.
11111
+ * @param {Chart.Controller} chart - The chart instance.
11112
+ * @param {Object} options - The plugin options.
11113
+ */
11114
+ /**
11115
+ * @method IPlugin#afterInit
11116
+ * @desc Called after `chart` has been initialized and before the first update.
11117
+ * @param {Chart.Controller} chart - The chart instance.
11118
+ * @param {Object} options - The plugin options.
11119
+ */
11120
+ /**
11121
+ * @method IPlugin#beforeUpdate
11122
+ * @desc Called before updating `chart`. If any plugin returns `false`, the update
11123
+ * is cancelled (and thus subsequent render(s)) until another `update` is triggered.
11124
+ * @param {Chart.Controller} chart - The chart instance.
11125
+ * @param {Object} options - The plugin options.
11126
+ * @returns {Boolean} `false` to cancel the chart update.
11127
+ */
11128
+ /**
11129
+ * @method IPlugin#afterUpdate
11130
+ * @desc Called after `chart` has been updated and before rendering. Note that this
11131
+ * hook will not be called if the chart update has been previously cancelled.
11132
+ * @param {Chart.Controller} chart - The chart instance.
11133
+ * @param {Object} options - The plugin options.
11134
+ */
11135
+ /**
11136
+ * @method IPlugin#beforeDatasetsUpdate
11137
+ * @desc Called before updating the `chart` datasets. If any plugin returns `false`,
11138
+ * the datasets update is cancelled until another `update` is triggered.
11139
+ * @param {Chart.Controller} chart - The chart instance.
11140
+ * @param {Object} options - The plugin options.
11141
+ * @returns {Boolean} false to cancel the datasets update.
11142
+ * @since version 2.1.5
11143
+ */
11144
+ /**
11145
+ * @method IPlugin#afterDatasetsUpdate
11146
+ * @desc Called after the `chart` datasets have been updated. Note that this hook
11147
+ * will not be called if the datasets update has been previously cancelled.
11148
+ * @param {Chart.Controller} chart - The chart instance.
11149
+ * @param {Object} options - The plugin options.
11150
+ * @since version 2.1.5
11151
+ */
11152
+ /**
11153
+ * @method IPlugin#beforeDatasetUpdate
11154
+ * @desc Called before updating the `chart` dataset at the given `args.index`. If any plugin
11155
+ * returns `false`, the datasets update is cancelled until another `update` is triggered.
11156
+ * @param {Chart} chart - The chart instance.
11157
+ * @param {Object} args - The call arguments.
11158
+ * @param {Number} args.index - The dataset index.
11159
+ * @param {Object} args.meta - The dataset metadata.
11160
+ * @param {Object} options - The plugin options.
11161
+ * @returns {Boolean} `false` to cancel the chart datasets drawing.
11162
+ */
11163
+ /**
11164
+ * @method IPlugin#afterDatasetUpdate
11165
+ * @desc Called after the `chart` datasets at the given `args.index` has been updated. Note
11166
+ * that this hook will not be called if the datasets update has been previously cancelled.
11167
+ * @param {Chart} chart - The chart instance.
11168
+ * @param {Object} args - The call arguments.
11169
+ * @param {Number} args.index - The dataset index.
11170
+ * @param {Object} args.meta - The dataset metadata.
11171
+ * @param {Object} options - The plugin options.
11172
+ */
11173
+ /**
11174
+ * @method IPlugin#beforeLayout
11175
+ * @desc Called before laying out `chart`. If any plugin returns `false`,
11176
+ * the layout update is cancelled until another `update` is triggered.
11177
+ * @param {Chart.Controller} chart - The chart instance.
11178
+ * @param {Object} options - The plugin options.
11179
+ * @returns {Boolean} `false` to cancel the chart layout.
11180
+ */
11181
+ /**
11182
+ * @method IPlugin#afterLayout
11183
+ * @desc Called after the `chart` has been layed out. Note that this hook will not
11184
+ * be called if the layout update has been previously cancelled.
11185
+ * @param {Chart.Controller} chart - The chart instance.
11186
+ * @param {Object} options - The plugin options.
11187
+ */
11188
+ /**
11189
+ * @method IPlugin#beforeRender
11190
+ * @desc Called before rendering `chart`. If any plugin returns `false`,
11191
+ * the rendering is cancelled until another `render` is triggered.
11192
+ * @param {Chart.Controller} chart - The chart instance.
11193
+ * @param {Object} options - The plugin options.
11194
+ * @returns {Boolean} `false` to cancel the chart rendering.
11195
+ */
11196
+ /**
11197
+ * @method IPlugin#afterRender
11198
+ * @desc Called after the `chart` has been fully rendered (and animation completed). Note
11199
+ * that this hook will not be called if the rendering has been previously cancelled.
11200
+ * @param {Chart.Controller} chart - The chart instance.
11201
+ * @param {Object} options - The plugin options.
11202
+ */
11203
+ /**
11204
+ * @method IPlugin#beforeDraw
11205
+ * @desc Called before drawing `chart` at every animation frame specified by the given
11206
+ * easing value. If any plugin returns `false`, the frame drawing is cancelled until
11207
+ * another `render` is triggered.
11208
+ * @param {Chart.Controller} chart - The chart instance.
11209
+ * @param {Number} easingValue - The current animation value, between 0.0 and 1.0.
11210
+ * @param {Object} options - The plugin options.
11211
+ * @returns {Boolean} `false` to cancel the chart drawing.
11212
+ */
11213
+ /**
11214
+ * @method IPlugin#afterDraw
11215
+ * @desc Called after the `chart` has been drawn for the specific easing value. Note
11216
+ * that this hook will not be called if the drawing has been previously cancelled.
11217
+ * @param {Chart.Controller} chart - The chart instance.
11218
+ * @param {Number} easingValue - The current animation value, between 0.0 and 1.0.
11219
+ * @param {Object} options - The plugin options.
11220
+ */
11221
+ /**
11222
+ * @method IPlugin#beforeDatasetsDraw
11223
+ * @desc Called before drawing the `chart` datasets. If any plugin returns `false`,
11224
+ * the datasets drawing is cancelled until another `render` is triggered.
11225
+ * @param {Chart.Controller} chart - The chart instance.
11226
+ * @param {Number} easingValue - The current animation value, between 0.0 and 1.0.
11227
+ * @param {Object} options - The plugin options.
11228
+ * @returns {Boolean} `false` to cancel the chart datasets drawing.
11229
+ */
11230
+ /**
11231
+ * @method IPlugin#afterDatasetsDraw
11232
+ * @desc Called after the `chart` datasets have been drawn. Note that this hook
11233
+ * will not be called if the datasets drawing has been previously cancelled.
11234
+ * @param {Chart.Controller} chart - The chart instance.
11235
+ * @param {Number} easingValue - The current animation value, between 0.0 and 1.0.
11236
+ * @param {Object} options - The plugin options.
11237
+ */
11238
+ /**
11239
+ * @method IPlugin#beforeDatasetDraw
11240
+ * @desc Called before drawing the `chart` dataset at the given `args.index` (datasets
11241
+ * are drawn in the reverse order). If any plugin returns `false`, the datasets drawing
11242
+ * is cancelled until another `render` is triggered.
11243
+ * @param {Chart} chart - The chart instance.
11244
+ * @param {Object} args - The call arguments.
11245
+ * @param {Number} args.index - The dataset index.
11246
+ * @param {Object} args.meta - The dataset metadata.
11247
+ * @param {Number} args.easingValue - The current animation value, between 0.0 and 1.0.
11248
+ * @param {Object} options - The plugin options.
11249
+ * @returns {Boolean} `false` to cancel the chart datasets drawing.
11250
+ */
11251
+ /**
11252
+ * @method IPlugin#afterDatasetDraw
11253
+ * @desc Called after the `chart` datasets at the given `args.index` have been drawn
11254
+ * (datasets are drawn in the reverse order). Note that this hook will not be called
11255
+ * if the datasets drawing has been previously cancelled.
11256
+ * @param {Chart} chart - The chart instance.
11257
+ * @param {Object} args - The call arguments.
11258
+ * @param {Number} args.index - The dataset index.
11259
+ * @param {Object} args.meta - The dataset metadata.
11260
+ * @param {Number} args.easingValue - The current animation value, between 0.0 and 1.0.
11261
+ * @param {Object} options - The plugin options.
11262
+ */
11263
+ /**
11264
+ * @method IPlugin#beforeEvent
11265
+ * @desc Called before processing the specified `event`. If any plugin returns `false`,
11266
+ * the event will be discarded.
11267
+ * @param {Chart.Controller} chart - The chart instance.
11268
+ * @param {IEvent} event - The event object.
11269
+ * @param {Object} options - The plugin options.
11270
+ */
11271
+ /**
11272
+ * @method IPlugin#afterEvent
11273
+ * @desc Called after the `event` has been consumed. Note that this hook
11274
+ * will not be called if the `event` has been previously discarded.
11275
+ * @param {Chart.Controller} chart - The chart instance.
11276
+ * @param {IEvent} event - The event object.
11277
+ * @param {Object} options - The plugin options.
11278
+ */
11279
+ /**
11280
+ * @method IPlugin#resize
11281
+ * @desc Called after the chart as been resized.
11282
+ * @param {Chart.Controller} chart - The chart instance.
11283
+ * @param {Number} size - The new canvas display size (eq. canvas.style width & height).
11284
+ * @param {Object} options - The plugin options.
11285
+ */
11286
+ /**
11287
+ * @method IPlugin#destroy
11288
+ * @desc Called after the chart as been destroyed.
11289
+ * @param {Chart.Controller} chart - The chart instance.
11290
+ * @param {Object} options - The plugin options.
11291
+ */
11292
+
11293
+ /**
11294
+ * Provided for backward compatibility, use Chart.plugins instead
11295
+ * @namespace Chart.pluginService
11296
+ * @deprecated since version 2.1.5
11297
+ * @todo remove at version 3
11298
+ * @private
11299
+ */
11300
+ Chart.pluginService = Chart.plugins;
11301
+
11302
+ /**
11303
+ * Provided for backward compatibility, inheriting from Chart.PlugingBase has no
11304
+ * effect, instead simply create/register plugins via plain JavaScript objects.
11305
+ * @interface Chart.PluginBase
11306
+ * @deprecated since version 2.5.0
11307
+ * @todo remove at version 3
11308
+ * @private
11309
+ */
11310
+ Chart.PluginBase = Element.extend({});
11311
+ };
11312
+
11313
+ },{"25":25,"26":26,"45":45}],32:[function(require,module,exports){
11314
+ 'use strict';
11315
+
11316
+ var defaults = require(25);
11317
+ var Element = require(26);
11318
+ var helpers = require(45);
11319
+ var Ticks = require(34);
11320
+
11321
+ defaults._set('scale', {
11322
+ display: true,
11323
+ position: 'left',
11324
+ offset: false,
11325
+
11326
+ // grid line settings
11327
+ gridLines: {
11328
+ display: true,
11329
+ color: 'rgba(0, 0, 0, 0.1)',
11330
+ lineWidth: 1,
11331
+ drawBorder: true,
11332
+ drawOnChartArea: true,
11333
+ drawTicks: true,
11334
+ tickMarkLength: 10,
11335
+ zeroLineWidth: 1,
11336
+ zeroLineColor: 'rgba(0,0,0,0.25)',
11337
+ zeroLineBorderDash: [],
11338
+ zeroLineBorderDashOffset: 0.0,
11339
+ offsetGridLines: false,
11340
+ borderDash: [],
11341
+ borderDashOffset: 0.0
11342
+ },
11343
+
11344
+ // scale label
11345
+ scaleLabel: {
11346
+ // display property
11347
+ display: false,
11348
+
11349
+ // actual label
11350
+ labelString: '',
11351
+
11352
+ // line height
11353
+ lineHeight: 1.2,
11354
+
11355
+ // top/bottom padding
11356
+ padding: {
11357
+ top: 4,
11358
+ bottom: 4
11359
+ }
11360
+ },
11361
+
11362
+ // label settings
11363
+ ticks: {
11364
+ beginAtZero: false,
11365
+ minRotation: 0,
11366
+ maxRotation: 50,
11367
+ mirror: false,
11368
+ padding: 0,
11369
+ reverse: false,
11370
+ display: true,
11371
+ autoSkip: true,
11372
+ autoSkipPadding: 0,
11373
+ labelOffset: 0,
11374
+ // We pass through arrays to be rendered as multiline labels, we convert Others to strings here.
11375
+ callback: Ticks.formatters.values,
11376
+ minor: {},
11377
+ major: {}
11378
+ }
11379
+ });
11380
+
11381
+ function labelsFromTicks(ticks) {
11382
+ var labels = [];
11383
+ var i, ilen;
11384
+
11385
+ for (i = 0, ilen = ticks.length; i < ilen; ++i) {
11386
+ labels.push(ticks[i].label);
11387
+ }
11388
+
11389
+ return labels;
11390
+ }
11391
+
11392
+ function getLineValue(scale, index, offsetGridLines) {
11393
+ var lineValue = scale.getPixelForTick(index);
11394
+
11395
+ if (offsetGridLines) {
11396
+ if (index === 0) {
11397
+ lineValue -= (scale.getPixelForTick(1) - lineValue) / 2;
11398
+ } else {
11399
+ lineValue -= (lineValue - scale.getPixelForTick(index - 1)) / 2;
11400
+ }
11401
+ }
11402
+ return lineValue;
11403
+ }
11404
+
11405
+ module.exports = function(Chart) {
11406
+
11407
+ function computeTextSize(context, tick, font) {
11408
+ return helpers.isArray(tick) ?
11409
+ helpers.longestText(context, font, tick) :
11410
+ context.measureText(tick).width;
11411
+ }
11412
+
11413
+ function parseFontOptions(options) {
11414
+ var valueOrDefault = helpers.valueOrDefault;
11415
+ var globalDefaults = defaults.global;
11416
+ var size = valueOrDefault(options.fontSize, globalDefaults.defaultFontSize);
11417
+ var style = valueOrDefault(options.fontStyle, globalDefaults.defaultFontStyle);
11418
+ var family = valueOrDefault(options.fontFamily, globalDefaults.defaultFontFamily);
11419
+
11420
+ return {
11421
+ size: size,
11422
+ style: style,
11423
+ family: family,
11424
+ font: helpers.fontString(size, style, family)
11425
+ };
11426
+ }
11427
+
11428
+ function parseLineHeight(options) {
11429
+ return helpers.options.toLineHeight(
11430
+ helpers.valueOrDefault(options.lineHeight, 1.2),
11431
+ helpers.valueOrDefault(options.fontSize, defaults.global.defaultFontSize));
11432
+ }
11433
+
11434
+ Chart.Scale = Element.extend({
11435
+ /**
11436
+ * Get the padding needed for the scale
11437
+ * @method getPadding
11438
+ * @private
11439
+ * @returns {Padding} the necessary padding
11440
+ */
11441
+ getPadding: function() {
11442
+ var me = this;
11443
+ return {
11444
+ left: me.paddingLeft || 0,
11445
+ top: me.paddingTop || 0,
11446
+ right: me.paddingRight || 0,
11447
+ bottom: me.paddingBottom || 0
11448
+ };
11449
+ },
11450
+
11451
+ /**
11452
+ * Returns the scale tick objects ({label, major})
11453
+ * @since 2.7
11454
+ */
11455
+ getTicks: function() {
11456
+ return this._ticks;
11457
+ },
11458
+
11459
+ // These methods are ordered by lifecyle. Utilities then follow.
11460
+ // Any function defined here is inherited by all scale types.
11461
+ // Any function can be extended by the scale type
11462
+
11463
+ mergeTicksOptions: function() {
11464
+ var ticks = this.options.ticks;
11465
+ if (ticks.minor === false) {
11466
+ ticks.minor = {
11467
+ display: false
11468
+ };
11469
+ }
11470
+ if (ticks.major === false) {
11471
+ ticks.major = {
11472
+ display: false
11473
+ };
11474
+ }
11475
+ for (var key in ticks) {
11476
+ if (key !== 'major' && key !== 'minor') {
11477
+ if (typeof ticks.minor[key] === 'undefined') {
11478
+ ticks.minor[key] = ticks[key];
11479
+ }
11480
+ if (typeof ticks.major[key] === 'undefined') {
11481
+ ticks.major[key] = ticks[key];
11482
+ }
11483
+ }
11484
+ }
11485
+ },
11486
+ beforeUpdate: function() {
11487
+ helpers.callback(this.options.beforeUpdate, [this]);
11488
+ },
11489
+ update: function(maxWidth, maxHeight, margins) {
11490
+ var me = this;
11491
+ var i, ilen, labels, label, ticks, tick;
11492
+
11493
+ // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
11494
+ me.beforeUpdate();
11495
+
11496
+ // Absorb the master measurements
11497
+ me.maxWidth = maxWidth;
11498
+ me.maxHeight = maxHeight;
11499
+ me.margins = helpers.extend({
11500
+ left: 0,
11501
+ right: 0,
11502
+ top: 0,
11503
+ bottom: 0
11504
+ }, margins);
11505
+ me.longestTextCache = me.longestTextCache || {};
11506
+
11507
+ // Dimensions
11508
+ me.beforeSetDimensions();
11509
+ me.setDimensions();
11510
+ me.afterSetDimensions();
11511
+
11512
+ // Data min/max
11513
+ me.beforeDataLimits();
11514
+ me.determineDataLimits();
11515
+ me.afterDataLimits();
11516
+
11517
+ // Ticks - `this.ticks` is now DEPRECATED!
11518
+ // Internal ticks are now stored as objects in the PRIVATE `this._ticks` member
11519
+ // and must not be accessed directly from outside this class. `this.ticks` being
11520
+ // around for long time and not marked as private, we can't change its structure
11521
+ // without unexpected breaking changes. If you need to access the scale ticks,
11522
+ // use scale.getTicks() instead.
11523
+
11524
+ me.beforeBuildTicks();
11525
+
11526
+ // New implementations should return an array of objects but for BACKWARD COMPAT,
11527
+ // we still support no return (`this.ticks` internally set by calling this method).
11528
+ ticks = me.buildTicks() || [];
11529
+
11530
+ me.afterBuildTicks();
11531
+
11532
+ me.beforeTickToLabelConversion();
11533
+
11534
+ // New implementations should return the formatted tick labels but for BACKWARD
11535
+ // COMPAT, we still support no return (`this.ticks` internally changed by calling
11536
+ // this method and supposed to contain only string values).
11537
+ labels = me.convertTicksToLabels(ticks) || me.ticks;
11538
+
11539
+ me.afterTickToLabelConversion();
11540
+
11541
+ me.ticks = labels; // BACKWARD COMPATIBILITY
11542
+
11543
+ // IMPORTANT: from this point, we consider that `this.ticks` will NEVER change!
11544
+
11545
+ // BACKWARD COMPAT: synchronize `_ticks` with labels (so potentially `this.ticks`)
11546
+ for (i = 0, ilen = labels.length; i < ilen; ++i) {
11547
+ label = labels[i];
11548
+ tick = ticks[i];
11549
+ if (!tick) {
11550
+ ticks.push(tick = {
11551
+ label: label,
11552
+ major: false
11553
+ });
11554
+ } else {
11555
+ tick.label = label;
11556
+ }
11557
+ }
11558
+
11559
+ me._ticks = ticks;
11560
+
11561
+ // Tick Rotation
11562
+ me.beforeCalculateTickRotation();
11563
+ me.calculateTickRotation();
11564
+ me.afterCalculateTickRotation();
11565
+ // Fit
11566
+ me.beforeFit();
11567
+ me.fit();
11568
+ me.afterFit();
11569
+ //
11570
+ me.afterUpdate();
11571
+
11572
+ return me.minSize;
11573
+
11574
+ },
11575
+ afterUpdate: function() {
11576
+ helpers.callback(this.options.afterUpdate, [this]);
11577
+ },
11578
+
11579
+ //
11580
+
11581
+ beforeSetDimensions: function() {
11582
+ helpers.callback(this.options.beforeSetDimensions, [this]);
11583
+ },
11584
+ setDimensions: function() {
11585
+ var me = this;
11586
+ // Set the unconstrained dimension before label rotation
11587
+ if (me.isHorizontal()) {
11588
+ // Reset position before calculating rotation
11589
+ me.width = me.maxWidth;
11590
+ me.left = 0;
11591
+ me.right = me.width;
11592
+ } else {
11593
+ me.height = me.maxHeight;
11594
+
11595
+ // Reset position before calculating rotation
11596
+ me.top = 0;
11597
+ me.bottom = me.height;
11598
+ }
11599
+
11600
+ // Reset padding
11601
+ me.paddingLeft = 0;
11602
+ me.paddingTop = 0;
11603
+ me.paddingRight = 0;
11604
+ me.paddingBottom = 0;
11605
+ },
11606
+ afterSetDimensions: function() {
11607
+ helpers.callback(this.options.afterSetDimensions, [this]);
11608
+ },
11609
+
11610
+ // Data limits
11611
+ beforeDataLimits: function() {
11612
+ helpers.callback(this.options.beforeDataLimits, [this]);
11613
+ },
11614
+ determineDataLimits: helpers.noop,
11615
+ afterDataLimits: function() {
11616
+ helpers.callback(this.options.afterDataLimits, [this]);
11617
+ },
11618
+
11619
+ //
11620
+ beforeBuildTicks: function() {
11621
+ helpers.callback(this.options.beforeBuildTicks, [this]);
11622
+ },
11623
+ buildTicks: helpers.noop,
11624
+ afterBuildTicks: function() {
11625
+ helpers.callback(this.options.afterBuildTicks, [this]);
11626
+ },
11627
+
11628
+ beforeTickToLabelConversion: function() {
11629
+ helpers.callback(this.options.beforeTickToLabelConversion, [this]);
11630
+ },
11631
+ convertTicksToLabels: function() {
11632
+ var me = this;
11633
+ // Convert ticks to strings
11634
+ var tickOpts = me.options.ticks;
11635
+ me.ticks = me.ticks.map(tickOpts.userCallback || tickOpts.callback, this);
11636
+ },
11637
+ afterTickToLabelConversion: function() {
11638
+ helpers.callback(this.options.afterTickToLabelConversion, [this]);
11639
+ },
11640
+
11641
+ //
11642
+
11643
+ beforeCalculateTickRotation: function() {
11644
+ helpers.callback(this.options.beforeCalculateTickRotation, [this]);
11645
+ },
11646
+ calculateTickRotation: function() {
11647
+ var me = this;
11648
+ var context = me.ctx;
11649
+ var tickOpts = me.options.ticks;
11650
+ var labels = labelsFromTicks(me._ticks);
11651
+
11652
+ // Get the width of each grid by calculating the difference
11653
+ // between x offsets between 0 and 1.
11654
+ var tickFont = parseFontOptions(tickOpts);
11655
+ context.font = tickFont.font;
11656
+
11657
+ var labelRotation = tickOpts.minRotation || 0;
11658
+
11659
+ if (labels.length && me.options.display && me.isHorizontal()) {
11660
+ var originalLabelWidth = helpers.longestText(context, tickFont.font, labels, me.longestTextCache);
11661
+ var labelWidth = originalLabelWidth;
11662
+ var cosRotation, sinRotation;
11663
+
11664
+ // Allow 3 pixels x2 padding either side for label readability
11665
+ var tickWidth = me.getPixelForTick(1) - me.getPixelForTick(0) - 6;
11666
+
11667
+ // Max label rotation can be set or default to 90 - also act as a loop counter
11668
+ while (labelWidth > tickWidth && labelRotation < tickOpts.maxRotation) {
11669
+ var angleRadians = helpers.toRadians(labelRotation);
11670
+ cosRotation = Math.cos(angleRadians);
11671
+ sinRotation = Math.sin(angleRadians);
11672
+
11673
+ if (sinRotation * originalLabelWidth > me.maxHeight) {
11674
+ // go back one step
11675
+ labelRotation--;
11676
+ break;
11677
+ }
11678
+
11679
+ labelRotation++;
11680
+ labelWidth = cosRotation * originalLabelWidth;
11681
+ }
11682
+ }
11683
+
11684
+ me.labelRotation = labelRotation;
11685
+ },
11686
+ afterCalculateTickRotation: function() {
11687
+ helpers.callback(this.options.afterCalculateTickRotation, [this]);
11688
+ },
11689
+
11690
+ //
11691
+
11692
+ beforeFit: function() {
11693
+ helpers.callback(this.options.beforeFit, [this]);
11694
+ },
11695
+ fit: function() {
11696
+ var me = this;
11697
+ // Reset
11698
+ var minSize = me.minSize = {
11699
+ width: 0,
11700
+ height: 0
11701
+ };
11702
+
11703
+ var labels = labelsFromTicks(me._ticks);
11704
+
11705
+ var opts = me.options;
11706
+ var tickOpts = opts.ticks;
11707
+ var scaleLabelOpts = opts.scaleLabel;
11708
+ var gridLineOpts = opts.gridLines;
11709
+ var display = opts.display;
11710
+ var isHorizontal = me.isHorizontal();
11711
+
11712
+ var tickFont = parseFontOptions(tickOpts);
11713
+ var tickMarkLength = opts.gridLines.tickMarkLength;
11714
+
11715
+ // Width
11716
+ if (isHorizontal) {
11717
+ // subtract the margins to line up with the chartArea if we are a full width scale
11718
+ minSize.width = me.isFullWidth() ? me.maxWidth - me.margins.left - me.margins.right : me.maxWidth;
11719
+ } else {
11720
+ minSize.width = display && gridLineOpts.drawTicks ? tickMarkLength : 0;
11721
+ }
11722
+
11723
+ // height
11724
+ if (isHorizontal) {
11725
+ minSize.height = display && gridLineOpts.drawTicks ? tickMarkLength : 0;
11726
+ } else {
11727
+ minSize.height = me.maxHeight; // fill all the height
11728
+ }
11729
+
11730
+ // Are we showing a title for the scale?
11731
+ if (scaleLabelOpts.display && display) {
11732
+ var scaleLabelLineHeight = parseLineHeight(scaleLabelOpts);
11733
+ var scaleLabelPadding = helpers.options.toPadding(scaleLabelOpts.padding);
11734
+ var deltaHeight = scaleLabelLineHeight + scaleLabelPadding.height;
11735
+
11736
+ if (isHorizontal) {
11737
+ minSize.height += deltaHeight;
11738
+ } else {
11739
+ minSize.width += deltaHeight;
11740
+ }
11741
+ }
11742
+
11743
+ // Don't bother fitting the ticks if we are not showing them
11744
+ if (tickOpts.display && display) {
11745
+ var largestTextWidth = helpers.longestText(me.ctx, tickFont.font, labels, me.longestTextCache);
11746
+ var tallestLabelHeightInLines = helpers.numberOfLabelLines(labels);
11747
+ var lineSpace = tickFont.size * 0.5;
11748
+ var tickPadding = me.options.ticks.padding;
11749
+
11750
+ if (isHorizontal) {
11751
+ // A horizontal axis is more constrained by the height.
11752
+ me.longestLabelWidth = largestTextWidth;
11753
+
11754
+ var angleRadians = helpers.toRadians(me.labelRotation);
11755
+ var cosRotation = Math.cos(angleRadians);
11756
+ var sinRotation = Math.sin(angleRadians);
11757
+
11758
+ // TODO - improve this calculation
11759
+ var labelHeight = (sinRotation * largestTextWidth)
11760
+ + (tickFont.size * tallestLabelHeightInLines)
11761
+ + (lineSpace * (tallestLabelHeightInLines - 1))
11762
+ + lineSpace; // padding
11763
+
11764
+ minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight + tickPadding);
11765
+
11766
+ me.ctx.font = tickFont.font;
11767
+ var firstLabelWidth = computeTextSize(me.ctx, labels[0], tickFont.font);
11768
+ var lastLabelWidth = computeTextSize(me.ctx, labels[labels.length - 1], tickFont.font);
11769
+
11770
+ // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned
11771
+ // which means that the right padding is dominated by the font height
11772
+ if (me.labelRotation !== 0) {
11773
+ me.paddingLeft = opts.position === 'bottom' ? (cosRotation * firstLabelWidth) + 3 : (cosRotation * lineSpace) + 3; // add 3 px to move away from canvas edges
11774
+ me.paddingRight = opts.position === 'bottom' ? (cosRotation * lineSpace) + 3 : (cosRotation * lastLabelWidth) + 3;
11775
+ } else {
11776
+ me.paddingLeft = firstLabelWidth / 2 + 3; // add 3 px to move away from canvas edges
11777
+ me.paddingRight = lastLabelWidth / 2 + 3;
11778
+ }
11779
+ } else {
11780
+ // A vertical axis is more constrained by the width. Labels are the
11781
+ // dominant factor here, so get that length first and account for padding
11782
+ if (tickOpts.mirror) {
11783
+ largestTextWidth = 0;
11784
+ } else {
11785
+ // use lineSpace for consistency with horizontal axis
11786
+ // tickPadding is not implemented for horizontal
11787
+ largestTextWidth += tickPadding + lineSpace;
11788
+ }
11789
+
11790
+ minSize.width = Math.min(me.maxWidth, minSize.width + largestTextWidth);
11791
+
11792
+ me.paddingTop = tickFont.size / 2;
11793
+ me.paddingBottom = tickFont.size / 2;
11794
+ }
11795
+ }
11796
+
11797
+ me.handleMargins();
11798
+
11799
+ me.width = minSize.width;
11800
+ me.height = minSize.height;
11801
+ },
11802
+
11803
+ /**
11804
+ * Handle margins and padding interactions
11805
+ * @private
11806
+ */
11807
+ handleMargins: function() {
11808
+ var me = this;
11809
+ if (me.margins) {
11810
+ me.paddingLeft = Math.max(me.paddingLeft - me.margins.left, 0);
11811
+ me.paddingTop = Math.max(me.paddingTop - me.margins.top, 0);
11812
+ me.paddingRight = Math.max(me.paddingRight - me.margins.right, 0);
11813
+ me.paddingBottom = Math.max(me.paddingBottom - me.margins.bottom, 0);
11814
+ }
11815
+ },
11816
+
11817
+ afterFit: function() {
11818
+ helpers.callback(this.options.afterFit, [this]);
11819
+ },
11820
+
11821
+ // Shared Methods
11822
+ isHorizontal: function() {
11823
+ return this.options.position === 'top' || this.options.position === 'bottom';
11824
+ },
11825
+ isFullWidth: function() {
11826
+ return (this.options.fullWidth);
11827
+ },
11828
+
11829
+ // Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not
11830
+ getRightValue: function(rawValue) {
11831
+ // Null and undefined values first
11832
+ if (helpers.isNullOrUndef(rawValue)) {
11833
+ return NaN;
11834
+ }
11835
+ // isNaN(object) returns true, so make sure NaN is checking for a number; Discard Infinite values
11836
+ if (typeof rawValue === 'number' && !isFinite(rawValue)) {
11837
+ return NaN;
11838
+ }
11839
+ // If it is in fact an object, dive in one more level
11840
+ if (rawValue) {
11841
+ if (this.isHorizontal()) {
11842
+ if (rawValue.x !== undefined) {
11843
+ return this.getRightValue(rawValue.x);
11844
+ }
11845
+ } else if (rawValue.y !== undefined) {
11846
+ return this.getRightValue(rawValue.y);
11847
+ }
11848
+ }
11849
+
11850
+ // Value is good, return it
11851
+ return rawValue;
11852
+ },
11853
+
11854
+ // Used to get the value to display in the tooltip for the data at the given index
11855
+ // function getLabelForIndex(index, datasetIndex)
11856
+ getLabelForIndex: helpers.noop,
11857
+
11858
+ // Used to get data value locations. Value can either be an index or a numerical value
11859
+ getPixelForValue: helpers.noop,
11860
+
11861
+ // Used to get the data value from a given pixel. This is the inverse of getPixelForValue
11862
+ getValueForPixel: helpers.noop,
11863
+
11864
+ // Used for tick location, should
11865
+ getPixelForTick: function(index) {
11866
+ var me = this;
11867
+ var offset = me.options.offset;
11868
+ if (me.isHorizontal()) {
11869
+ var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
11870
+ var tickWidth = innerWidth / Math.max((me._ticks.length - (offset ? 0 : 1)), 1);
11871
+ var pixel = (tickWidth * index) + me.paddingLeft;
11872
+
11873
+ if (offset) {
11874
+ pixel += tickWidth / 2;
11875
+ }
11876
+
11877
+ var finalVal = me.left + Math.round(pixel);
11878
+ finalVal += me.isFullWidth() ? me.margins.left : 0;
11879
+ return finalVal;
11880
+ }
11881
+ var innerHeight = me.height - (me.paddingTop + me.paddingBottom);
11882
+ return me.top + (index * (innerHeight / (me._ticks.length - 1)));
11883
+ },
11884
+
11885
+ // Utility for getting the pixel location of a percentage of scale
11886
+ getPixelForDecimal: function(decimal) {
11887
+ var me = this;
11888
+ if (me.isHorizontal()) {
11889
+ var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
11890
+ var valueOffset = (innerWidth * decimal) + me.paddingLeft;
11891
+
11892
+ var finalVal = me.left + Math.round(valueOffset);
11893
+ finalVal += me.isFullWidth() ? me.margins.left : 0;
11894
+ return finalVal;
11895
+ }
11896
+ return me.top + (decimal * me.height);
11897
+ },
11898
+
11899
+ getBasePixel: function() {
11900
+ return this.getPixelForValue(this.getBaseValue());
11901
+ },
11902
+
11903
+ getBaseValue: function() {
11904
+ var me = this;
11905
+ var min = me.min;
11906
+ var max = me.max;
11907
+
11908
+ return me.beginAtZero ? 0 :
11909
+ min < 0 && max < 0 ? max :
11910
+ min > 0 && max > 0 ? min :
11911
+ 0;
11912
+ },
11913
+
11914
+ /**
11915
+ * Returns a subset of ticks to be plotted to avoid overlapping labels.
11916
+ * @private
11917
+ */
11918
+ _autoSkip: function(ticks) {
11919
+ var skipRatio;
11920
+ var me = this;
11921
+ var isHorizontal = me.isHorizontal();
11922
+ var optionTicks = me.options.ticks.minor;
11923
+ var tickCount = ticks.length;
11924
+ var labelRotationRadians = helpers.toRadians(me.labelRotation);
11925
+ var cosRotation = Math.cos(labelRotationRadians);
11926
+ var longestRotatedLabel = me.longestLabelWidth * cosRotation;
11927
+ var result = [];
11928
+ var i, tick, shouldSkip;
11929
+
11930
+ // figure out the maximum number of gridlines to show
11931
+ var maxTicks;
11932
+ if (optionTicks.maxTicksLimit) {
11933
+ maxTicks = optionTicks.maxTicksLimit;
11934
+ }
11935
+
11936
+ if (isHorizontal) {
11937
+ skipRatio = false;
11938
+
11939
+ if ((longestRotatedLabel + optionTicks.autoSkipPadding) * tickCount > (me.width - (me.paddingLeft + me.paddingRight))) {
11940
+ skipRatio = 1 + Math.floor(((longestRotatedLabel + optionTicks.autoSkipPadding) * tickCount) / (me.width - (me.paddingLeft + me.paddingRight)));
11941
+ }
11942
+
11943
+ // if they defined a max number of optionTicks,
11944
+ // increase skipRatio until that number is met
11945
+ if (maxTicks && tickCount > maxTicks) {
11946
+ skipRatio = Math.max(skipRatio, Math.floor(tickCount / maxTicks));
11947
+ }
11948
+ }
11949
+
11950
+ for (i = 0; i < tickCount; i++) {
11951
+ tick = ticks[i];
11952
+
11953
+ // Since we always show the last tick,we need may need to hide the last shown one before
11954
+ shouldSkip = (skipRatio > 1 && i % skipRatio > 0) || (i % skipRatio === 0 && i + skipRatio >= tickCount);
11955
+ if (shouldSkip && i !== tickCount - 1 || helpers.isNullOrUndef(tick.label)) {
11956
+ // leave tick in place but make sure it's not displayed (#4635)
11957
+ delete tick.label;
11958
+ }
11959
+ result.push(tick);
11960
+ }
11961
+ return result;
11962
+ },
11963
+
11964
+ // Actually draw the scale on the canvas
11965
+ // @param {rectangle} chartArea : the area of the chart to draw full grid lines on
11966
+ draw: function(chartArea) {
11967
+ var me = this;
11968
+ var options = me.options;
11969
+ if (!options.display) {
11970
+ return;
11971
+ }
11972
+
11973
+ var context = me.ctx;
11974
+ var globalDefaults = defaults.global;
11975
+ var optionTicks = options.ticks.minor;
11976
+ var optionMajorTicks = options.ticks.major || optionTicks;
11977
+ var gridLines = options.gridLines;
11978
+ var scaleLabel = options.scaleLabel;
11979
+
11980
+ var isRotated = me.labelRotation !== 0;
11981
+ var isHorizontal = me.isHorizontal();
11982
+
11983
+ var ticks = optionTicks.autoSkip ? me._autoSkip(me.getTicks()) : me.getTicks();
11984
+ var tickFontColor = helpers.valueOrDefault(optionTicks.fontColor, globalDefaults.defaultFontColor);
11985
+ var tickFont = parseFontOptions(optionTicks);
11986
+ var majorTickFontColor = helpers.valueOrDefault(optionMajorTicks.fontColor, globalDefaults.defaultFontColor);
11987
+ var majorTickFont = parseFontOptions(optionMajorTicks);
11988
+
11989
+ var tl = gridLines.drawTicks ? gridLines.tickMarkLength : 0;
11990
+
11991
+ var scaleLabelFontColor = helpers.valueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor);
11992
+ var scaleLabelFont = parseFontOptions(scaleLabel);
11993
+ var scaleLabelPadding = helpers.options.toPadding(scaleLabel.padding);
11994
+ var labelRotationRadians = helpers.toRadians(me.labelRotation);
11995
+
11996
+ var itemsToDraw = [];
11997
+
11998
+ var xTickStart = options.position === 'right' ? me.left : me.right - tl;
11999
+ var xTickEnd = options.position === 'right' ? me.left + tl : me.right;
12000
+ var yTickStart = options.position === 'bottom' ? me.top : me.bottom - tl;
12001
+ var yTickEnd = options.position === 'bottom' ? me.top + tl : me.bottom;
12002
+
12003
+ helpers.each(ticks, function(tick, index) {
12004
+ // autoskipper skipped this tick (#4635)
12005
+ if (tick.label === undefined) {
12006
+ return;
12007
+ }
12008
+
12009
+ var label = tick.label;
12010
+ var lineWidth, lineColor, borderDash, borderDashOffset;
12011
+ if (index === me.zeroLineIndex && options.offset === gridLines.offsetGridLines) {
12012
+ // Draw the first index specially
12013
+ lineWidth = gridLines.zeroLineWidth;
12014
+ lineColor = gridLines.zeroLineColor;
12015
+ borderDash = gridLines.zeroLineBorderDash;
12016
+ borderDashOffset = gridLines.zeroLineBorderDashOffset;
12017
+ } else {
12018
+ lineWidth = helpers.valueAtIndexOrDefault(gridLines.lineWidth, index);
12019
+ lineColor = helpers.valueAtIndexOrDefault(gridLines.color, index);
12020
+ borderDash = helpers.valueOrDefault(gridLines.borderDash, globalDefaults.borderDash);
12021
+ borderDashOffset = helpers.valueOrDefault(gridLines.borderDashOffset, globalDefaults.borderDashOffset);
12022
+ }
12023
+
12024
+ // Common properties
12025
+ var tx1, ty1, tx2, ty2, x1, y1, x2, y2, labelX, labelY;
12026
+ var textAlign = 'middle';
12027
+ var textBaseline = 'middle';
12028
+ var tickPadding = optionTicks.padding;
12029
+
12030
+ if (isHorizontal) {
12031
+ var labelYOffset = tl + tickPadding;
12032
+
12033
+ if (options.position === 'bottom') {
12034
+ // bottom
12035
+ textBaseline = !isRotated ? 'top' : 'middle';
12036
+ textAlign = !isRotated ? 'center' : 'right';
12037
+ labelY = me.top + labelYOffset;
12038
+ } else {
12039
+ // top
12040
+ textBaseline = !isRotated ? 'bottom' : 'middle';
12041
+ textAlign = !isRotated ? 'center' : 'left';
12042
+ labelY = me.bottom - labelYOffset;
12043
+ }
12044
+
12045
+ var xLineValue = getLineValue(me, index, gridLines.offsetGridLines && ticks.length > 1);
12046
+ if (xLineValue < me.left) {
12047
+ lineColor = 'rgba(0,0,0,0)';
12048
+ }
12049
+ xLineValue += helpers.aliasPixel(lineWidth);
12050
+
12051
+ labelX = me.getPixelForTick(index) + optionTicks.labelOffset; // x values for optionTicks (need to consider offsetLabel option)
12052
+
12053
+ tx1 = tx2 = x1 = x2 = xLineValue;
12054
+ ty1 = yTickStart;
12055
+ ty2 = yTickEnd;
12056
+ y1 = chartArea.top;
12057
+ y2 = chartArea.bottom;
12058
+ } else {
12059
+ var isLeft = options.position === 'left';
12060
+ var labelXOffset;
12061
+
12062
+ if (optionTicks.mirror) {
12063
+ textAlign = isLeft ? 'left' : 'right';
12064
+ labelXOffset = tickPadding;
12065
+ } else {
12066
+ textAlign = isLeft ? 'right' : 'left';
12067
+ labelXOffset = tl + tickPadding;
12068
+ }
12069
+
12070
+ labelX = isLeft ? me.right - labelXOffset : me.left + labelXOffset;
12071
+
12072
+ var yLineValue = getLineValue(me, index, gridLines.offsetGridLines && ticks.length > 1);
12073
+ if (yLineValue < me.top) {
12074
+ lineColor = 'rgba(0,0,0,0)';
12075
+ }
12076
+ yLineValue += helpers.aliasPixel(lineWidth);
12077
+
12078
+ labelY = me.getPixelForTick(index) + optionTicks.labelOffset;
12079
+
12080
+ tx1 = xTickStart;
12081
+ tx2 = xTickEnd;
12082
+ x1 = chartArea.left;
12083
+ x2 = chartArea.right;
12084
+ ty1 = ty2 = y1 = y2 = yLineValue;
12085
+ }
12086
+
12087
+ itemsToDraw.push({
12088
+ tx1: tx1,
12089
+ ty1: ty1,
12090
+ tx2: tx2,
12091
+ ty2: ty2,
12092
+ x1: x1,
12093
+ y1: y1,
12094
+ x2: x2,
12095
+ y2: y2,
12096
+ labelX: labelX,
12097
+ labelY: labelY,
12098
+ glWidth: lineWidth,
12099
+ glColor: lineColor,
12100
+ glBorderDash: borderDash,
12101
+ glBorderDashOffset: borderDashOffset,
12102
+ rotation: -1 * labelRotationRadians,
12103
+ label: label,
12104
+ major: tick.major,
12105
+ textBaseline: textBaseline,
12106
+ textAlign: textAlign
12107
+ });
12108
+ });
12109
+
12110
+ // Draw all of the tick labels, tick marks, and grid lines at the correct places
12111
+ helpers.each(itemsToDraw, function(itemToDraw) {
12112
+ if (gridLines.display) {
12113
+ context.save();
12114
+ context.lineWidth = itemToDraw.glWidth;
12115
+ context.strokeStyle = itemToDraw.glColor;
12116
+ if (context.setLineDash) {
12117
+ context.setLineDash(itemToDraw.glBorderDash);
12118
+ context.lineDashOffset = itemToDraw.glBorderDashOffset;
12119
+ }
12120
+
12121
+ context.beginPath();
12122
+
12123
+ if (gridLines.drawTicks) {
12124
+ context.moveTo(itemToDraw.tx1, itemToDraw.ty1);
12125
+ context.lineTo(itemToDraw.tx2, itemToDraw.ty2);
12126
+ }
12127
+
12128
+ if (gridLines.drawOnChartArea) {
12129
+ context.moveTo(itemToDraw.x1, itemToDraw.y1);
12130
+ context.lineTo(itemToDraw.x2, itemToDraw.y2);
12131
+ }
12132
+
12133
+ context.stroke();
12134
+ context.restore();
12135
+ }
12136
+
12137
+ if (optionTicks.display) {
12138
+ // Make sure we draw text in the correct color and font
12139
+ context.save();
12140
+ context.translate(itemToDraw.labelX, itemToDraw.labelY);
12141
+ context.rotate(itemToDraw.rotation);
12142
+ context.font = itemToDraw.major ? majorTickFont.font : tickFont.font;
12143
+ context.fillStyle = itemToDraw.major ? majorTickFontColor : tickFontColor;
12144
+ context.textBaseline = itemToDraw.textBaseline;
12145
+ context.textAlign = itemToDraw.textAlign;
12146
+
12147
+ var label = itemToDraw.label;
12148
+ if (helpers.isArray(label)) {
12149
+ for (var i = 0, y = 0; i < label.length; ++i) {
12150
+ // We just make sure the multiline element is a string here..
12151
+ context.fillText('' + label[i], 0, y);
12152
+ // apply same lineSpacing as calculated @ L#320
12153
+ y += (tickFont.size * 1.5);
12154
+ }
12155
+ } else {
12156
+ context.fillText(label, 0, 0);
12157
+ }
12158
+ context.restore();
12159
+ }
12160
+ });
12161
+
12162
+ if (scaleLabel.display) {
12163
+ // Draw the scale label
12164
+ var scaleLabelX;
12165
+ var scaleLabelY;
12166
+ var rotation = 0;
12167
+ var halfLineHeight = parseLineHeight(scaleLabel) / 2;
12168
+
12169
+ if (isHorizontal) {
12170
+ scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width
12171
+ scaleLabelY = options.position === 'bottom'
12172
+ ? me.bottom - halfLineHeight - scaleLabelPadding.bottom
12173
+ : me.top + halfLineHeight + scaleLabelPadding.top;
12174
+ } else {
12175
+ var isLeft = options.position === 'left';
12176
+ scaleLabelX = isLeft
12177
+ ? me.left + halfLineHeight + scaleLabelPadding.top
12178
+ : me.right - halfLineHeight - scaleLabelPadding.top;
12179
+ scaleLabelY = me.top + ((me.bottom - me.top) / 2);
12180
+ rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI;
12181
+ }
12182
+
12183
+ context.save();
12184
+ context.translate(scaleLabelX, scaleLabelY);
12185
+ context.rotate(rotation);
12186
+ context.textAlign = 'center';
12187
+ context.textBaseline = 'middle';
12188
+ context.fillStyle = scaleLabelFontColor; // render in correct colour
12189
+ context.font = scaleLabelFont.font;
12190
+ context.fillText(scaleLabel.labelString, 0, 0);
12191
+ context.restore();
12192
+ }
12193
+
12194
+ if (gridLines.drawBorder) {
12195
+ // Draw the line at the edge of the axis
12196
+ context.lineWidth = helpers.valueAtIndexOrDefault(gridLines.lineWidth, 0);
12197
+ context.strokeStyle = helpers.valueAtIndexOrDefault(gridLines.color, 0);
12198
+ var x1 = me.left;
12199
+ var x2 = me.right;
12200
+ var y1 = me.top;
12201
+ var y2 = me.bottom;
12202
+
12203
+ var aliasPixel = helpers.aliasPixel(context.lineWidth);
12204
+ if (isHorizontal) {
12205
+ y1 = y2 = options.position === 'top' ? me.bottom : me.top;
12206
+ y1 += aliasPixel;
12207
+ y2 += aliasPixel;
12208
+ } else {
12209
+ x1 = x2 = options.position === 'left' ? me.right : me.left;
12210
+ x1 += aliasPixel;
12211
+ x2 += aliasPixel;
12212
+ }
12213
+
12214
+ context.beginPath();
12215
+ context.moveTo(x1, y1);
12216
+ context.lineTo(x2, y2);
12217
+ context.stroke();
12218
+ }
12219
+ }
12220
+ });
12221
+ };
12222
+
12223
+ },{"25":25,"26":26,"34":34,"45":45}],33:[function(require,module,exports){
12224
+ 'use strict';
12225
+
12226
+ var defaults = require(25);
12227
+ var helpers = require(45);
12228
+
12229
+ module.exports = function(Chart) {
12230
+
12231
+ Chart.scaleService = {
12232
+ // Scale registration object. Extensions can register new scale types (such as log or DB scales) and then
12233
+ // use the new chart options to grab the correct scale
12234
+ constructors: {},
12235
+ // Use a registration function so that we can move to an ES6 map when we no longer need to support
12236
+ // old browsers
12237
+
12238
+ // Scale config defaults
12239
+ defaults: {},
12240
+ registerScaleType: function(type, scaleConstructor, scaleDefaults) {
12241
+ this.constructors[type] = scaleConstructor;
12242
+ this.defaults[type] = helpers.clone(scaleDefaults);
12243
+ },
12244
+ getScaleConstructor: function(type) {
12245
+ return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined;
12246
+ },
12247
+ getScaleDefaults: function(type) {
12248
+ // Return the scale defaults merged with the global settings so that we always use the latest ones
12249
+ return this.defaults.hasOwnProperty(type) ? helpers.merge({}, [defaults.scale, this.defaults[type]]) : {};
12250
+ },
12251
+ updateScaleDefaults: function(type, additions) {
12252
+ var me = this;
12253
+ if (me.defaults.hasOwnProperty(type)) {
12254
+ me.defaults[type] = helpers.extend(me.defaults[type], additions);
12255
+ }
12256
+ },
12257
+ addScalesToLayout: function(chart) {
12258
+ // Adds each scale to the chart.boxes array to be sized accordingly
12259
+ helpers.each(chart.scales, function(scale) {
12260
+ // Set ILayoutItem parameters for backwards compatibility
12261
+ scale.fullWidth = scale.options.fullWidth;
12262
+ scale.position = scale.options.position;
12263
+ scale.weight = scale.options.weight;
12264
+ Chart.layoutService.addBox(chart, scale);
12265
+ });
12266
+ }
12267
+ };
12268
+ };
12269
+
12270
+ },{"25":25,"45":45}],34:[function(require,module,exports){
12271
+ 'use strict';
12272
+
12273
+ var helpers = require(45);
12274
+
12275
+ /**
12276
+ * Namespace to hold static tick generation functions
12277
+ * @namespace Chart.Ticks
12278
+ */
12279
+ module.exports = {
12280
+ /**
12281
+ * Namespace to hold generators for different types of ticks
12282
+ * @namespace Chart.Ticks.generators
12283
+ */
12284
+ generators: {
12285
+ /**
12286
+ * Interface for the options provided to the numeric tick generator
12287
+ * @interface INumericTickGenerationOptions
12288
+ */
12289
+ /**
12290
+ * The maximum number of ticks to display
12291
+ * @name INumericTickGenerationOptions#maxTicks
12292
+ * @type Number
12293
+ */
12294
+ /**
12295
+ * The distance between each tick.
12296
+ * @name INumericTickGenerationOptions#stepSize
12297
+ * @type Number
12298
+ * @optional
12299
+ */
12300
+ /**
12301
+ * Forced minimum for the ticks. If not specified, the minimum of the data range is used to calculate the tick minimum
12302
+ * @name INumericTickGenerationOptions#min
12303
+ * @type Number
12304
+ * @optional
12305
+ */
12306
+ /**
12307
+ * The maximum value of the ticks. If not specified, the maximum of the data range is used to calculate the tick maximum
12308
+ * @name INumericTickGenerationOptions#max
12309
+ * @type Number
12310
+ * @optional
12311
+ */
12312
+
12313
+ /**
12314
+ * Generate a set of linear ticks
12315
+ * @method Chart.Ticks.generators.linear
12316
+ * @param generationOptions {INumericTickGenerationOptions} the options used to generate the ticks
12317
+ * @param dataRange {IRange} the range of the data
12318
+ * @returns {Array<Number>} array of tick values
12319
+ */
12320
+ linear: function(generationOptions, dataRange) {
12321
+ var ticks = [];
12322
+ // To get a "nice" value for the tick spacing, we will use the appropriately named
12323
+ // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
12324
+ // for details.
12325
+
12326
+ var spacing;
12327
+ if (generationOptions.stepSize && generationOptions.stepSize > 0) {
12328
+ spacing = generationOptions.stepSize;
12329
+ } else {
12330
+ var niceRange = helpers.niceNum(dataRange.max - dataRange.min, false);
12331
+ spacing = helpers.niceNum(niceRange / (generationOptions.maxTicks - 1), true);
12332
+ }
12333
+ var niceMin = Math.floor(dataRange.min / spacing) * spacing;
12334
+ var niceMax = Math.ceil(dataRange.max / spacing) * spacing;
12335
+
12336
+ // If min, max and stepSize is set and they make an evenly spaced scale use it.
12337
+ if (generationOptions.min && generationOptions.max && generationOptions.stepSize) {
12338
+ // If very close to our whole number, use it.
12339
+ if (helpers.almostWhole((generationOptions.max - generationOptions.min) / generationOptions.stepSize, spacing / 1000)) {
12340
+ niceMin = generationOptions.min;
12341
+ niceMax = generationOptions.max;
12342
+ }
12343
+ }
12344
+
12345
+ var numSpaces = (niceMax - niceMin) / spacing;
12346
+ // If very close to our rounded value, use it.
12347
+ if (helpers.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) {
12348
+ numSpaces = Math.round(numSpaces);
12349
+ } else {
12350
+ numSpaces = Math.ceil(numSpaces);
12351
+ }
12352
+
12353
+ // Put the values into the ticks array
12354
+ ticks.push(generationOptions.min !== undefined ? generationOptions.min : niceMin);
12355
+ for (var j = 1; j < numSpaces; ++j) {
12356
+ ticks.push(niceMin + (j * spacing));
12357
+ }
12358
+ ticks.push(generationOptions.max !== undefined ? generationOptions.max : niceMax);
12359
+
12360
+ return ticks;
12361
+ },
12362
+
12363
+ /**
12364
+ * Generate a set of logarithmic ticks
12365
+ * @method Chart.Ticks.generators.logarithmic
12366
+ * @param generationOptions {INumericTickGenerationOptions} the options used to generate the ticks
12367
+ * @param dataRange {IRange} the range of the data
12368
+ * @returns {Array<Number>} array of tick values
12369
+ */
12370
+ logarithmic: function(generationOptions, dataRange) {
12371
+ var ticks = [];
12372
+ var valueOrDefault = helpers.valueOrDefault;
12373
+
12374
+ // Figure out what the max number of ticks we can support it is based on the size of
12375
+ // the axis area. For now, we say that the minimum tick spacing in pixels must be 50
12376
+ // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
12377
+ // the graph
12378
+ var tickVal = valueOrDefault(generationOptions.min, Math.pow(10, Math.floor(helpers.log10(dataRange.min))));
12379
+
12380
+ var endExp = Math.floor(helpers.log10(dataRange.max));
12381
+ var endSignificand = Math.ceil(dataRange.max / Math.pow(10, endExp));
12382
+ var exp, significand;
12383
+
12384
+ if (tickVal === 0) {
12385
+ exp = Math.floor(helpers.log10(dataRange.minNotZero));
12386
+ significand = Math.floor(dataRange.minNotZero / Math.pow(10, exp));
12387
+
12388
+ ticks.push(tickVal);
12389
+ tickVal = significand * Math.pow(10, exp);
12390
+ } else {
12391
+ exp = Math.floor(helpers.log10(tickVal));
12392
+ significand = Math.floor(tickVal / Math.pow(10, exp));
12393
+ }
12394
+
12395
+ do {
12396
+ ticks.push(tickVal);
12397
+
12398
+ ++significand;
12399
+ if (significand === 10) {
12400
+ significand = 1;
12401
+ ++exp;
12402
+ }
12403
+
12404
+ tickVal = significand * Math.pow(10, exp);
12405
+ } while (exp < endExp || (exp === endExp && significand < endSignificand));
12406
+
12407
+ var lastTick = valueOrDefault(generationOptions.max, tickVal);
12408
+ ticks.push(lastTick);
12409
+
12410
+ return ticks;
12411
+ }
12412
+ },
12413
+
12414
+ /**
12415
+ * Namespace to hold formatters for different types of ticks
12416
+ * @namespace Chart.Ticks.formatters
12417
+ */
12418
+ formatters: {
12419
+ /**
12420
+ * Formatter for value labels
12421
+ * @method Chart.Ticks.formatters.values
12422
+ * @param value the value to display
12423
+ * @return {String|Array} the label to display
12424
+ */
12425
+ values: function(value) {
12426
+ return helpers.isArray(value) ? value : '' + value;
12427
+ },
12428
+
12429
+ /**
12430
+ * Formatter for linear numeric ticks
12431
+ * @method Chart.Ticks.formatters.linear
12432
+ * @param tickValue {Number} the value to be formatted
12433
+ * @param index {Number} the position of the tickValue parameter in the ticks array
12434
+ * @param ticks {Array<Number>} the list of ticks being converted
12435
+ * @return {String} string representation of the tickValue parameter
12436
+ */
12437
+ linear: function(tickValue, index, ticks) {
12438
+ // If we have lots of ticks, don't use the ones
12439
+ var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0];
12440
+
12441
+ // If we have a number like 2.5 as the delta, figure out how many decimal places we need
12442
+ if (Math.abs(delta) > 1) {
12443
+ if (tickValue !== Math.floor(tickValue)) {
12444
+ // not an integer
12445
+ delta = tickValue - Math.floor(tickValue);
12446
+ }
12447
+ }
12448
+
12449
+ var logDelta = helpers.log10(Math.abs(delta));
12450
+ var tickString = '';
12451
+
12452
+ if (tickValue !== 0) {
12453
+ var numDecimal = -1 * Math.floor(logDelta);
12454
+ numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places
12455
+ tickString = tickValue.toFixed(numDecimal);
12456
+ } else {
12457
+ tickString = '0'; // never show decimal places for 0
12458
+ }
12459
+
12460
+ return tickString;
12461
+ },
12462
+
12463
+ logarithmic: function(tickValue, index, ticks) {
12464
+ var remain = tickValue / (Math.pow(10, Math.floor(helpers.log10(tickValue))));
12465
+
12466
+ if (tickValue === 0) {
12467
+ return '0';
12468
+ } else if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === ticks.length - 1) {
12469
+ return tickValue.toExponential();
12470
+ }
12471
+ return '';
12472
+ }
12473
+ }
12474
+ };
12475
+
12476
+ },{"45":45}],35:[function(require,module,exports){
12477
+ 'use strict';
12478
+
12479
+ var defaults = require(25);
12480
+ var Element = require(26);
12481
+ var helpers = require(45);
12482
+
12483
+ defaults._set('global', {
12484
+ tooltips: {
12485
+ enabled: true,
12486
+ custom: null,
12487
+ mode: 'nearest',
12488
+ position: 'average',
12489
+ intersect: true,
12490
+ backgroundColor: 'rgba(0,0,0,0.8)',
12491
+ titleFontStyle: 'bold',
12492
+ titleSpacing: 2,
12493
+ titleMarginBottom: 6,
12494
+ titleFontColor: '#fff',
12495
+ titleAlign: 'left',
12496
+ bodySpacing: 2,
12497
+ bodyFontColor: '#fff',
12498
+ bodyAlign: 'left',
12499
+ footerFontStyle: 'bold',
12500
+ footerSpacing: 2,
12501
+ footerMarginTop: 6,
12502
+ footerFontColor: '#fff',
12503
+ footerAlign: 'left',
12504
+ yPadding: 6,
12505
+ xPadding: 6,
12506
+ caretPadding: 2,
12507
+ caretSize: 5,
12508
+ cornerRadius: 6,
12509
+ multiKeyBackground: '#fff',
12510
+ displayColors: true,
12511
+ borderColor: 'rgba(0,0,0,0)',
12512
+ borderWidth: 0,
12513
+ callbacks: {
12514
+ // Args are: (tooltipItems, data)
12515
+ beforeTitle: helpers.noop,
12516
+ title: function(tooltipItems, data) {
12517
+ // Pick first xLabel for now
12518
+ var title = '';
12519
+ var labels = data.labels;
12520
+ var labelCount = labels ? labels.length : 0;
12521
+
12522
+ if (tooltipItems.length > 0) {
12523
+ var item = tooltipItems[0];
12524
+
12525
+ if (item.xLabel) {
12526
+ title = item.xLabel;
12527
+ } else if (labelCount > 0 && item.index < labelCount) {
12528
+ title = labels[item.index];
12529
+ }
12530
+ }
12531
+
12532
+ return title;
12533
+ },
12534
+ afterTitle: helpers.noop,
12535
+
12536
+ // Args are: (tooltipItems, data)
12537
+ beforeBody: helpers.noop,
12538
+
12539
+ // Args are: (tooltipItem, data)
12540
+ beforeLabel: helpers.noop,
12541
+ label: function(tooltipItem, data) {
12542
+ var label = data.datasets[tooltipItem.datasetIndex].label || '';
12543
+
12544
+ if (label) {
12545
+ label += ': ';
12546
+ }
12547
+ label += tooltipItem.yLabel;
12548
+ return label;
12549
+ },
12550
+ labelColor: function(tooltipItem, chart) {
12551
+ var meta = chart.getDatasetMeta(tooltipItem.datasetIndex);
12552
+ var activeElement = meta.data[tooltipItem.index];
12553
+ var view = activeElement._view;
12554
+ return {
12555
+ borderColor: view.borderColor,
12556
+ backgroundColor: view.backgroundColor
12557
+ };
12558
+ },
12559
+ labelTextColor: function() {
12560
+ return this._options.bodyFontColor;
12561
+ },
12562
+ afterLabel: helpers.noop,
12563
+
12564
+ // Args are: (tooltipItems, data)
12565
+ afterBody: helpers.noop,
12566
+
12567
+ // Args are: (tooltipItems, data)
12568
+ beforeFooter: helpers.noop,
12569
+ footer: helpers.noop,
12570
+ afterFooter: helpers.noop
12571
+ }
12572
+ }
12573
+ });
12574
+
12575
+ module.exports = function(Chart) {
12576
+
12577
+ /**
12578
+ * Helper method to merge the opacity into a color
12579
+ */
12580
+ function mergeOpacity(colorString, opacity) {
12581
+ var color = helpers.color(colorString);
12582
+ return color.alpha(opacity * color.alpha()).rgbaString();
12583
+ }
12584
+
12585
+ // Helper to push or concat based on if the 2nd parameter is an array or not
12586
+ function pushOrConcat(base, toPush) {
12587
+ if (toPush) {
12588
+ if (helpers.isArray(toPush)) {
12589
+ // base = base.concat(toPush);
12590
+ Array.prototype.push.apply(base, toPush);
12591
+ } else {
12592
+ base.push(toPush);
12593
+ }
12594
+ }
12595
+
12596
+ return base;
12597
+ }
12598
+
12599
+ // Private helper to create a tooltip item model
12600
+ // @param element : the chart element (point, arc, bar) to create the tooltip item for
12601
+ // @return : new tooltip item
12602
+ function createTooltipItem(element) {
12603
+ var xScale = element._xScale;
12604
+ var yScale = element._yScale || element._scale; // handle radar || polarArea charts
12605
+ var index = element._index;
12606
+ var datasetIndex = element._datasetIndex;
12607
+
12608
+ return {
12609
+ xLabel: xScale ? xScale.getLabelForIndex(index, datasetIndex) : '',
12610
+ yLabel: yScale ? yScale.getLabelForIndex(index, datasetIndex) : '',
12611
+ index: index,
12612
+ datasetIndex: datasetIndex,
12613
+ x: element._model.x,
12614
+ y: element._model.y
12615
+ };
12616
+ }
12617
+
12618
+ /**
12619
+ * Helper to get the reset model for the tooltip
12620
+ * @param tooltipOpts {Object} the tooltip options
12621
+ */
12622
+ function getBaseModel(tooltipOpts) {
12623
+ var globalDefaults = defaults.global;
12624
+ var valueOrDefault = helpers.valueOrDefault;
12625
+
12626
+ return {
12627
+ // Positioning
12628
+ xPadding: tooltipOpts.xPadding,
12629
+ yPadding: tooltipOpts.yPadding,
12630
+ xAlign: tooltipOpts.xAlign,
12631
+ yAlign: tooltipOpts.yAlign,
12632
+
12633
+ // Body
12634
+ bodyFontColor: tooltipOpts.bodyFontColor,
12635
+ _bodyFontFamily: valueOrDefault(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily),
12636
+ _bodyFontStyle: valueOrDefault(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle),
12637
+ _bodyAlign: tooltipOpts.bodyAlign,
12638
+ bodyFontSize: valueOrDefault(tooltipOpts.bodyFontSize, globalDefaults.defaultFontSize),
12639
+ bodySpacing: tooltipOpts.bodySpacing,
12640
+
12641
+ // Title
12642
+ titleFontColor: tooltipOpts.titleFontColor,
12643
+ _titleFontFamily: valueOrDefault(tooltipOpts.titleFontFamily, globalDefaults.defaultFontFamily),
12644
+ _titleFontStyle: valueOrDefault(tooltipOpts.titleFontStyle, globalDefaults.defaultFontStyle),
12645
+ titleFontSize: valueOrDefault(tooltipOpts.titleFontSize, globalDefaults.defaultFontSize),
12646
+ _titleAlign: tooltipOpts.titleAlign,
12647
+ titleSpacing: tooltipOpts.titleSpacing,
12648
+ titleMarginBottom: tooltipOpts.titleMarginBottom,
12649
+
12650
+ // Footer
12651
+ footerFontColor: tooltipOpts.footerFontColor,
12652
+ _footerFontFamily: valueOrDefault(tooltipOpts.footerFontFamily, globalDefaults.defaultFontFamily),
12653
+ _footerFontStyle: valueOrDefault(tooltipOpts.footerFontStyle, globalDefaults.defaultFontStyle),
12654
+ footerFontSize: valueOrDefault(tooltipOpts.footerFontSize, globalDefaults.defaultFontSize),
12655
+ _footerAlign: tooltipOpts.footerAlign,
12656
+ footerSpacing: tooltipOpts.footerSpacing,
12657
+ footerMarginTop: tooltipOpts.footerMarginTop,
12658
+
12659
+ // Appearance
12660
+ caretSize: tooltipOpts.caretSize,
12661
+ cornerRadius: tooltipOpts.cornerRadius,
12662
+ backgroundColor: tooltipOpts.backgroundColor,
12663
+ opacity: 0,
12664
+ legendColorBackground: tooltipOpts.multiKeyBackground,
12665
+ displayColors: tooltipOpts.displayColors,
12666
+ borderColor: tooltipOpts.borderColor,
12667
+ borderWidth: tooltipOpts.borderWidth
12668
+ };
12669
+ }
12670
+
12671
+ /**
12672
+ * Get the size of the tooltip
12673
+ */
12674
+ function getTooltipSize(tooltip, model) {
12675
+ var ctx = tooltip._chart.ctx;
12676
+
12677
+ var height = model.yPadding * 2; // Tooltip Padding
12678
+ var width = 0;
12679
+
12680
+ // Count of all lines in the body
12681
+ var body = model.body;
12682
+ var combinedBodyLength = body.reduce(function(count, bodyItem) {
12683
+ return count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length;
12684
+ }, 0);
12685
+ combinedBodyLength += model.beforeBody.length + model.afterBody.length;
12686
+
12687
+ var titleLineCount = model.title.length;
12688
+ var footerLineCount = model.footer.length;
12689
+ var titleFontSize = model.titleFontSize;
12690
+ var bodyFontSize = model.bodyFontSize;
12691
+ var footerFontSize = model.footerFontSize;
12692
+
12693
+ height += titleLineCount * titleFontSize; // Title Lines
12694
+ height += titleLineCount ? (titleLineCount - 1) * model.titleSpacing : 0; // Title Line Spacing
12695
+ height += titleLineCount ? model.titleMarginBottom : 0; // Title's bottom Margin
12696
+ height += combinedBodyLength * bodyFontSize; // Body Lines
12697
+ height += combinedBodyLength ? (combinedBodyLength - 1) * model.bodySpacing : 0; // Body Line Spacing
12698
+ height += footerLineCount ? model.footerMarginTop : 0; // Footer Margin
12699
+ height += footerLineCount * (footerFontSize); // Footer Lines
12700
+ height += footerLineCount ? (footerLineCount - 1) * model.footerSpacing : 0; // Footer Line Spacing
12701
+
12702
+ // Title width
12703
+ var widthPadding = 0;
12704
+ var maxLineWidth = function(line) {
12705
+ width = Math.max(width, ctx.measureText(line).width + widthPadding);
12706
+ };
12707
+
12708
+ ctx.font = helpers.fontString(titleFontSize, model._titleFontStyle, model._titleFontFamily);
12709
+ helpers.each(model.title, maxLineWidth);
12710
+
12711
+ // Body width
12712
+ ctx.font = helpers.fontString(bodyFontSize, model._bodyFontStyle, model._bodyFontFamily);
12713
+ helpers.each(model.beforeBody.concat(model.afterBody), maxLineWidth);
12714
+
12715
+ // Body lines may include some extra width due to the color box
12716
+ widthPadding = model.displayColors ? (bodyFontSize + 2) : 0;
12717
+ helpers.each(body, function(bodyItem) {
12718
+ helpers.each(bodyItem.before, maxLineWidth);
12719
+ helpers.each(bodyItem.lines, maxLineWidth);
12720
+ helpers.each(bodyItem.after, maxLineWidth);
12721
+ });
12722
+
12723
+ // Reset back to 0
12724
+ widthPadding = 0;
12725
+
12726
+ // Footer width
12727
+ ctx.font = helpers.fontString(footerFontSize, model._footerFontStyle, model._footerFontFamily);
12728
+ helpers.each(model.footer, maxLineWidth);
12729
+
12730
+ // Add padding
12731
+ width += 2 * model.xPadding;
12732
+
12733
+ return {
12734
+ width: width,
12735
+ height: height
12736
+ };
12737
+ }
12738
+
12739
+ /**
12740
+ * Helper to get the alignment of a tooltip given the size
12741
+ */
12742
+ function determineAlignment(tooltip, size) {
12743
+ var model = tooltip._model;
12744
+ var chart = tooltip._chart;
12745
+ var chartArea = tooltip._chart.chartArea;
12746
+ var xAlign = 'center';
12747
+ var yAlign = 'center';
12748
+
12749
+ if (model.y < size.height) {
12750
+ yAlign = 'top';
12751
+ } else if (model.y > (chart.height - size.height)) {
12752
+ yAlign = 'bottom';
12753
+ }
12754
+
12755
+ var lf, rf; // functions to determine left, right alignment
12756
+ var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart
12757
+ var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges
12758
+ var midX = (chartArea.left + chartArea.right) / 2;
12759
+ var midY = (chartArea.top + chartArea.bottom) / 2;
12760
+
12761
+ if (yAlign === 'center') {
12762
+ lf = function(x) {
12763
+ return x <= midX;
12764
+ };
12765
+ rf = function(x) {
12766
+ return x > midX;
12767
+ };
12768
+ } else {
12769
+ lf = function(x) {
12770
+ return x <= (size.width / 2);
12771
+ };
12772
+ rf = function(x) {
12773
+ return x >= (chart.width - (size.width / 2));
12774
+ };
12775
+ }
12776
+
12777
+ olf = function(x) {
12778
+ return x + size.width > chart.width;
12779
+ };
12780
+ orf = function(x) {
12781
+ return x - size.width < 0;
12782
+ };
12783
+ yf = function(y) {
12784
+ return y <= midY ? 'top' : 'bottom';
12785
+ };
12786
+
12787
+ if (lf(model.x)) {
12788
+ xAlign = 'left';
12789
+
12790
+ // Is tooltip too wide and goes over the right side of the chart.?
12791
+ if (olf(model.x)) {
12792
+ xAlign = 'center';
12793
+ yAlign = yf(model.y);
12794
+ }
12795
+ } else if (rf(model.x)) {
12796
+ xAlign = 'right';
12797
+
12798
+ // Is tooltip too wide and goes outside left edge of canvas?
12799
+ if (orf(model.x)) {
12800
+ xAlign = 'center';
12801
+ yAlign = yf(model.y);
12802
+ }
12803
+ }
12804
+
12805
+ var opts = tooltip._options;
12806
+ return {
12807
+ xAlign: opts.xAlign ? opts.xAlign : xAlign,
12808
+ yAlign: opts.yAlign ? opts.yAlign : yAlign
12809
+ };
12810
+ }
12811
+
12812
+ /**
12813
+ * @Helper to get the location a tooltip needs to be placed at given the initial position (via the vm) and the size and alignment
12814
+ */
12815
+ function getBackgroundPoint(vm, size, alignment) {
12816
+ // Background Position
12817
+ var x = vm.x;
12818
+ var y = vm.y;
12819
+
12820
+ var caretSize = vm.caretSize;
12821
+ var caretPadding = vm.caretPadding;
12822
+ var cornerRadius = vm.cornerRadius;
12823
+ var xAlign = alignment.xAlign;
12824
+ var yAlign = alignment.yAlign;
12825
+ var paddingAndSize = caretSize + caretPadding;
12826
+ var radiusAndPadding = cornerRadius + caretPadding;
12827
+
12828
+ if (xAlign === 'right') {
12829
+ x -= size.width;
12830
+ } else if (xAlign === 'center') {
12831
+ x -= (size.width / 2);
12832
+ }
12833
+
12834
+ if (yAlign === 'top') {
12835
+ y += paddingAndSize;
12836
+ } else if (yAlign === 'bottom') {
12837
+ y -= size.height + paddingAndSize;
12838
+ } else {
12839
+ y -= (size.height / 2);
12840
+ }
12841
+
12842
+ if (yAlign === 'center') {
12843
+ if (xAlign === 'left') {
12844
+ x += paddingAndSize;
12845
+ } else if (xAlign === 'right') {
12846
+ x -= paddingAndSize;
12847
+ }
12848
+ } else if (xAlign === 'left') {
12849
+ x -= radiusAndPadding;
12850
+ } else if (xAlign === 'right') {
12851
+ x += radiusAndPadding;
12852
+ }
12853
+
12854
+ return {
12855
+ x: x,
12856
+ y: y
12857
+ };
12858
+ }
12859
+
12860
+ Chart.Tooltip = Element.extend({
12861
+ initialize: function() {
12862
+ this._model = getBaseModel(this._options);
12863
+ },
12864
+
12865
+ // Get the title
12866
+ // Args are: (tooltipItem, data)
12867
+ getTitle: function() {
12868
+ var me = this;
12869
+ var opts = me._options;
12870
+ var callbacks = opts.callbacks;
12871
+
12872
+ var beforeTitle = callbacks.beforeTitle.apply(me, arguments);
12873
+ var title = callbacks.title.apply(me, arguments);
12874
+ var afterTitle = callbacks.afterTitle.apply(me, arguments);
12875
+
12876
+ var lines = [];
12877
+ lines = pushOrConcat(lines, beforeTitle);
12878
+ lines = pushOrConcat(lines, title);
12879
+ lines = pushOrConcat(lines, afterTitle);
12880
+
12881
+ return lines;
12882
+ },
12883
+
12884
+ // Args are: (tooltipItem, data)
12885
+ getBeforeBody: function() {
12886
+ var lines = this._options.callbacks.beforeBody.apply(this, arguments);
12887
+ return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : [];
12888
+ },
12889
+
12890
+ // Args are: (tooltipItem, data)
12891
+ getBody: function(tooltipItems, data) {
12892
+ var me = this;
12893
+ var callbacks = me._options.callbacks;
12894
+ var bodyItems = [];
12895
+
12896
+ helpers.each(tooltipItems, function(tooltipItem) {
12897
+ var bodyItem = {
12898
+ before: [],
12899
+ lines: [],
12900
+ after: []
12901
+ };
12902
+ pushOrConcat(bodyItem.before, callbacks.beforeLabel.call(me, tooltipItem, data));
12903
+ pushOrConcat(bodyItem.lines, callbacks.label.call(me, tooltipItem, data));
12904
+ pushOrConcat(bodyItem.after, callbacks.afterLabel.call(me, tooltipItem, data));
12905
+
12906
+ bodyItems.push(bodyItem);
12907
+ });
12908
+
12909
+ return bodyItems;
12910
+ },
12911
+
12912
+ // Args are: (tooltipItem, data)
12913
+ getAfterBody: function() {
12914
+ var lines = this._options.callbacks.afterBody.apply(this, arguments);
12915
+ return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : [];
12916
+ },
12917
+
12918
+ // Get the footer and beforeFooter and afterFooter lines
12919
+ // Args are: (tooltipItem, data)
12920
+ getFooter: function() {
12921
+ var me = this;
12922
+ var callbacks = me._options.callbacks;
12923
+
12924
+ var beforeFooter = callbacks.beforeFooter.apply(me, arguments);
12925
+ var footer = callbacks.footer.apply(me, arguments);
12926
+ var afterFooter = callbacks.afterFooter.apply(me, arguments);
12927
+
12928
+ var lines = [];
12929
+ lines = pushOrConcat(lines, beforeFooter);
12930
+ lines = pushOrConcat(lines, footer);
12931
+ lines = pushOrConcat(lines, afterFooter);
12932
+
12933
+ return lines;
12934
+ },
12935
+
12936
+ update: function(changed) {
12937
+ var me = this;
12938
+ var opts = me._options;
12939
+
12940
+ // Need to regenerate the model because its faster than using extend and it is necessary due to the optimization in Chart.Element.transition
12941
+ // that does _view = _model if ease === 1. This causes the 2nd tooltip update to set properties in both the view and model at the same time
12942
+ // which breaks any animations.
12943
+ var existingModel = me._model;
12944
+ var model = me._model = getBaseModel(opts);
12945
+ var active = me._active;
12946
+
12947
+ var data = me._data;
12948
+
12949
+ // In the case where active.length === 0 we need to keep these at existing values for good animations
12950
+ var alignment = {
12951
+ xAlign: existingModel.xAlign,
12952
+ yAlign: existingModel.yAlign
12953
+ };
12954
+ var backgroundPoint = {
12955
+ x: existingModel.x,
12956
+ y: existingModel.y
12957
+ };
12958
+ var tooltipSize = {
12959
+ width: existingModel.width,
12960
+ height: existingModel.height
12961
+ };
12962
+ var tooltipPosition = {
12963
+ x: existingModel.caretX,
12964
+ y: existingModel.caretY
12965
+ };
12966
+
12967
+ var i, len;
12968
+
12969
+ if (active.length) {
12970
+ model.opacity = 1;
12971
+
12972
+ var labelColors = [];
12973
+ var labelTextColors = [];
12974
+ tooltipPosition = Chart.Tooltip.positioners[opts.position](active, me._eventPosition);
12975
+
12976
+ var tooltipItems = [];
12977
+ for (i = 0, len = active.length; i < len; ++i) {
12978
+ tooltipItems.push(createTooltipItem(active[i]));
12979
+ }
12980
+
12981
+ // If the user provided a filter function, use it to modify the tooltip items
12982
+ if (opts.filter) {
12983
+ tooltipItems = tooltipItems.filter(function(a) {
12984
+ return opts.filter(a, data);
12985
+ });
12986
+ }
12987
+
12988
+ // If the user provided a sorting function, use it to modify the tooltip items
12989
+ if (opts.itemSort) {
12990
+ tooltipItems = tooltipItems.sort(function(a, b) {
12991
+ return opts.itemSort(a, b, data);
12992
+ });
12993
+ }
12994
+
12995
+ // Determine colors for boxes
12996
+ helpers.each(tooltipItems, function(tooltipItem) {
12997
+ labelColors.push(opts.callbacks.labelColor.call(me, tooltipItem, me._chart));
12998
+ labelTextColors.push(opts.callbacks.labelTextColor.call(me, tooltipItem, me._chart));
12999
+ });
13000
+
13001
+
13002
+ // Build the Text Lines
13003
+ model.title = me.getTitle(tooltipItems, data);
13004
+ model.beforeBody = me.getBeforeBody(tooltipItems, data);
13005
+ model.body = me.getBody(tooltipItems, data);
13006
+ model.afterBody = me.getAfterBody(tooltipItems, data);
13007
+ model.footer = me.getFooter(tooltipItems, data);
13008
+
13009
+ // Initial positioning and colors
13010
+ model.x = Math.round(tooltipPosition.x);
13011
+ model.y = Math.round(tooltipPosition.y);
13012
+ model.caretPadding = opts.caretPadding;
13013
+ model.labelColors = labelColors;
13014
+ model.labelTextColors = labelTextColors;
13015
+
13016
+ // data points
13017
+ model.dataPoints = tooltipItems;
13018
+
13019
+ // We need to determine alignment of the tooltip
13020
+ tooltipSize = getTooltipSize(this, model);
13021
+ alignment = determineAlignment(this, tooltipSize);
13022
+ // Final Size and Position
13023
+ backgroundPoint = getBackgroundPoint(model, tooltipSize, alignment);
13024
+ } else {
13025
+ model.opacity = 0;
13026
+ }
13027
+
13028
+ model.xAlign = alignment.xAlign;
13029
+ model.yAlign = alignment.yAlign;
13030
+ model.x = backgroundPoint.x;
13031
+ model.y = backgroundPoint.y;
13032
+ model.width = tooltipSize.width;
13033
+ model.height = tooltipSize.height;
13034
+
13035
+ // Point where the caret on the tooltip points to
13036
+ model.caretX = tooltipPosition.x;
13037
+ model.caretY = tooltipPosition.y;
13038
+
13039
+ me._model = model;
13040
+
13041
+ if (changed && opts.custom) {
13042
+ opts.custom.call(me, model);
13043
+ }
13044
+
13045
+ return me;
13046
+ },
13047
+ drawCaret: function(tooltipPoint, size) {
13048
+ var ctx = this._chart.ctx;
13049
+ var vm = this._view;
13050
+ var caretPosition = this.getCaretPosition(tooltipPoint, size, vm);
13051
+
13052
+ ctx.lineTo(caretPosition.x1, caretPosition.y1);
13053
+ ctx.lineTo(caretPosition.x2, caretPosition.y2);
13054
+ ctx.lineTo(caretPosition.x3, caretPosition.y3);
13055
+ },
13056
+ getCaretPosition: function(tooltipPoint, size, vm) {
13057
+ var x1, x2, x3, y1, y2, y3;
13058
+ var caretSize = vm.caretSize;
13059
+ var cornerRadius = vm.cornerRadius;
13060
+ var xAlign = vm.xAlign;
13061
+ var yAlign = vm.yAlign;
13062
+ var ptX = tooltipPoint.x;
13063
+ var ptY = tooltipPoint.y;
13064
+ var width = size.width;
13065
+ var height = size.height;
13066
+
13067
+ if (yAlign === 'center') {
13068
+ y2 = ptY + (height / 2);
13069
+
13070
+ if (xAlign === 'left') {
13071
+ x1 = ptX;
13072
+ x2 = x1 - caretSize;
13073
+ x3 = x1;
13074
+
13075
+ y1 = y2 + caretSize;
13076
+ y3 = y2 - caretSize;
13077
+ } else {
13078
+ x1 = ptX + width;
13079
+ x2 = x1 + caretSize;
13080
+ x3 = x1;
13081
+
13082
+ y1 = y2 - caretSize;
13083
+ y3 = y2 + caretSize;
13084
+ }
13085
+ } else {
13086
+ if (xAlign === 'left') {
13087
+ x2 = ptX + cornerRadius + (caretSize);
13088
+ x1 = x2 - caretSize;
13089
+ x3 = x2 + caretSize;
13090
+ } else if (xAlign === 'right') {
13091
+ x2 = ptX + width - cornerRadius - caretSize;
13092
+ x1 = x2 - caretSize;
13093
+ x3 = x2 + caretSize;
13094
+ } else {
13095
+ x2 = ptX + (width / 2);
13096
+ x1 = x2 - caretSize;
13097
+ x3 = x2 + caretSize;
13098
+ }
13099
+ if (yAlign === 'top') {
13100
+ y1 = ptY;
13101
+ y2 = y1 - caretSize;
13102
+ y3 = y1;
13103
+ } else {
13104
+ y1 = ptY + height;
13105
+ y2 = y1 + caretSize;
13106
+ y3 = y1;
13107
+ // invert drawing order
13108
+ var tmp = x3;
13109
+ x3 = x1;
13110
+ x1 = tmp;
13111
+ }
13112
+ }
13113
+ return {x1: x1, x2: x2, x3: x3, y1: y1, y2: y2, y3: y3};
13114
+ },
13115
+ drawTitle: function(pt, vm, ctx, opacity) {
13116
+ var title = vm.title;
13117
+
13118
+ if (title.length) {
13119
+ ctx.textAlign = vm._titleAlign;
13120
+ ctx.textBaseline = 'top';
13121
+
13122
+ var titleFontSize = vm.titleFontSize;
13123
+ var titleSpacing = vm.titleSpacing;
13124
+
13125
+ ctx.fillStyle = mergeOpacity(vm.titleFontColor, opacity);
13126
+ ctx.font = helpers.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily);
13127
+
13128
+ var i, len;
13129
+ for (i = 0, len = title.length; i < len; ++i) {
13130
+ ctx.fillText(title[i], pt.x, pt.y);
13131
+ pt.y += titleFontSize + titleSpacing; // Line Height and spacing
13132
+
13133
+ if (i + 1 === title.length) {
13134
+ pt.y += vm.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing
13135
+ }
13136
+ }
13137
+ }
13138
+ },
13139
+ drawBody: function(pt, vm, ctx, opacity) {
13140
+ var bodyFontSize = vm.bodyFontSize;
13141
+ var bodySpacing = vm.bodySpacing;
13142
+ var body = vm.body;
13143
+
13144
+ ctx.textAlign = vm._bodyAlign;
13145
+ ctx.textBaseline = 'top';
13146
+ ctx.font = helpers.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);
13147
+
13148
+ // Before Body
13149
+ var xLinePadding = 0;
13150
+ var fillLineOfText = function(line) {
13151
+ ctx.fillText(line, pt.x + xLinePadding, pt.y);
13152
+ pt.y += bodyFontSize + bodySpacing;
13153
+ };
13154
+
13155
+ // Before body lines
13156
+ helpers.each(vm.beforeBody, fillLineOfText);
13157
+
13158
+ var drawColorBoxes = vm.displayColors;
13159
+ xLinePadding = drawColorBoxes ? (bodyFontSize + 2) : 0;
13160
+
13161
+ // Draw body lines now
13162
+ helpers.each(body, function(bodyItem, i) {
13163
+ helpers.each(bodyItem.before, fillLineOfText);
13164
+
13165
+ helpers.each(bodyItem.lines, function(line) {
13166
+ // Draw Legend-like boxes if needed
13167
+ if (drawColorBoxes) {
13168
+ // Fill a white rect so that colours merge nicely if the opacity is < 1
13169
+ ctx.fillStyle = mergeOpacity(vm.legendColorBackground, opacity);
13170
+ ctx.fillRect(pt.x, pt.y, bodyFontSize, bodyFontSize);
13171
+
13172
+ // Border
13173
+ ctx.lineWidth = 1;
13174
+ ctx.strokeStyle = mergeOpacity(vm.labelColors[i].borderColor, opacity);
13175
+ ctx.strokeRect(pt.x, pt.y, bodyFontSize, bodyFontSize);
13176
+
13177
+ // Inner square
13178
+ ctx.fillStyle = mergeOpacity(vm.labelColors[i].backgroundColor, opacity);
13179
+ ctx.fillRect(pt.x + 1, pt.y + 1, bodyFontSize - 2, bodyFontSize - 2);
13180
+ var textColor = mergeOpacity(vm.labelTextColors[i], opacity);
13181
+ ctx.fillStyle = textColor;
13182
+ }
13183
+
13184
+ fillLineOfText(line);
13185
+ });
13186
+
13187
+ helpers.each(bodyItem.after, fillLineOfText);
13188
+ });
13189
+
13190
+ // Reset back to 0 for after body
13191
+ xLinePadding = 0;
13192
+
13193
+ // After body lines
13194
+ helpers.each(vm.afterBody, fillLineOfText);
13195
+ pt.y -= bodySpacing; // Remove last body spacing
13196
+ },
13197
+ drawFooter: function(pt, vm, ctx, opacity) {
13198
+ var footer = vm.footer;
13199
+
13200
+ if (footer.length) {
13201
+ pt.y += vm.footerMarginTop;
13202
+
13203
+ ctx.textAlign = vm._footerAlign;
13204
+ ctx.textBaseline = 'top';
13205
+
13206
+ ctx.fillStyle = mergeOpacity(vm.footerFontColor, opacity);
13207
+ ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily);
13208
+
13209
+ helpers.each(footer, function(line) {
13210
+ ctx.fillText(line, pt.x, pt.y);
13211
+ pt.y += vm.footerFontSize + vm.footerSpacing;
13212
+ });
13213
+ }
13214
+ },
13215
+ drawBackground: function(pt, vm, ctx, tooltipSize, opacity) {
13216
+ ctx.fillStyle = mergeOpacity(vm.backgroundColor, opacity);
13217
+ ctx.strokeStyle = mergeOpacity(vm.borderColor, opacity);
13218
+ ctx.lineWidth = vm.borderWidth;
13219
+ var xAlign = vm.xAlign;
13220
+ var yAlign = vm.yAlign;
13221
+ var x = pt.x;
13222
+ var y = pt.y;
13223
+ var width = tooltipSize.width;
13224
+ var height = tooltipSize.height;
13225
+ var radius = vm.cornerRadius;
13226
+
13227
+ ctx.beginPath();
13228
+ ctx.moveTo(x + radius, y);
13229
+ if (yAlign === 'top') {
13230
+ this.drawCaret(pt, tooltipSize);
13231
+ }
13232
+ ctx.lineTo(x + width - radius, y);
13233
+ ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
13234
+ if (yAlign === 'center' && xAlign === 'right') {
13235
+ this.drawCaret(pt, tooltipSize);
13236
+ }
13237
+ ctx.lineTo(x + width, y + height - radius);
13238
+ ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
13239
+ if (yAlign === 'bottom') {
13240
+ this.drawCaret(pt, tooltipSize);
13241
+ }
13242
+ ctx.lineTo(x + radius, y + height);
13243
+ ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
13244
+ if (yAlign === 'center' && xAlign === 'left') {
13245
+ this.drawCaret(pt, tooltipSize);
13246
+ }
13247
+ ctx.lineTo(x, y + radius);
13248
+ ctx.quadraticCurveTo(x, y, x + radius, y);
13249
+ ctx.closePath();
13250
+
13251
+ ctx.fill();
13252
+
13253
+ if (vm.borderWidth > 0) {
13254
+ ctx.stroke();
13255
+ }
13256
+ },
13257
+ draw: function() {
13258
+ var ctx = this._chart.ctx;
13259
+ var vm = this._view;
13260
+
13261
+ if (vm.opacity === 0) {
13262
+ return;
13263
+ }
13264
+
13265
+ var tooltipSize = {
13266
+ width: vm.width,
13267
+ height: vm.height
13268
+ };
13269
+ var pt = {
13270
+ x: vm.x,
13271
+ y: vm.y
13272
+ };
13273
+
13274
+ // IE11/Edge does not like very small opacities, so snap to 0
13275
+ var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity;
13276
+
13277
+ // Truthy/falsey value for empty tooltip
13278
+ var hasTooltipContent = vm.title.length || vm.beforeBody.length || vm.body.length || vm.afterBody.length || vm.footer.length;
13279
+
13280
+ if (this._options.enabled && hasTooltipContent) {
13281
+ // Draw Background
13282
+ this.drawBackground(pt, vm, ctx, tooltipSize, opacity);
13283
+
13284
+ // Draw Title, Body, and Footer
13285
+ pt.x += vm.xPadding;
13286
+ pt.y += vm.yPadding;
13287
+
13288
+ // Titles
13289
+ this.drawTitle(pt, vm, ctx, opacity);
13290
+
13291
+ // Body
13292
+ this.drawBody(pt, vm, ctx, opacity);
13293
+
13294
+ // Footer
13295
+ this.drawFooter(pt, vm, ctx, opacity);
13296
+ }
13297
+ },
13298
+
13299
+ /**
13300
+ * Handle an event
13301
+ * @private
13302
+ * @param {IEvent} event - The event to handle
13303
+ * @returns {Boolean} true if the tooltip changed
13304
+ */
13305
+ handleEvent: function(e) {
13306
+ var me = this;
13307
+ var options = me._options;
13308
+ var changed = false;
13309
+
13310
+ me._lastActive = me._lastActive || [];
13311
+
13312
+ // Find Active Elements for tooltips
13313
+ if (e.type === 'mouseout') {
13314
+ me._active = [];
13315
+ } else {
13316
+ me._active = me._chart.getElementsAtEventForMode(e, options.mode, options);
13317
+ }
13318
+
13319
+ // Remember Last Actives
13320
+ changed = !helpers.arrayEquals(me._active, me._lastActive);
13321
+
13322
+ // If tooltip didn't change, do not handle the target event
13323
+ if (!changed) {
13324
+ return false;
13325
+ }
13326
+
13327
+ me._lastActive = me._active;
13328
+
13329
+ if (options.enabled || options.custom) {
13330
+ me._eventPosition = {
13331
+ x: e.x,
13332
+ y: e.y
13333
+ };
13334
+
13335
+ var model = me._model;
13336
+ me.update(true);
13337
+ me.pivot();
13338
+
13339
+ // See if our tooltip position changed
13340
+ changed |= (model.x !== me._model.x) || (model.y !== me._model.y);
13341
+ }
13342
+
13343
+ return changed;
13344
+ }
13345
+ });
13346
+
13347
+ /**
13348
+ * @namespace Chart.Tooltip.positioners
13349
+ */
13350
+ Chart.Tooltip.positioners = {
13351
+ /**
13352
+ * Average mode places the tooltip at the average position of the elements shown
13353
+ * @function Chart.Tooltip.positioners.average
13354
+ * @param elements {ChartElement[]} the elements being displayed in the tooltip
13355
+ * @returns {Point} tooltip position
13356
+ */
13357
+ average: function(elements) {
13358
+ if (!elements.length) {
13359
+ return false;
13360
+ }
13361
+
13362
+ var i, len;
13363
+ var x = 0;
13364
+ var y = 0;
13365
+ var count = 0;
13366
+
13367
+ for (i = 0, len = elements.length; i < len; ++i) {
13368
+ var el = elements[i];
13369
+ if (el && el.hasValue()) {
13370
+ var pos = el.tooltipPosition();
13371
+ x += pos.x;
13372
+ y += pos.y;
13373
+ ++count;
13374
+ }
13375
+ }
13376
+
13377
+ return {
13378
+ x: Math.round(x / count),
13379
+ y: Math.round(y / count)
13380
+ };
13381
+ },
13382
+
13383
+ /**
13384
+ * Gets the tooltip position nearest of the item nearest to the event position
13385
+ * @function Chart.Tooltip.positioners.nearest
13386
+ * @param elements {Chart.Element[]} the tooltip elements
13387
+ * @param eventPosition {Point} the position of the event in canvas coordinates
13388
+ * @returns {Point} the tooltip position
13389
+ */
13390
+ nearest: function(elements, eventPosition) {
13391
+ var x = eventPosition.x;
13392
+ var y = eventPosition.y;
13393
+ var minDistance = Number.POSITIVE_INFINITY;
13394
+ var i, len, nearestElement;
13395
+
13396
+ for (i = 0, len = elements.length; i < len; ++i) {
13397
+ var el = elements[i];
13398
+ if (el && el.hasValue()) {
13399
+ var center = el.getCenterPoint();
13400
+ var d = helpers.distanceBetweenPoints(eventPosition, center);
13401
+
13402
+ if (d < minDistance) {
13403
+ minDistance = d;
13404
+ nearestElement = el;
13405
+ }
13406
+ }
13407
+ }
13408
+
13409
+ if (nearestElement) {
13410
+ var tp = nearestElement.tooltipPosition();
13411
+ x = tp.x;
13412
+ y = tp.y;
13413
+ }
13414
+
13415
+ return {
13416
+ x: x,
13417
+ y: y
13418
+ };
13419
+ }
13420
+ };
13421
+ };
13422
+
13423
+ },{"25":25,"26":26,"45":45}],36:[function(require,module,exports){
13424
+ 'use strict';
13425
+
13426
+ var defaults = require(25);
13427
+ var Element = require(26);
13428
+ var helpers = require(45);
13429
+
13430
+ defaults._set('global', {
13431
+ elements: {
13432
+ arc: {
13433
+ backgroundColor: defaults.global.defaultColor,
13434
+ borderColor: '#fff',
13435
+ borderWidth: 2
13436
+ }
13437
+ }
13438
+ });
13439
+
13440
+ module.exports = Element.extend({
13441
+ inLabelRange: function(mouseX) {
13442
+ var vm = this._view;
13443
+
13444
+ if (vm) {
13445
+ return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2));
13446
+ }
13447
+ return false;
13448
+ },
13449
+
13450
+ inRange: function(chartX, chartY) {
13451
+ var vm = this._view;
13452
+
13453
+ if (vm) {
13454
+ var pointRelativePosition = helpers.getAngleFromPoint(vm, {x: chartX, y: chartY});
13455
+ var angle = pointRelativePosition.angle;
13456
+ var distance = pointRelativePosition.distance;
13457
+
13458
+ // Sanitise angle range
13459
+ var startAngle = vm.startAngle;
13460
+ var endAngle = vm.endAngle;
13461
+ while (endAngle < startAngle) {
13462
+ endAngle += 2.0 * Math.PI;
13463
+ }
13464
+ while (angle > endAngle) {
13465
+ angle -= 2.0 * Math.PI;
13466
+ }
13467
+ while (angle < startAngle) {
13468
+ angle += 2.0 * Math.PI;
13469
+ }
13470
+
13471
+ // Check if within the range of the open/close angle
13472
+ var betweenAngles = (angle >= startAngle && angle <= endAngle);
13473
+ var withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius);
13474
+
13475
+ return (betweenAngles && withinRadius);
13476
+ }
13477
+ return false;
13478
+ },
13479
+
13480
+ getCenterPoint: function() {
13481
+ var vm = this._view;
13482
+ var halfAngle = (vm.startAngle + vm.endAngle) / 2;
13483
+ var halfRadius = (vm.innerRadius + vm.outerRadius) / 2;
13484
+ return {
13485
+ x: vm.x + Math.cos(halfAngle) * halfRadius,
13486
+ y: vm.y + Math.sin(halfAngle) * halfRadius
13487
+ };
13488
+ },
13489
+
13490
+ getArea: function() {
13491
+ var vm = this._view;
13492
+ return Math.PI * ((vm.endAngle - vm.startAngle) / (2 * Math.PI)) * (Math.pow(vm.outerRadius, 2) - Math.pow(vm.innerRadius, 2));
13493
+ },
13494
+
13495
+ tooltipPosition: function() {
13496
+ var vm = this._view;
13497
+ var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2);
13498
+ var rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius;
13499
+
13500
+ return {
13501
+ x: vm.x + (Math.cos(centreAngle) * rangeFromCentre),
13502
+ y: vm.y + (Math.sin(centreAngle) * rangeFromCentre)
13503
+ };
13504
+ },
13505
+
13506
+ draw: function() {
13507
+ var ctx = this._chart.ctx;
13508
+ var vm = this._view;
13509
+ var sA = vm.startAngle;
13510
+ var eA = vm.endAngle;
13511
+
13512
+ ctx.beginPath();
13513
+
13514
+ ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA);
13515
+ ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true);
13516
+
13517
+ ctx.closePath();
13518
+ ctx.strokeStyle = vm.borderColor;
13519
+ ctx.lineWidth = vm.borderWidth;
13520
+
13521
+ ctx.fillStyle = vm.backgroundColor;
13522
+
13523
+ ctx.fill();
13524
+ ctx.lineJoin = 'bevel';
13525
+
13526
+ if (vm.borderWidth) {
13527
+ ctx.stroke();
13528
+ }
13529
+ }
13530
+ });
13531
+
13532
+ },{"25":25,"26":26,"45":45}],37:[function(require,module,exports){
13533
+ 'use strict';
13534
+
13535
+ var defaults = require(25);
13536
+ var Element = require(26);
13537
+ var helpers = require(45);
13538
+
13539
+ var globalDefaults = defaults.global;
13540
+
13541
+ defaults._set('global', {
13542
+ elements: {
13543
+ line: {
13544
+ tension: 0.4,
13545
+ backgroundColor: globalDefaults.defaultColor,
13546
+ borderWidth: 3,
13547
+ borderColor: globalDefaults.defaultColor,
13548
+ borderCapStyle: 'butt',
13549
+ borderDash: [],
13550
+ borderDashOffset: 0.0,
13551
+ borderJoinStyle: 'miter',
13552
+ capBezierPoints: true,
13553
+ fill: true, // do we fill in the area between the line and its base axis
13554
+ }
13555
+ }
13556
+ });
13557
+
13558
+ module.exports = Element.extend({
13559
+ draw: function() {
13560
+ var me = this;
13561
+ var vm = me._view;
13562
+ var ctx = me._chart.ctx;
13563
+ var spanGaps = vm.spanGaps;
13564
+ var points = me._children.slice(); // clone array
13565
+ var globalOptionLineElements = globalDefaults.elements.line;
13566
+ var lastDrawnIndex = -1;
13567
+ var index, current, previous, currentVM;
13568
+
13569
+ // If we are looping, adding the first point again
13570
+ if (me._loop && points.length) {
13571
+ points.push(points[0]);
13572
+ }
13573
+
13574
+ ctx.save();
13575
+
13576
+ // Stroke Line Options
13577
+ ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;
13578
+
13579
+ // IE 9 and 10 do not support line dash
13580
+ if (ctx.setLineDash) {
13581
+ ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash);
13582
+ }
13583
+
13584
+ ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset;
13585
+ ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;
13586
+ ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth;
13587
+ ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;
13588
+
13589
+ // Stroke Line
13590
+ ctx.beginPath();
13591
+ lastDrawnIndex = -1;
13592
+
13593
+ for (index = 0; index < points.length; ++index) {
13594
+ current = points[index];
13595
+ previous = helpers.previousItem(points, index);
13596
+ currentVM = current._view;
13597
+
13598
+ // First point moves to it's starting position no matter what
13599
+ if (index === 0) {
13600
+ if (!currentVM.skip) {
13601
+ ctx.moveTo(currentVM.x, currentVM.y);
13602
+ lastDrawnIndex = index;
13603
+ }
13604
+ } else {
13605
+ previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex];
13606
+
13607
+ if (!currentVM.skip) {
13608
+ if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) {
13609
+ // There was a gap and this is the first point after the gap
13610
+ ctx.moveTo(currentVM.x, currentVM.y);
13611
+ } else {
13612
+ // Line to next point
13613
+ helpers.canvas.lineTo(ctx, previous._view, current._view);
13614
+ }
13615
+ lastDrawnIndex = index;
13616
+ }
13617
+ }
13618
+ }
13619
+
13620
+ ctx.stroke();
13621
+ ctx.restore();
13622
+ }
13623
+ });
13624
+
13625
+ },{"25":25,"26":26,"45":45}],38:[function(require,module,exports){
13626
+ 'use strict';
13627
+
13628
+ var defaults = require(25);
13629
+ var Element = require(26);
13630
+ var helpers = require(45);
13631
+
13632
+ var defaultColor = defaults.global.defaultColor;
13633
+
13634
+ defaults._set('global', {
13635
+ elements: {
13636
+ point: {
13637
+ radius: 3,
13638
+ pointStyle: 'circle',
13639
+ backgroundColor: defaultColor,
13640
+ borderColor: defaultColor,
13641
+ borderWidth: 1,
13642
+ // Hover
13643
+ hitRadius: 1,
13644
+ hoverRadius: 4,
13645
+ hoverBorderWidth: 1
13646
+ }
13647
+ }
13648
+ });
13649
+
13650
+ function xRange(mouseX) {
13651
+ var vm = this._view;
13652
+ return vm ? (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false;
13653
+ }
13654
+
13655
+ function yRange(mouseY) {
13656
+ var vm = this._view;
13657
+ return vm ? (Math.pow(mouseY - vm.y, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false;
13658
+ }
13659
+
13660
+ module.exports = Element.extend({
13661
+ inRange: function(mouseX, mouseY) {
13662
+ var vm = this._view;
13663
+ return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false;
13664
+ },
13665
+
13666
+ inLabelRange: xRange,
13667
+ inXRange: xRange,
13668
+ inYRange: yRange,
13669
+
13670
+ getCenterPoint: function() {
13671
+ var vm = this._view;
13672
+ return {
13673
+ x: vm.x,
13674
+ y: vm.y
13675
+ };
13676
+ },
13677
+
13678
+ getArea: function() {
13679
+ return Math.PI * Math.pow(this._view.radius, 2);
13680
+ },
13681
+
13682
+ tooltipPosition: function() {
13683
+ var vm = this._view;
13684
+ return {
13685
+ x: vm.x,
13686
+ y: vm.y,
13687
+ padding: vm.radius + vm.borderWidth
13688
+ };
13689
+ },
13690
+
13691
+ draw: function(chartArea) {
13692
+ var vm = this._view;
13693
+ var model = this._model;
13694
+ var ctx = this._chart.ctx;
13695
+ var pointStyle = vm.pointStyle;
13696
+ var radius = vm.radius;
13697
+ var x = vm.x;
13698
+ var y = vm.y;
13699
+ var color = helpers.color;
13700
+ var errMargin = 1.01; // 1.01 is margin for Accumulated error. (Especially Edge, IE.)
13701
+ var ratio = 0;
13702
+
13703
+ if (vm.skip) {
13704
+ return;
13705
+ }
13706
+
13707
+ ctx.strokeStyle = vm.borderColor || defaultColor;
13708
+ ctx.lineWidth = helpers.valueOrDefault(vm.borderWidth, defaults.global.elements.point.borderWidth);
13709
+ ctx.fillStyle = vm.backgroundColor || defaultColor;
13710
+
13711
+ // Cliping for Points.
13712
+ // going out from inner charArea?
13713
+ if ((chartArea !== undefined) && ((model.x < chartArea.left) || (chartArea.right * errMargin < model.x) || (model.y < chartArea.top) || (chartArea.bottom * errMargin < model.y))) {
13714
+ // Point fade out
13715
+ if (model.x < chartArea.left) {
13716
+ ratio = (x - model.x) / (chartArea.left - model.x);
13717
+ } else if (chartArea.right * errMargin < model.x) {
13718
+ ratio = (model.x - x) / (model.x - chartArea.right);
13719
+ } else if (model.y < chartArea.top) {
13720
+ ratio = (y - model.y) / (chartArea.top - model.y);
13721
+ } else if (chartArea.bottom * errMargin < model.y) {
13722
+ ratio = (model.y - y) / (model.y - chartArea.bottom);
13723
+ }
13724
+ ratio = Math.round(ratio * 100) / 100;
13725
+ ctx.strokeStyle = color(ctx.strokeStyle).alpha(ratio).rgbString();
13726
+ ctx.fillStyle = color(ctx.fillStyle).alpha(ratio).rgbString();
13727
+ }
13728
+
13729
+ helpers.canvas.drawPoint(ctx, pointStyle, radius, x, y);
13730
+ }
13731
+ });
13732
+
13733
+ },{"25":25,"26":26,"45":45}],39:[function(require,module,exports){
13734
+ 'use strict';
13735
+
13736
+ var defaults = require(25);
13737
+ var Element = require(26);
13738
+
13739
+ defaults._set('global', {
13740
+ elements: {
13741
+ rectangle: {
13742
+ backgroundColor: defaults.global.defaultColor,
13743
+ borderColor: defaults.global.defaultColor,
13744
+ borderSkipped: 'bottom',
13745
+ borderWidth: 0
13746
+ }
13747
+ }
13748
+ });
13749
+
13750
+ function isVertical(bar) {
13751
+ return bar._view.width !== undefined;
13752
+ }
13753
+
13754
+ /**
13755
+ * Helper function to get the bounds of the bar regardless of the orientation
13756
+ * @param bar {Chart.Element.Rectangle} the bar
13757
+ * @return {Bounds} bounds of the bar
13758
+ * @private
13759
+ */
13760
+ function getBarBounds(bar) {
13761
+ var vm = bar._view;
13762
+ var x1, x2, y1, y2;
13763
+
13764
+ if (isVertical(bar)) {
13765
+ // vertical
13766
+ var halfWidth = vm.width / 2;
13767
+ x1 = vm.x - halfWidth;
13768
+ x2 = vm.x + halfWidth;
13769
+ y1 = Math.min(vm.y, vm.base);
13770
+ y2 = Math.max(vm.y, vm.base);
13771
+ } else {
13772
+ // horizontal bar
13773
+ var halfHeight = vm.height / 2;
13774
+ x1 = Math.min(vm.x, vm.base);
13775
+ x2 = Math.max(vm.x, vm.base);
13776
+ y1 = vm.y - halfHeight;
13777
+ y2 = vm.y + halfHeight;
13778
+ }
13779
+
13780
+ return {
13781
+ left: x1,
13782
+ top: y1,
13783
+ right: x2,
13784
+ bottom: y2
13785
+ };
13786
+ }
13787
+
13788
+ module.exports = Element.extend({
13789
+ draw: function() {
13790
+ var ctx = this._chart.ctx;
13791
+ var vm = this._view;
13792
+ var left, right, top, bottom, signX, signY, borderSkipped;
13793
+ var borderWidth = vm.borderWidth;
13794
+
13795
+ if (!vm.horizontal) {
13796
+ // bar
13797
+ left = vm.x - vm.width / 2;
13798
+ right = vm.x + vm.width / 2;
13799
+ top = vm.y;
13800
+ bottom = vm.base;
13801
+ signX = 1;
13802
+ signY = bottom > top ? 1 : -1;
13803
+ borderSkipped = vm.borderSkipped || 'bottom';
13804
+ } else {
13805
+ // horizontal bar
13806
+ left = vm.base;
13807
+ right = vm.x;
13808
+ top = vm.y - vm.height / 2;
13809
+ bottom = vm.y + vm.height / 2;
13810
+ signX = right > left ? 1 : -1;
13811
+ signY = 1;
13812
+ borderSkipped = vm.borderSkipped || 'left';
13813
+ }
13814
+
13815
+ // Canvas doesn't allow us to stroke inside the width so we can
13816
+ // adjust the sizes to fit if we're setting a stroke on the line
13817
+ if (borderWidth) {
13818
+ // borderWidth shold be less than bar width and bar height.
13819
+ var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom));
13820
+ borderWidth = borderWidth > barSize ? barSize : borderWidth;
13821
+ var halfStroke = borderWidth / 2;
13822
+ // Adjust borderWidth when bar top position is near vm.base(zero).
13823
+ var borderLeft = left + (borderSkipped !== 'left' ? halfStroke * signX : 0);
13824
+ var borderRight = right + (borderSkipped !== 'right' ? -halfStroke * signX : 0);
13825
+ var borderTop = top + (borderSkipped !== 'top' ? halfStroke * signY : 0);
13826
+ var borderBottom = bottom + (borderSkipped !== 'bottom' ? -halfStroke * signY : 0);
13827
+ // not become a vertical line?
13828
+ if (borderLeft !== borderRight) {
13829
+ top = borderTop;
13830
+ bottom = borderBottom;
13831
+ }
13832
+ // not become a horizontal line?
13833
+ if (borderTop !== borderBottom) {
13834
+ left = borderLeft;
13835
+ right = borderRight;
13836
+ }
13837
+ }
13838
+
13839
+ ctx.beginPath();
13840
+ ctx.fillStyle = vm.backgroundColor;
13841
+ ctx.strokeStyle = vm.borderColor;
13842
+ ctx.lineWidth = borderWidth;
13843
+
13844
+ // Corner points, from bottom-left to bottom-right clockwise
13845
+ // | 1 2 |
13846
+ // | 0 3 |
13847
+ var corners = [
13848
+ [left, bottom],
13849
+ [left, top],
13850
+ [right, top],
13851
+ [right, bottom]
13852
+ ];
13853
+
13854
+ // Find first (starting) corner with fallback to 'bottom'
13855
+ var borders = ['bottom', 'left', 'top', 'right'];
13856
+ var startCorner = borders.indexOf(borderSkipped, 0);
13857
+ if (startCorner === -1) {
13858
+ startCorner = 0;
13859
+ }
13860
+
13861
+ function cornerAt(index) {
13862
+ return corners[(startCorner + index) % 4];
13863
+ }
13864
+
13865
+ // Draw rectangle from 'startCorner'
13866
+ var corner = cornerAt(0);
13867
+ ctx.moveTo(corner[0], corner[1]);
13868
+
13869
+ for (var i = 1; i < 4; i++) {
13870
+ corner = cornerAt(i);
13871
+ ctx.lineTo(corner[0], corner[1]);
13872
+ }
13873
+
13874
+ ctx.fill();
13875
+ if (borderWidth) {
13876
+ ctx.stroke();
13877
+ }
13878
+ },
13879
+
13880
+ height: function() {
13881
+ var vm = this._view;
13882
+ return vm.base - vm.y;
13883
+ },
13884
+
13885
+ inRange: function(mouseX, mouseY) {
13886
+ var inRange = false;
13887
+
13888
+ if (this._view) {
13889
+ var bounds = getBarBounds(this);
13890
+ inRange = mouseX >= bounds.left && mouseX <= bounds.right && mouseY >= bounds.top && mouseY <= bounds.bottom;
13891
+ }
13892
+
13893
+ return inRange;
13894
+ },
13895
+
13896
+ inLabelRange: function(mouseX, mouseY) {
13897
+ var me = this;
13898
+ if (!me._view) {
13899
+ return false;
13900
+ }
13901
+
13902
+ var inRange = false;
13903
+ var bounds = getBarBounds(me);
13904
+
13905
+ if (isVertical(me)) {
13906
+ inRange = mouseX >= bounds.left && mouseX <= bounds.right;
13907
+ } else {
13908
+ inRange = mouseY >= bounds.top && mouseY <= bounds.bottom;
13909
+ }
13910
+
13911
+ return inRange;
13912
+ },
13913
+
13914
+ inXRange: function(mouseX) {
13915
+ var bounds = getBarBounds(this);
13916
+ return mouseX >= bounds.left && mouseX <= bounds.right;
13917
+ },
13918
+
13919
+ inYRange: function(mouseY) {
13920
+ var bounds = getBarBounds(this);
13921
+ return mouseY >= bounds.top && mouseY <= bounds.bottom;
13922
+ },
13923
+
13924
+ getCenterPoint: function() {
13925
+ var vm = this._view;
13926
+ var x, y;
13927
+ if (isVertical(this)) {
13928
+ x = vm.x;
13929
+ y = (vm.y + vm.base) / 2;
13930
+ } else {
13931
+ x = (vm.x + vm.base) / 2;
13932
+ y = vm.y;
13933
+ }
13934
+
13935
+ return {x: x, y: y};
13936
+ },
13937
+
13938
+ getArea: function() {
13939
+ var vm = this._view;
13940
+ return vm.width * Math.abs(vm.y - vm.base);
13941
+ },
13942
+
13943
+ tooltipPosition: function() {
13944
+ var vm = this._view;
13945
+ return {
13946
+ x: vm.x,
13947
+ y: vm.y
13948
+ };
13949
+ }
13950
+ });
13951
+
13952
+ },{"25":25,"26":26}],40:[function(require,module,exports){
13953
+ 'use strict';
13954
+
13955
+ module.exports = {};
13956
+ module.exports.Arc = require(36);
13957
+ module.exports.Line = require(37);
13958
+ module.exports.Point = require(38);
13959
+ module.exports.Rectangle = require(39);
13960
+
13961
+ },{"36":36,"37":37,"38":38,"39":39}],41:[function(require,module,exports){
13962
+ 'use strict';
13963
+
13964
+ var helpers = require(42);
13965
+
13966
+ /**
13967
+ * @namespace Chart.helpers.canvas
13968
+ */
13969
+ var exports = module.exports = {
13970
+ /**
13971
+ * Clears the entire canvas associated to the given `chart`.
13972
+ * @param {Chart} chart - The chart for which to clear the canvas.
13973
+ */
13974
+ clear: function(chart) {
13975
+ chart.ctx.clearRect(0, 0, chart.width, chart.height);
13976
+ },
13977
+
13978
+ /**
13979
+ * Creates a "path" for a rectangle with rounded corners at position (x, y) with a
13980
+ * given size (width, height) and the same `radius` for all corners.
13981
+ * @param {CanvasRenderingContext2D} ctx - The canvas 2D Context.
13982
+ * @param {Number} x - The x axis of the coordinate for the rectangle starting point.
13983
+ * @param {Number} y - The y axis of the coordinate for the rectangle starting point.
13984
+ * @param {Number} width - The rectangle's width.
13985
+ * @param {Number} height - The rectangle's height.
13986
+ * @param {Number} radius - The rounded amount (in pixels) for the four corners.
13987
+ * @todo handle `radius` as top-left, top-right, bottom-right, bottom-left array/object?
13988
+ */
13989
+ roundedRect: function(ctx, x, y, width, height, radius) {
13990
+ if (radius) {
13991
+ var rx = Math.min(radius, width / 2);
13992
+ var ry = Math.min(radius, height / 2);
13993
+
13994
+ ctx.moveTo(x + rx, y);
13995
+ ctx.lineTo(x + width - rx, y);
13996
+ ctx.quadraticCurveTo(x + width, y, x + width, y + ry);
13997
+ ctx.lineTo(x + width, y + height - ry);
13998
+ ctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height);
13999
+ ctx.lineTo(x + rx, y + height);
14000
+ ctx.quadraticCurveTo(x, y + height, x, y + height - ry);
14001
+ ctx.lineTo(x, y + ry);
14002
+ ctx.quadraticCurveTo(x, y, x + rx, y);
14003
+ } else {
14004
+ ctx.rect(x, y, width, height);
14005
+ }
14006
+ },
14007
+
14008
+ drawPoint: function(ctx, style, radius, x, y) {
14009
+ var type, edgeLength, xOffset, yOffset, height, size;
14010
+
14011
+ if (typeof style === 'object') {
14012
+ type = style.toString();
14013
+ if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {
14014
+ ctx.drawImage(style, x - style.width / 2, y - style.height / 2, style.width, style.height);
14015
+ return;
14016
+ }
14017
+ }
14018
+
14019
+ if (isNaN(radius) || radius <= 0) {
14020
+ return;
14021
+ }
14022
+
14023
+ switch (style) {
14024
+ // Default includes circle
14025
+ default:
14026
+ ctx.beginPath();
14027
+ ctx.arc(x, y, radius, 0, Math.PI * 2);
14028
+ ctx.closePath();
14029
+ ctx.fill();
14030
+ break;
14031
+ case 'triangle':
14032
+ ctx.beginPath();
14033
+ edgeLength = 3 * radius / Math.sqrt(3);
14034
+ height = edgeLength * Math.sqrt(3) / 2;
14035
+ ctx.moveTo(x - edgeLength / 2, y + height / 3);
14036
+ ctx.lineTo(x + edgeLength / 2, y + height / 3);
14037
+ ctx.lineTo(x, y - 2 * height / 3);
14038
+ ctx.closePath();
14039
+ ctx.fill();
14040
+ break;
14041
+ case 'rect':
14042
+ size = 1 / Math.SQRT2 * radius;
14043
+ ctx.beginPath();
14044
+ ctx.fillRect(x - size, y - size, 2 * size, 2 * size);
14045
+ ctx.strokeRect(x - size, y - size, 2 * size, 2 * size);
14046
+ break;
14047
+ case 'rectRounded':
14048
+ var offset = radius / Math.SQRT2;
14049
+ var leftX = x - offset;
14050
+ var topY = y - offset;
14051
+ var sideSize = Math.SQRT2 * radius;
14052
+ ctx.beginPath();
14053
+ this.roundedRect(ctx, leftX, topY, sideSize, sideSize, radius / 2);
14054
+ ctx.closePath();
14055
+ ctx.fill();
14056
+ break;
14057
+ case 'rectRot':
14058
+ size = 1 / Math.SQRT2 * radius;
14059
+ ctx.beginPath();
14060
+ ctx.moveTo(x - size, y);
14061
+ ctx.lineTo(x, y + size);
14062
+ ctx.lineTo(x + size, y);
14063
+ ctx.lineTo(x, y - size);
14064
+ ctx.closePath();
14065
+ ctx.fill();
14066
+ break;
14067
+ case 'cross':
14068
+ ctx.beginPath();
14069
+ ctx.moveTo(x, y + radius);
14070
+ ctx.lineTo(x, y - radius);
14071
+ ctx.moveTo(x - radius, y);
14072
+ ctx.lineTo(x + radius, y);
14073
+ ctx.closePath();
14074
+ break;
14075
+ case 'crossRot':
14076
+ ctx.beginPath();
14077
+ xOffset = Math.cos(Math.PI / 4) * radius;
14078
+ yOffset = Math.sin(Math.PI / 4) * radius;
14079
+ ctx.moveTo(x - xOffset, y - yOffset);
14080
+ ctx.lineTo(x + xOffset, y + yOffset);
14081
+ ctx.moveTo(x - xOffset, y + yOffset);
14082
+ ctx.lineTo(x + xOffset, y - yOffset);
14083
+ ctx.closePath();
14084
+ break;
14085
+ case 'star':
14086
+ ctx.beginPath();
14087
+ ctx.moveTo(x, y + radius);
14088
+ ctx.lineTo(x, y - radius);
14089
+ ctx.moveTo(x - radius, y);
14090
+ ctx.lineTo(x + radius, y);
14091
+ xOffset = Math.cos(Math.PI / 4) * radius;
14092
+ yOffset = Math.sin(Math.PI / 4) * radius;
14093
+ ctx.moveTo(x - xOffset, y - yOffset);
14094
+ ctx.lineTo(x + xOffset, y + yOffset);
14095
+ ctx.moveTo(x - xOffset, y + yOffset);
14096
+ ctx.lineTo(x + xOffset, y - yOffset);
14097
+ ctx.closePath();
14098
+ break;
14099
+ case 'line':
14100
+ ctx.beginPath();
14101
+ ctx.moveTo(x - radius, y);
14102
+ ctx.lineTo(x + radius, y);
14103
+ ctx.closePath();
14104
+ break;
14105
+ case 'dash':
14106
+ ctx.beginPath();
14107
+ ctx.moveTo(x, y);
14108
+ ctx.lineTo(x + radius, y);
14109
+ ctx.closePath();
14110
+ break;
14111
+ }
14112
+
14113
+ ctx.stroke();
14114
+ },
14115
+
14116
+ clipArea: function(ctx, area) {
14117
+ ctx.save();
14118
+ ctx.beginPath();
14119
+ ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top);
14120
+ ctx.clip();
14121
+ },
14122
+
14123
+ unclipArea: function(ctx) {
14124
+ ctx.restore();
14125
+ },
14126
+
14127
+ lineTo: function(ctx, previous, target, flip) {
14128
+ if (target.steppedLine) {
14129
+ if ((target.steppedLine === 'after' && !flip) || (target.steppedLine !== 'after' && flip)) {
14130
+ ctx.lineTo(previous.x, target.y);
14131
+ } else {
14132
+ ctx.lineTo(target.x, previous.y);
14133
+ }
14134
+ ctx.lineTo(target.x, target.y);
14135
+ return;
14136
+ }
14137
+
14138
+ if (!target.tension) {
14139
+ ctx.lineTo(target.x, target.y);
14140
+ return;
14141
+ }
14142
+
14143
+ ctx.bezierCurveTo(
14144
+ flip ? previous.controlPointPreviousX : previous.controlPointNextX,
14145
+ flip ? previous.controlPointPreviousY : previous.controlPointNextY,
14146
+ flip ? target.controlPointNextX : target.controlPointPreviousX,
14147
+ flip ? target.controlPointNextY : target.controlPointPreviousY,
14148
+ target.x,
14149
+ target.y);
14150
+ }
14151
+ };
14152
+
14153
+ // DEPRECATIONS
14154
+
14155
+ /**
14156
+ * Provided for backward compatibility, use Chart.helpers.canvas.clear instead.
14157
+ * @namespace Chart.helpers.clear
14158
+ * @deprecated since version 2.7.0
14159
+ * @todo remove at version 3
14160
+ * @private
14161
+ */
14162
+ helpers.clear = exports.clear;
14163
+
14164
+ /**
14165
+ * Provided for backward compatibility, use Chart.helpers.canvas.roundedRect instead.
14166
+ * @namespace Chart.helpers.drawRoundedRectangle
14167
+ * @deprecated since version 2.7.0
14168
+ * @todo remove at version 3
14169
+ * @private
14170
+ */
14171
+ helpers.drawRoundedRectangle = function(ctx) {
14172
+ ctx.beginPath();
14173
+ exports.roundedRect.apply(exports, arguments);
14174
+ ctx.closePath();
14175
+ };
14176
+
14177
+ },{"42":42}],42:[function(require,module,exports){
14178
+ 'use strict';
14179
+
14180
+ /**
14181
+ * @namespace Chart.helpers
14182
+ */
14183
+ var helpers = {
14184
+ /**
14185
+ * An empty function that can be used, for example, for optional callback.
14186
+ */
14187
+ noop: function() {},
14188
+
14189
+ /**
14190
+ * Returns a unique id, sequentially generated from a global variable.
14191
+ * @returns {Number}
14192
+ * @function
14193
+ */
14194
+ uid: (function() {
14195
+ var id = 0;
14196
+ return function() {
14197
+ return id++;
14198
+ };
14199
+ }()),
14200
+
14201
+ /**
14202
+ * Returns true if `value` is neither null nor undefined, else returns false.
14203
+ * @param {*} value - The value to test.
14204
+ * @returns {Boolean}
14205
+ * @since 2.7.0
14206
+ */
14207
+ isNullOrUndef: function(value) {
14208
+ return value === null || typeof value === 'undefined';
14209
+ },
14210
+
14211
+ /**
14212
+ * Returns true if `value` is an array, else returns false.
14213
+ * @param {*} value - The value to test.
14214
+ * @returns {Boolean}
14215
+ * @function
14216
+ */
14217
+ isArray: Array.isArray ? Array.isArray : function(value) {
14218
+ return Object.prototype.toString.call(value) === '[object Array]';
14219
+ },
14220
+
14221
+ /**
14222
+ * Returns true if `value` is an object (excluding null), else returns false.
14223
+ * @param {*} value - The value to test.
14224
+ * @returns {Boolean}
14225
+ * @since 2.7.0
14226
+ */
14227
+ isObject: function(value) {
14228
+ return value !== null && Object.prototype.toString.call(value) === '[object Object]';
14229
+ },
14230
+
14231
+ /**
14232
+ * Returns `value` if defined, else returns `defaultValue`.
14233
+ * @param {*} value - The value to return if defined.
14234
+ * @param {*} defaultValue - The value to return if `value` is undefined.
14235
+ * @returns {*}
14236
+ */
14237
+ valueOrDefault: function(value, defaultValue) {
14238
+ return typeof value === 'undefined' ? defaultValue : value;
14239
+ },
14240
+
14241
+ /**
14242
+ * Returns value at the given `index` in array if defined, else returns `defaultValue`.
14243
+ * @param {Array} value - The array to lookup for value at `index`.
14244
+ * @param {Number} index - The index in `value` to lookup for value.
14245
+ * @param {*} defaultValue - The value to return if `value[index]` is undefined.
14246
+ * @returns {*}
14247
+ */
14248
+ valueAtIndexOrDefault: function(value, index, defaultValue) {
14249
+ return helpers.valueOrDefault(helpers.isArray(value) ? value[index] : value, defaultValue);
14250
+ },
14251
+
14252
+ /**
14253
+ * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the
14254
+ * value returned by `fn`. If `fn` is not a function, this method returns undefined.
14255
+ * @param {Function} fn - The function to call.
14256
+ * @param {Array|undefined|null} args - The arguments with which `fn` should be called.
14257
+ * @param {Object} [thisArg] - The value of `this` provided for the call to `fn`.
14258
+ * @returns {*}
14259
+ */
14260
+ callback: function(fn, args, thisArg) {
14261
+ if (fn && typeof fn.call === 'function') {
14262
+ return fn.apply(thisArg, args);
14263
+ }
14264
+ },
14265
+
14266
+ /**
14267
+ * Note(SB) for performance sake, this method should only be used when loopable type
14268
+ * is unknown or in none intensive code (not called often and small loopable). Else
14269
+ * it's preferable to use a regular for() loop and save extra function calls.
14270
+ * @param {Object|Array} loopable - The object or array to be iterated.
14271
+ * @param {Function} fn - The function to call for each item.
14272
+ * @param {Object} [thisArg] - The value of `this` provided for the call to `fn`.
14273
+ * @param {Boolean} [reverse] - If true, iterates backward on the loopable.
14274
+ */
14275
+ each: function(loopable, fn, thisArg, reverse) {
14276
+ var i, len, keys;
14277
+ if (helpers.isArray(loopable)) {
14278
+ len = loopable.length;
14279
+ if (reverse) {
14280
+ for (i = len - 1; i >= 0; i--) {
14281
+ fn.call(thisArg, loopable[i], i);
14282
+ }
14283
+ } else {
14284
+ for (i = 0; i < len; i++) {
14285
+ fn.call(thisArg, loopable[i], i);
14286
+ }
14287
+ }
14288
+ } else if (helpers.isObject(loopable)) {
14289
+ keys = Object.keys(loopable);
14290
+ len = keys.length;
14291
+ for (i = 0; i < len; i++) {
14292
+ fn.call(thisArg, loopable[keys[i]], keys[i]);
14293
+ }
14294
+ }
14295
+ },
14296
+
14297
+ /**
14298
+ * Returns true if the `a0` and `a1` arrays have the same content, else returns false.
14299
+ * @see http://stackoverflow.com/a/14853974
14300
+ * @param {Array} a0 - The array to compare
14301
+ * @param {Array} a1 - The array to compare
14302
+ * @returns {Boolean}
14303
+ */
14304
+ arrayEquals: function(a0, a1) {
14305
+ var i, ilen, v0, v1;
14306
+
14307
+ if (!a0 || !a1 || a0.length !== a1.length) {
14308
+ return false;
14309
+ }
14310
+
14311
+ for (i = 0, ilen = a0.length; i < ilen; ++i) {
14312
+ v0 = a0[i];
14313
+ v1 = a1[i];
14314
+
14315
+ if (v0 instanceof Array && v1 instanceof Array) {
14316
+ if (!helpers.arrayEquals(v0, v1)) {
14317
+ return false;
14318
+ }
14319
+ } else if (v0 !== v1) {
14320
+ // NOTE: two different object instances will never be equal: {x:20} != {x:20}
14321
+ return false;
14322
+ }
14323
+ }
14324
+
14325
+ return true;
14326
+ },
14327
+
14328
+ /**
14329
+ * Returns a deep copy of `source` without keeping references on objects and arrays.
14330
+ * @param {*} source - The value to clone.
14331
+ * @returns {*}
14332
+ */
14333
+ clone: function(source) {
14334
+ if (helpers.isArray(source)) {
14335
+ return source.map(helpers.clone);
14336
+ }
14337
+
14338
+ if (helpers.isObject(source)) {
14339
+ var target = {};
14340
+ var keys = Object.keys(source);
14341
+ var klen = keys.length;
14342
+ var k = 0;
14343
+
14344
+ for (; k < klen; ++k) {
14345
+ target[keys[k]] = helpers.clone(source[keys[k]]);
14346
+ }
14347
+
14348
+ return target;
14349
+ }
14350
+
14351
+ return source;
14352
+ },
14353
+
14354
+ /**
14355
+ * The default merger when Chart.helpers.merge is called without merger option.
14356
+ * Note(SB): this method is also used by configMerge and scaleMerge as fallback.
14357
+ * @private
14358
+ */
14359
+ _merger: function(key, target, source, options) {
14360
+ var tval = target[key];
14361
+ var sval = source[key];
14362
+
14363
+ if (helpers.isObject(tval) && helpers.isObject(sval)) {
14364
+ helpers.merge(tval, sval, options);
14365
+ } else {
14366
+ target[key] = helpers.clone(sval);
14367
+ }
14368
+ },
14369
+
14370
+ /**
14371
+ * Merges source[key] in target[key] only if target[key] is undefined.
14372
+ * @private
14373
+ */
14374
+ _mergerIf: function(key, target, source) {
14375
+ var tval = target[key];
14376
+ var sval = source[key];
14377
+
14378
+ if (helpers.isObject(tval) && helpers.isObject(sval)) {
14379
+ helpers.mergeIf(tval, sval);
14380
+ } else if (!target.hasOwnProperty(key)) {
14381
+ target[key] = helpers.clone(sval);
14382
+ }
14383
+ },
14384
+
14385
+ /**
14386
+ * Recursively deep copies `source` properties into `target` with the given `options`.
14387
+ * IMPORTANT: `target` is not cloned and will be updated with `source` properties.
14388
+ * @param {Object} target - The target object in which all sources are merged into.
14389
+ * @param {Object|Array(Object)} source - Object(s) to merge into `target`.
14390
+ * @param {Object} [options] - Merging options:
14391
+ * @param {Function} [options.merger] - The merge method (key, target, source, options)
14392
+ * @returns {Object} The `target` object.
14393
+ */
14394
+ merge: function(target, source, options) {
14395
+ var sources = helpers.isArray(source) ? source : [source];
14396
+ var ilen = sources.length;
14397
+ var merge, i, keys, klen, k;
14398
+
14399
+ if (!helpers.isObject(target)) {
14400
+ return target;
14401
+ }
14402
+
14403
+ options = options || {};
14404
+ merge = options.merger || helpers._merger;
14405
+
14406
+ for (i = 0; i < ilen; ++i) {
14407
+ source = sources[i];
14408
+ if (!helpers.isObject(source)) {
14409
+ continue;
14410
+ }
14411
+
14412
+ keys = Object.keys(source);
14413
+ for (k = 0, klen = keys.length; k < klen; ++k) {
14414
+ merge(keys[k], target, source, options);
14415
+ }
14416
+ }
14417
+
14418
+ return target;
14419
+ },
14420
+
14421
+ /**
14422
+ * Recursively deep copies `source` properties into `target` *only* if not defined in target.
14423
+ * IMPORTANT: `target` is not cloned and will be updated with `source` properties.
14424
+ * @param {Object} target - The target object in which all sources are merged into.
14425
+ * @param {Object|Array(Object)} source - Object(s) to merge into `target`.
14426
+ * @returns {Object} The `target` object.
14427
+ */
14428
+ mergeIf: function(target, source) {
14429
+ return helpers.merge(target, source, {merger: helpers._mergerIf});
14430
+ }
14431
+ };
14432
+
14433
+ module.exports = helpers;
14434
+
14435
+ // DEPRECATIONS
14436
+
14437
+ /**
14438
+ * Provided for backward compatibility, use Chart.helpers.callback instead.
14439
+ * @function Chart.helpers.callCallback
14440
+ * @deprecated since version 2.6.0
14441
+ * @todo remove at version 3
14442
+ * @private
14443
+ */
14444
+ helpers.callCallback = helpers.callback;
14445
+
14446
+ /**
14447
+ * Provided for backward compatibility, use Array.prototype.indexOf instead.
14448
+ * Array.prototype.indexOf compatibility: Chrome, Opera, Safari, FF1.5+, IE9+
14449
+ * @function Chart.helpers.indexOf
14450
+ * @deprecated since version 2.7.0
14451
+ * @todo remove at version 3
14452
+ * @private
14453
+ */
14454
+ helpers.indexOf = function(array, item, fromIndex) {
14455
+ return Array.prototype.indexOf.call(array, item, fromIndex);
14456
+ };
14457
+
14458
+ /**
14459
+ * Provided for backward compatibility, use Chart.helpers.valueOrDefault instead.
14460
+ * @function Chart.helpers.getValueOrDefault
14461
+ * @deprecated since version 2.7.0
14462
+ * @todo remove at version 3
14463
+ * @private
14464
+ */
14465
+ helpers.getValueOrDefault = helpers.valueOrDefault;
14466
+
14467
+ /**
14468
+ * Provided for backward compatibility, use Chart.helpers.valueAtIndexOrDefault instead.
14469
+ * @function Chart.helpers.getValueAtIndexOrDefault
14470
+ * @deprecated since version 2.7.0
14471
+ * @todo remove at version 3
14472
+ * @private
14473
+ */
14474
+ helpers.getValueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
14475
+
14476
+ },{}],43:[function(require,module,exports){
14477
+ 'use strict';
14478
+
14479
+ var helpers = require(42);
14480
+
14481
+ /**
14482
+ * Easing functions adapted from Robert Penner's easing equations.
14483
+ * @namespace Chart.helpers.easingEffects
14484
+ * @see http://www.robertpenner.com/easing/
14485
+ */
14486
+ var effects = {
14487
+ linear: function(t) {
14488
+ return t;
14489
+ },
14490
+
14491
+ easeInQuad: function(t) {
14492
+ return t * t;
14493
+ },
14494
+
14495
+ easeOutQuad: function(t) {
14496
+ return -t * (t - 2);
14497
+ },
14498
+
14499
+ easeInOutQuad: function(t) {
14500
+ if ((t /= 0.5) < 1) {
14501
+ return 0.5 * t * t;
14502
+ }
14503
+ return -0.5 * ((--t) * (t - 2) - 1);
14504
+ },
14505
+
14506
+ easeInCubic: function(t) {
14507
+ return t * t * t;
14508
+ },
14509
+
14510
+ easeOutCubic: function(t) {
14511
+ return (t = t - 1) * t * t + 1;
14512
+ },
14513
+
14514
+ easeInOutCubic: function(t) {
14515
+ if ((t /= 0.5) < 1) {
14516
+ return 0.5 * t * t * t;
14517
+ }
14518
+ return 0.5 * ((t -= 2) * t * t + 2);
14519
+ },
14520
+
14521
+ easeInQuart: function(t) {
14522
+ return t * t * t * t;
14523
+ },
14524
+
14525
+ easeOutQuart: function(t) {
14526
+ return -((t = t - 1) * t * t * t - 1);
14527
+ },
14528
+
14529
+ easeInOutQuart: function(t) {
14530
+ if ((t /= 0.5) < 1) {
14531
+ return 0.5 * t * t * t * t;
14532
+ }
14533
+ return -0.5 * ((t -= 2) * t * t * t - 2);
14534
+ },
14535
+
14536
+ easeInQuint: function(t) {
14537
+ return t * t * t * t * t;
14538
+ },
14539
+
14540
+ easeOutQuint: function(t) {
14541
+ return (t = t - 1) * t * t * t * t + 1;
14542
+ },
14543
+
14544
+ easeInOutQuint: function(t) {
14545
+ if ((t /= 0.5) < 1) {
14546
+ return 0.5 * t * t * t * t * t;
14547
+ }
14548
+ return 0.5 * ((t -= 2) * t * t * t * t + 2);
14549
+ },
14550
+
14551
+ easeInSine: function(t) {
14552
+ return -Math.cos(t * (Math.PI / 2)) + 1;
14553
+ },
14554
+
14555
+ easeOutSine: function(t) {
14556
+ return Math.sin(t * (Math.PI / 2));
14557
+ },
14558
+
14559
+ easeInOutSine: function(t) {
14560
+ return -0.5 * (Math.cos(Math.PI * t) - 1);
14561
+ },
14562
+
14563
+ easeInExpo: function(t) {
14564
+ return (t === 0) ? 0 : Math.pow(2, 10 * (t - 1));
14565
+ },
14566
+
14567
+ easeOutExpo: function(t) {
14568
+ return (t === 1) ? 1 : -Math.pow(2, -10 * t) + 1;
14569
+ },
14570
+
14571
+ easeInOutExpo: function(t) {
14572
+ if (t === 0) {
14573
+ return 0;
14574
+ }
14575
+ if (t === 1) {
14576
+ return 1;
14577
+ }
14578
+ if ((t /= 0.5) < 1) {
14579
+ return 0.5 * Math.pow(2, 10 * (t - 1));
14580
+ }
14581
+ return 0.5 * (-Math.pow(2, -10 * --t) + 2);
14582
+ },
14583
+
14584
+ easeInCirc: function(t) {
14585
+ if (t >= 1) {
14586
+ return t;
14587
+ }
14588
+ return -(Math.sqrt(1 - t * t) - 1);
14589
+ },
14590
+
14591
+ easeOutCirc: function(t) {
14592
+ return Math.sqrt(1 - (t = t - 1) * t);
14593
+ },
14594
+
14595
+ easeInOutCirc: function(t) {
14596
+ if ((t /= 0.5) < 1) {
14597
+ return -0.5 * (Math.sqrt(1 - t * t) - 1);
14598
+ }
14599
+ return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1);
14600
+ },
14601
+
14602
+ easeInElastic: function(t) {
14603
+ var s = 1.70158;
14604
+ var p = 0;
14605
+ var a = 1;
14606
+ if (t === 0) {
14607
+ return 0;
14608
+ }
14609
+ if (t === 1) {
14610
+ return 1;
14611
+ }
14612
+ if (!p) {
14613
+ p = 0.3;
14614
+ }
14615
+ if (a < 1) {
14616
+ a = 1;
14617
+ s = p / 4;
14618
+ } else {
14619
+ s = p / (2 * Math.PI) * Math.asin(1 / a);
14620
+ }
14621
+ return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p));
14622
+ },
14623
+
14624
+ easeOutElastic: function(t) {
14625
+ var s = 1.70158;
14626
+ var p = 0;
14627
+ var a = 1;
14628
+ if (t === 0) {
14629
+ return 0;
14630
+ }
14631
+ if (t === 1) {
14632
+ return 1;
14633
+ }
14634
+ if (!p) {
14635
+ p = 0.3;
14636
+ }
14637
+ if (a < 1) {
14638
+ a = 1;
14639
+ s = p / 4;
14640
+ } else {
14641
+ s = p / (2 * Math.PI) * Math.asin(1 / a);
14642
+ }
14643
+ return a * Math.pow(2, -10 * t) * Math.sin((t - s) * (2 * Math.PI) / p) + 1;
14644
+ },
14645
+
14646
+ easeInOutElastic: function(t) {
14647
+ var s = 1.70158;
14648
+ var p = 0;
14649
+ var a = 1;
14650
+ if (t === 0) {
14651
+ return 0;
14652
+ }
14653
+ if ((t /= 0.5) === 2) {
14654
+ return 1;
14655
+ }
14656
+ if (!p) {
14657
+ p = 0.45;
14658
+ }
14659
+ if (a < 1) {
14660
+ a = 1;
14661
+ s = p / 4;
14662
+ } else {
14663
+ s = p / (2 * Math.PI) * Math.asin(1 / a);
14664
+ }
14665
+ if (t < 1) {
14666
+ return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p));
14667
+ }
14668
+ return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p) * 0.5 + 1;
14669
+ },
14670
+ easeInBack: function(t) {
14671
+ var s = 1.70158;
14672
+ return t * t * ((s + 1) * t - s);
14673
+ },
14674
+
14675
+ easeOutBack: function(t) {
14676
+ var s = 1.70158;
14677
+ return (t = t - 1) * t * ((s + 1) * t + s) + 1;
14678
+ },
14679
+
14680
+ easeInOutBack: function(t) {
14681
+ var s = 1.70158;
14682
+ if ((t /= 0.5) < 1) {
14683
+ return 0.5 * (t * t * (((s *= (1.525)) + 1) * t - s));
14684
+ }
14685
+ return 0.5 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
14686
+ },
14687
+
14688
+ easeInBounce: function(t) {
14689
+ return 1 - effects.easeOutBounce(1 - t);
14690
+ },
14691
+
14692
+ easeOutBounce: function(t) {
14693
+ if (t < (1 / 2.75)) {
14694
+ return 7.5625 * t * t;
14695
+ }
14696
+ if (t < (2 / 2.75)) {
14697
+ return 7.5625 * (t -= (1.5 / 2.75)) * t + 0.75;
14698
+ }
14699
+ if (t < (2.5 / 2.75)) {
14700
+ return 7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375;
14701
+ }
14702
+ return 7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375;
14703
+ },
14704
+
14705
+ easeInOutBounce: function(t) {
14706
+ if (t < 0.5) {
14707
+ return effects.easeInBounce(t * 2) * 0.5;
14708
+ }
14709
+ return effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5;
14710
+ }
14711
+ };
14712
+
14713
+ module.exports = {
14714
+ effects: effects
14715
+ };
14716
+
14717
+ // DEPRECATIONS
14718
+
14719
+ /**
14720
+ * Provided for backward compatibility, use Chart.helpers.easing.effects instead.
14721
+ * @function Chart.helpers.easingEffects
14722
+ * @deprecated since version 2.7.0
14723
+ * @todo remove at version 3
14724
+ * @private
14725
+ */
14726
+ helpers.easingEffects = effects;
14727
+
14728
+ },{"42":42}],44:[function(require,module,exports){
14729
+ 'use strict';
14730
+
14731
+ var helpers = require(42);
14732
+
14733
+ /**
14734
+ * @alias Chart.helpers.options
14735
+ * @namespace
14736
+ */
14737
+ module.exports = {
14738
+ /**
14739
+ * Converts the given line height `value` in pixels for a specific font `size`.
14740
+ * @param {Number|String} value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em').
14741
+ * @param {Number} size - The font size (in pixels) used to resolve relative `value`.
14742
+ * @returns {Number} The effective line height in pixels (size * 1.2 if value is invalid).
14743
+ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
14744
+ * @since 2.7.0
14745
+ */
14746
+ toLineHeight: function(value, size) {
14747
+ var matches = ('' + value).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);
14748
+ if (!matches || matches[1] === 'normal') {
14749
+ return size * 1.2;
14750
+ }
14751
+
14752
+ value = +matches[2];
14753
+
14754
+ switch (matches[3]) {
14755
+ case 'px':
14756
+ return value;
14757
+ case '%':
14758
+ value /= 100;
14759
+ break;
14760
+ default:
14761
+ break;
14762
+ }
14763
+
14764
+ return size * value;
14765
+ },
14766
+
14767
+ /**
14768
+ * Converts the given value into a padding object with pre-computed width/height.
14769
+ * @param {Number|Object} value - If a number, set the value to all TRBL component,
14770
+ * else, if and object, use defined properties and sets undefined ones to 0.
14771
+ * @returns {Object} The padding values (top, right, bottom, left, width, height)
14772
+ * @since 2.7.0
14773
+ */
14774
+ toPadding: function(value) {
14775
+ var t, r, b, l;
14776
+
14777
+ if (helpers.isObject(value)) {
14778
+ t = +value.top || 0;
14779
+ r = +value.right || 0;
14780
+ b = +value.bottom || 0;
14781
+ l = +value.left || 0;
14782
+ } else {
14783
+ t = r = b = l = +value || 0;
14784
+ }
14785
+
14786
+ return {
14787
+ top: t,
14788
+ right: r,
14789
+ bottom: b,
14790
+ left: l,
14791
+ height: t + b,
14792
+ width: l + r
14793
+ };
14794
+ },
14795
+
14796
+ /**
14797
+ * Evaluates the given `inputs` sequentially and returns the first defined value.
14798
+ * @param {Array[]} inputs - An array of values, falling back to the last value.
14799
+ * @param {Object} [context] - If defined and the current value is a function, the value
14800
+ * is called with `context` as first argument and the result becomes the new input.
14801
+ * @param {Number} [index] - If defined and the current value is an array, the value
14802
+ * at `index` become the new input.
14803
+ * @since 2.7.0
14804
+ */
14805
+ resolve: function(inputs, context, index) {
14806
+ var i, ilen, value;
14807
+
14808
+ for (i = 0, ilen = inputs.length; i < ilen; ++i) {
14809
+ value = inputs[i];
14810
+ if (value === undefined) {
14811
+ continue;
14812
+ }
14813
+ if (context !== undefined && typeof value === 'function') {
14814
+ value = value(context);
14815
+ }
14816
+ if (index !== undefined && helpers.isArray(value)) {
14817
+ value = value[index];
14818
+ }
14819
+ if (value !== undefined) {
14820
+ return value;
14821
+ }
14822
+ }
14823
+ }
14824
+ };
14825
+
14826
+ },{"42":42}],45:[function(require,module,exports){
14827
+ 'use strict';
14828
+
14829
+ module.exports = require(42);
14830
+ module.exports.easing = require(43);
14831
+ module.exports.canvas = require(41);
14832
+ module.exports.options = require(44);
14833
+
14834
+ },{"41":41,"42":42,"43":43,"44":44}],46:[function(require,module,exports){
14835
+ /**
14836
+ * Platform fallback implementation (minimal).
14837
+ * @see https://github.com/chartjs/Chart.js/pull/4591#issuecomment-319575939
14838
+ */
14839
+
14840
+ module.exports = {
14841
+ acquireContext: function(item) {
14842
+ if (item && item.canvas) {
14843
+ // Support for any object associated to a canvas (including a context2d)
14844
+ item = item.canvas;
14845
+ }
14846
+
14847
+ return item && item.getContext('2d') || null;
14848
+ }
14849
+ };
14850
+
14851
+ },{}],47:[function(require,module,exports){
14852
+ /**
14853
+ * Chart.Platform implementation for targeting a web browser
14854
+ */
14855
+
14856
+ 'use strict';
14857
+
14858
+ var helpers = require(45);
14859
+
14860
+ var EXPANDO_KEY = '$chartjs';
14861
+ var CSS_PREFIX = 'chartjs-';
14862
+ var CSS_RENDER_MONITOR = CSS_PREFIX + 'render-monitor';
14863
+ var CSS_RENDER_ANIMATION = CSS_PREFIX + 'render-animation';
14864
+ var ANIMATION_START_EVENTS = ['animationstart', 'webkitAnimationStart'];
14865
+
14866
+ /**
14867
+ * DOM event types -> Chart.js event types.
14868
+ * Note: only events with different types are mapped.
14869
+ * @see https://developer.mozilla.org/en-US/docs/Web/Events
14870
+ */
14871
+ var EVENT_TYPES = {
14872
+ touchstart: 'mousedown',
14873
+ touchmove: 'mousemove',
14874
+ touchend: 'mouseup',
14875
+ pointerenter: 'mouseenter',
14876
+ pointerdown: 'mousedown',
14877
+ pointermove: 'mousemove',
14878
+ pointerup: 'mouseup',
14879
+ pointerleave: 'mouseout',
14880
+ pointerout: 'mouseout'
14881
+ };
14882
+
14883
+ /**
14884
+ * The "used" size is the final value of a dimension property after all calculations have
14885
+ * been performed. This method uses the computed style of `element` but returns undefined
14886
+ * if the computed style is not expressed in pixels. That can happen in some cases where
14887
+ * `element` has a size relative to its parent and this last one is not yet displayed,
14888
+ * for example because of `display: none` on a parent node.
14889
+ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value
14890
+ * @returns {Number} Size in pixels or undefined if unknown.
14891
+ */
14892
+ function readUsedSize(element, property) {
14893
+ var value = helpers.getStyle(element, property);
14894
+ var matches = value && value.match(/^(\d+)(\.\d+)?px$/);
14895
+ return matches ? Number(matches[1]) : undefined;
14896
+ }
14897
+
14898
+ /**
14899
+ * Initializes the canvas style and render size without modifying the canvas display size,
14900
+ * since responsiveness is handled by the controller.resize() method. The config is used
14901
+ * to determine the aspect ratio to apply in case no explicit height has been specified.
14902
+ */
14903
+ function initCanvas(canvas, config) {
14904
+ var style = canvas.style;
14905
+
14906
+ // NOTE(SB) canvas.getAttribute('width') !== canvas.width: in the first case it
14907
+ // returns null or '' if no explicit value has been set to the canvas attribute.
14908
+ var renderHeight = canvas.getAttribute('height');
14909
+ var renderWidth = canvas.getAttribute('width');
14910
+
14911
+ // Chart.js modifies some canvas values that we want to restore on destroy
14912
+ canvas[EXPANDO_KEY] = {
14913
+ initial: {
14914
+ height: renderHeight,
14915
+ width: renderWidth,
14916
+ style: {
14917
+ display: style.display,
14918
+ height: style.height,
14919
+ width: style.width
14920
+ }
14921
+ }
14922
+ };
14923
+
14924
+ // Force canvas to display as block to avoid extra space caused by inline
14925
+ // elements, which would interfere with the responsive resize process.
14926
+ // https://github.com/chartjs/Chart.js/issues/2538
14927
+ style.display = style.display || 'block';
14928
+
14929
+ if (renderWidth === null || renderWidth === '') {
14930
+ var displayWidth = readUsedSize(canvas, 'width');
14931
+ if (displayWidth !== undefined) {
14932
+ canvas.width = displayWidth;
14933
+ }
14934
+ }
14935
+
14936
+ if (renderHeight === null || renderHeight === '') {
14937
+ if (canvas.style.height === '') {
14938
+ // If no explicit render height and style height, let's apply the aspect ratio,
14939
+ // which one can be specified by the user but also by charts as default option
14940
+ // (i.e. options.aspectRatio). If not specified, use canvas aspect ratio of 2.
14941
+ canvas.height = canvas.width / (config.options.aspectRatio || 2);
14942
+ } else {
14943
+ var displayHeight = readUsedSize(canvas, 'height');
14944
+ if (displayWidth !== undefined) {
14945
+ canvas.height = displayHeight;
14946
+ }
14947
+ }
14948
+ }
14949
+
14950
+ return canvas;
14951
+ }
14952
+
14953
+ /**
14954
+ * Detects support for options object argument in addEventListener.
14955
+ * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support
14956
+ * @private
14957
+ */
14958
+ var supportsEventListenerOptions = (function() {
14959
+ var supports = false;
14960
+ try {
14961
+ var options = Object.defineProperty({}, 'passive', {
14962
+ get: function() {
14963
+ supports = true;
14964
+ }
14965
+ });
14966
+ window.addEventListener('e', null, options);
14967
+ } catch (e) {
14968
+ // continue regardless of error
14969
+ }
14970
+ return supports;
14971
+ }());
14972
+
14973
+ // Default passive to true as expected by Chrome for 'touchstart' and 'touchend' events.
14974
+ // https://github.com/chartjs/Chart.js/issues/4287
14975
+ var eventListenerOptions = supportsEventListenerOptions ? {passive: true} : false;
14976
+
14977
+ function addEventListener(node, type, listener) {
14978
+ node.addEventListener(type, listener, eventListenerOptions);
14979
+ }
14980
+
14981
+ function removeEventListener(node, type, listener) {
14982
+ node.removeEventListener(type, listener, eventListenerOptions);
14983
+ }
14984
+
14985
+ function createEvent(type, chart, x, y, nativeEvent) {
14986
+ return {
14987
+ type: type,
14988
+ chart: chart,
14989
+ native: nativeEvent || null,
14990
+ x: x !== undefined ? x : null,
14991
+ y: y !== undefined ? y : null,
14992
+ };
14993
+ }
14994
+
14995
+ function fromNativeEvent(event, chart) {
14996
+ var type = EVENT_TYPES[event.type] || event.type;
14997
+ var pos = helpers.getRelativePosition(event, chart);
14998
+ return createEvent(type, chart, pos.x, pos.y, event);
14999
+ }
15000
+
15001
+ function throttled(fn, thisArg) {
15002
+ var ticking = false;
15003
+ var args = [];
15004
+
15005
+ return function() {
15006
+ args = Array.prototype.slice.call(arguments);
15007
+ thisArg = thisArg || this;
15008
+
15009
+ if (!ticking) {
15010
+ ticking = true;
15011
+ helpers.requestAnimFrame.call(window, function() {
15012
+ ticking = false;
15013
+ fn.apply(thisArg, args);
15014
+ });
15015
+ }
15016
+ };
15017
+ }
15018
+
15019
+ // Implementation based on https://github.com/marcj/css-element-queries
15020
+ function createResizer(handler) {
15021
+ var resizer = document.createElement('div');
15022
+ var cls = CSS_PREFIX + 'size-monitor';
15023
+ var maxSize = 1000000;
15024
+ var style =
15025
+ 'position:absolute;' +
15026
+ 'left:0;' +
15027
+ 'top:0;' +
15028
+ 'right:0;' +
15029
+ 'bottom:0;' +
15030
+ 'overflow:hidden;' +
15031
+ 'pointer-events:none;' +
15032
+ 'visibility:hidden;' +
15033
+ 'z-index:-1;';
15034
+
15035
+ resizer.style.cssText = style;
15036
+ resizer.className = cls;
15037
+ resizer.innerHTML =
15038
+ '<div class="' + cls + '-expand" style="' + style + '">' +
15039
+ '<div style="' +
15040
+ 'position:absolute;' +
15041
+ 'width:' + maxSize + 'px;' +
15042
+ 'height:' + maxSize + 'px;' +
15043
+ 'left:0;' +
15044
+ 'top:0">' +
15045
+ '</div>' +
15046
+ '</div>' +
15047
+ '<div class="' + cls + '-shrink" style="' + style + '">' +
15048
+ '<div style="' +
15049
+ 'position:absolute;' +
15050
+ 'width:200%;' +
15051
+ 'height:200%;' +
15052
+ 'left:0; ' +
15053
+ 'top:0">' +
15054
+ '</div>' +
15055
+ '</div>';
15056
+
15057
+ var expand = resizer.childNodes[0];
15058
+ var shrink = resizer.childNodes[1];
15059
+
15060
+ resizer._reset = function() {
15061
+ expand.scrollLeft = maxSize;
15062
+ expand.scrollTop = maxSize;
15063
+ shrink.scrollLeft = maxSize;
15064
+ shrink.scrollTop = maxSize;
15065
+ };
15066
+ var onScroll = function() {
15067
+ resizer._reset();
15068
+ handler();
15069
+ };
15070
+
15071
+ addEventListener(expand, 'scroll', onScroll.bind(expand, 'expand'));
15072
+ addEventListener(shrink, 'scroll', onScroll.bind(shrink, 'shrink'));
15073
+
15074
+ return resizer;
15075
+ }
15076
+
15077
+ // https://davidwalsh.name/detect-node-insertion
15078
+ function watchForRender(node, handler) {
15079
+ var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {});
15080
+ var proxy = expando.renderProxy = function(e) {
15081
+ if (e.animationName === CSS_RENDER_ANIMATION) {
15082
+ handler();
15083
+ }
15084
+ };
15085
+
15086
+ helpers.each(ANIMATION_START_EVENTS, function(type) {
15087
+ addEventListener(node, type, proxy);
15088
+ });
15089
+
15090
+ node.classList.add(CSS_RENDER_MONITOR);
15091
+ }
15092
+
15093
+ function unwatchForRender(node) {
15094
+ var expando = node[EXPANDO_KEY] || {};
15095
+ var proxy = expando.renderProxy;
15096
+
15097
+ if (proxy) {
15098
+ helpers.each(ANIMATION_START_EVENTS, function(type) {
15099
+ removeEventListener(node, type, proxy);
15100
+ });
15101
+
15102
+ delete expando.renderProxy;
15103
+ }
15104
+
15105
+ node.classList.remove(CSS_RENDER_MONITOR);
15106
+ }
15107
+
15108
+ function addResizeListener(node, listener, chart) {
15109
+ var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {});
15110
+
15111
+ // Let's keep track of this added resizer and thus avoid DOM query when removing it.
15112
+ var resizer = expando.resizer = createResizer(throttled(function() {
15113
+ if (expando.resizer) {
15114
+ return listener(createEvent('resize', chart));
15115
+ }
15116
+ }));
15117
+
15118
+ // The resizer needs to be attached to the node parent, so we first need to be
15119
+ // sure that `node` is attached to the DOM before injecting the resizer element.
15120
+ watchForRender(node, function() {
15121
+ if (expando.resizer) {
15122
+ var container = node.parentNode;
15123
+ if (container && container !== resizer.parentNode) {
15124
+ container.insertBefore(resizer, container.firstChild);
15125
+ }
15126
+
15127
+ // The container size might have changed, let's reset the resizer state.
15128
+ resizer._reset();
15129
+ }
15130
+ });
15131
+ }
15132
+
15133
+ function removeResizeListener(node) {
15134
+ var expando = node[EXPANDO_KEY] || {};
15135
+ var resizer = expando.resizer;
15136
+
15137
+ delete expando.resizer;
15138
+ unwatchForRender(node);
15139
+
15140
+ if (resizer && resizer.parentNode) {
15141
+ resizer.parentNode.removeChild(resizer);
15142
+ }
15143
+ }
15144
+
15145
+ function injectCSS(platform, css) {
15146
+ // http://stackoverflow.com/q/3922139
15147
+ var style = platform._style || document.createElement('style');
15148
+ if (!platform._style) {
15149
+ platform._style = style;
15150
+ css = '/* Chart.js */\n' + css;
15151
+ style.setAttribute('type', 'text/css');
15152
+ document.getElementsByTagName('head')[0].appendChild(style);
15153
+ }
15154
+
15155
+ style.appendChild(document.createTextNode(css));
15156
+ }
15157
+
15158
+ module.exports = {
15159
+ /**
15160
+ * This property holds whether this platform is enabled for the current environment.
15161
+ * Currently used by platform.js to select the proper implementation.
15162
+ * @private
15163
+ */
15164
+ _enabled: typeof window !== 'undefined' && typeof document !== 'undefined',
15165
+
15166
+ initialize: function() {
15167
+ var keyframes = 'from{opacity:0.99}to{opacity:1}';
15168
+
15169
+ injectCSS(this,
15170
+ // DOM rendering detection
15171
+ // https://davidwalsh.name/detect-node-insertion
15172
+ '@-webkit-keyframes ' + CSS_RENDER_ANIMATION + '{' + keyframes + '}' +
15173
+ '@keyframes ' + CSS_RENDER_ANIMATION + '{' + keyframes + '}' +
15174
+ '.' + CSS_RENDER_MONITOR + '{' +
15175
+ '-webkit-animation:' + CSS_RENDER_ANIMATION + ' 0.001s;' +
15176
+ 'animation:' + CSS_RENDER_ANIMATION + ' 0.001s;' +
15177
+ '}'
15178
+ );
15179
+ },
15180
+
15181
+ acquireContext: function(item, config) {
15182
+ if (typeof item === 'string') {
15183
+ item = document.getElementById(item);
15184
+ } else if (item.length) {
15185
+ // Support for array based queries (such as jQuery)
15186
+ item = item[0];
15187
+ }
15188
+
15189
+ if (item && item.canvas) {
15190
+ // Support for any object associated to a canvas (including a context2d)
15191
+ item = item.canvas;
15192
+ }
15193
+
15194
+ // To prevent canvas fingerprinting, some add-ons undefine the getContext
15195
+ // method, for example: https://github.com/kkapsner/CanvasBlocker
15196
+ // https://github.com/chartjs/Chart.js/issues/2807
15197
+ var context = item && item.getContext && item.getContext('2d');
15198
+
15199
+ // `instanceof HTMLCanvasElement/CanvasRenderingContext2D` fails when the item is
15200
+ // inside an iframe or when running in a protected environment. We could guess the
15201
+ // types from their toString() value but let's keep things flexible and assume it's
15202
+ // a sufficient condition if the item has a context2D which has item as `canvas`.
15203
+ // https://github.com/chartjs/Chart.js/issues/3887
15204
+ // https://github.com/chartjs/Chart.js/issues/4102
15205
+ // https://github.com/chartjs/Chart.js/issues/4152
15206
+ if (context && context.canvas === item) {
15207
+ initCanvas(item, config);
15208
+ return context;
15209
+ }
15210
+
15211
+ return null;
15212
+ },
15213
+
15214
+ releaseContext: function(context) {
15215
+ var canvas = context.canvas;
15216
+ if (!canvas[EXPANDO_KEY]) {
15217
+ return;
15218
+ }
15219
+
15220
+ var initial = canvas[EXPANDO_KEY].initial;
15221
+ ['height', 'width'].forEach(function(prop) {
15222
+ var value = initial[prop];
15223
+ if (helpers.isNullOrUndef(value)) {
15224
+ canvas.removeAttribute(prop);
15225
+ } else {
15226
+ canvas.setAttribute(prop, value);
15227
+ }
15228
+ });
15229
+
15230
+ helpers.each(initial.style || {}, function(value, key) {
15231
+ canvas.style[key] = value;
15232
+ });
15233
+
15234
+ // The canvas render size might have been changed (and thus the state stack discarded),
15235
+ // we can't use save() and restore() to restore the initial state. So make sure that at
15236
+ // least the canvas context is reset to the default state by setting the canvas width.
15237
+ // https://www.w3.org/TR/2011/WD-html5-20110525/the-canvas-element.html
15238
+ canvas.width = canvas.width;
15239
+
15240
+ delete canvas[EXPANDO_KEY];
15241
+ },
15242
+
15243
+ addEventListener: function(chart, type, listener) {
15244
+ var canvas = chart.canvas;
15245
+ if (type === 'resize') {
15246
+ // Note: the resize event is not supported on all browsers.
15247
+ addResizeListener(canvas, listener, chart);
15248
+ return;
15249
+ }
15250
+
15251
+ var expando = listener[EXPANDO_KEY] || (listener[EXPANDO_KEY] = {});
15252
+ var proxies = expando.proxies || (expando.proxies = {});
15253
+ var proxy = proxies[chart.id + '_' + type] = function(event) {
15254
+ listener(fromNativeEvent(event, chart));
15255
+ };
15256
+
15257
+ addEventListener(canvas, type, proxy);
15258
+ },
15259
+
15260
+ removeEventListener: function(chart, type, listener) {
15261
+ var canvas = chart.canvas;
15262
+ if (type === 'resize') {
15263
+ // Note: the resize event is not supported on all browsers.
15264
+ removeResizeListener(canvas, listener);
15265
+ return;
15266
+ }
15267
+
15268
+ var expando = listener[EXPANDO_KEY] || {};
15269
+ var proxies = expando.proxies || {};
15270
+ var proxy = proxies[chart.id + '_' + type];
15271
+ if (!proxy) {
15272
+ return;
15273
+ }
15274
+
15275
+ removeEventListener(canvas, type, proxy);
15276
+ }
15277
+ };
15278
+
15279
+ // DEPRECATIONS
15280
+
15281
+ /**
15282
+ * Provided for backward compatibility, use EventTarget.addEventListener instead.
15283
+ * EventTarget.addEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+
15284
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
15285
+ * @function Chart.helpers.addEvent
15286
+ * @deprecated since version 2.7.0
15287
+ * @todo remove at version 3
15288
+ * @private
15289
+ */
15290
+ helpers.addEvent = addEventListener;
15291
+
15292
+ /**
15293
+ * Provided for backward compatibility, use EventTarget.removeEventListener instead.
15294
+ * EventTarget.removeEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+
15295
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
15296
+ * @function Chart.helpers.removeEvent
15297
+ * @deprecated since version 2.7.0
15298
+ * @todo remove at version 3
15299
+ * @private
15300
+ */
15301
+ helpers.removeEvent = removeEventListener;
15302
+
15303
+ },{"45":45}],48:[function(require,module,exports){
15304
+ 'use strict';
15305
+
15306
+ var helpers = require(45);
15307
+ var basic = require(46);
15308
+ var dom = require(47);
15309
+
15310
+ // @TODO Make possible to select another platform at build time.
15311
+ var implementation = dom._enabled ? dom : basic;
15312
+
15313
+ /**
15314
+ * @namespace Chart.platform
15315
+ * @see https://chartjs.gitbooks.io/proposals/content/Platform.html
15316
+ * @since 2.4.0
15317
+ */
15318
+ module.exports = helpers.extend({
15319
+ /**
15320
+ * @since 2.7.0
15321
+ */
15322
+ initialize: function() {},
15323
+
15324
+ /**
15325
+ * Called at chart construction time, returns a context2d instance implementing
15326
+ * the [W3C Canvas 2D Context API standard]{@link https://www.w3.org/TR/2dcontext/}.
15327
+ * @param {*} item - The native item from which to acquire context (platform specific)
15328
+ * @param {Object} options - The chart options
15329
+ * @returns {CanvasRenderingContext2D} context2d instance
15330
+ */
15331
+ acquireContext: function() {},
15332
+
15333
+ /**
15334
+ * Called at chart destruction time, releases any resources associated to the context
15335
+ * previously returned by the acquireContext() method.
15336
+ * @param {CanvasRenderingContext2D} context - The context2d instance
15337
+ * @returns {Boolean} true if the method succeeded, else false
15338
+ */
15339
+ releaseContext: function() {},
15340
+
15341
+ /**
15342
+ * Registers the specified listener on the given chart.
15343
+ * @param {Chart} chart - Chart from which to listen for event
15344
+ * @param {String} type - The ({@link IEvent}) type to listen for
15345
+ * @param {Function} listener - Receives a notification (an object that implements
15346
+ * the {@link IEvent} interface) when an event of the specified type occurs.
15347
+ */
15348
+ addEventListener: function() {},
15349
+
15350
+ /**
15351
+ * Removes the specified listener previously registered with addEventListener.
15352
+ * @param {Chart} chart -Chart from which to remove the listener
15353
+ * @param {String} type - The ({@link IEvent}) type to remove
15354
+ * @param {Function} listener - The listener function to remove from the event target.
15355
+ */
15356
+ removeEventListener: function() {}
15357
+
15358
+ }, implementation);
15359
+
15360
+ /**
15361
+ * @interface IPlatform
15362
+ * Allows abstracting platform dependencies away from the chart
15363
+ * @borrows Chart.platform.acquireContext as acquireContext
15364
+ * @borrows Chart.platform.releaseContext as releaseContext
15365
+ * @borrows Chart.platform.addEventListener as addEventListener
15366
+ * @borrows Chart.platform.removeEventListener as removeEventListener
15367
+ */
15368
+
15369
+ /**
15370
+ * @interface IEvent
15371
+ * @prop {String} type - The event type name, possible values are:
15372
+ * 'contextmenu', 'mouseenter', 'mousedown', 'mousemove', 'mouseup', 'mouseout',
15373
+ * 'click', 'dblclick', 'keydown', 'keypress', 'keyup' and 'resize'
15374
+ * @prop {*} native - The original native event (null for emulated events, e.g. 'resize')
15375
+ * @prop {Number} x - The mouse x position, relative to the canvas (null for incompatible events)
15376
+ * @prop {Number} y - The mouse y position, relative to the canvas (null for incompatible events)
15377
+ */
15378
+
15379
+ },{"45":45,"46":46,"47":47}],49:[function(require,module,exports){
15380
+ /**
15381
+ * Plugin based on discussion from the following Chart.js issues:
15382
+ * @see https://github.com/chartjs/Chart.js/issues/2380#issuecomment-279961569
15383
+ * @see https://github.com/chartjs/Chart.js/issues/2440#issuecomment-256461897
15384
+ */
15385
+
15386
+ 'use strict';
15387
+
15388
+ var defaults = require(25);
15389
+ var elements = require(40);
15390
+ var helpers = require(45);
15391
+
15392
+ defaults._set('global', {
15393
+ plugins: {
15394
+ filler: {
15395
+ propagate: true
15396
+ }
15397
+ }
15398
+ });
15399
+
15400
+ module.exports = function() {
15401
+
15402
+ var mappers = {
15403
+ dataset: function(source) {
15404
+ var index = source.fill;
15405
+ var chart = source.chart;
15406
+ var meta = chart.getDatasetMeta(index);
15407
+ var visible = meta && chart.isDatasetVisible(index);
15408
+ var points = (visible && meta.dataset._children) || [];
15409
+ var length = points.length || 0;
15410
+
15411
+ return !length ? null : function(point, i) {
15412
+ return (i < length && points[i]._view) || null;
15413
+ };
15414
+ },
15415
+
15416
+ boundary: function(source) {
15417
+ var boundary = source.boundary;
15418
+ var x = boundary ? boundary.x : null;
15419
+ var y = boundary ? boundary.y : null;
15420
+
15421
+ return function(point) {
15422
+ return {
15423
+ x: x === null ? point.x : x,
15424
+ y: y === null ? point.y : y,
15425
+ };
15426
+ };
15427
+ }
15428
+ };
15429
+
15430
+ // @todo if (fill[0] === '#')
15431
+ function decodeFill(el, index, count) {
15432
+ var model = el._model || {};
15433
+ var fill = model.fill;
15434
+ var target;
15435
+
15436
+ if (fill === undefined) {
15437
+ fill = !!model.backgroundColor;
15438
+ }
15439
+
15440
+ if (fill === false || fill === null) {
15441
+ return false;
15442
+ }
15443
+
15444
+ if (fill === true) {
15445
+ return 'origin';
15446
+ }
15447
+
15448
+ target = parseFloat(fill, 10);
15449
+ if (isFinite(target) && Math.floor(target) === target) {
15450
+ if (fill[0] === '-' || fill[0] === '+') {
15451
+ target = index + target;
15452
+ }
15453
+
15454
+ if (target === index || target < 0 || target >= count) {
15455
+ return false;
15456
+ }
15457
+
15458
+ return target;
15459
+ }
15460
+
15461
+ switch (fill) {
15462
+ // compatibility
15463
+ case 'bottom':
15464
+ return 'start';
15465
+ case 'top':
15466
+ return 'end';
15467
+ case 'zero':
15468
+ return 'origin';
15469
+ // supported boundaries
15470
+ case 'origin':
15471
+ case 'start':
15472
+ case 'end':
15473
+ return fill;
15474
+ // invalid fill values
15475
+ default:
15476
+ return false;
15477
+ }
15478
+ }
15479
+
15480
+ function computeBoundary(source) {
15481
+ var model = source.el._model || {};
15482
+ var scale = source.el._scale || {};
15483
+ var fill = source.fill;
15484
+ var target = null;
15485
+ var horizontal;
15486
+
15487
+ if (isFinite(fill)) {
15488
+ return null;
15489
+ }
15490
+
15491
+ // Backward compatibility: until v3, we still need to support boundary values set on
15492
+ // the model (scaleTop, scaleBottom and scaleZero) because some external plugins and
15493
+ // controllers might still use it (e.g. the Smith chart).
15494
+
15495
+ if (fill === 'start') {
15496
+ target = model.scaleBottom === undefined ? scale.bottom : model.scaleBottom;
15497
+ } else if (fill === 'end') {
15498
+ target = model.scaleTop === undefined ? scale.top : model.scaleTop;
15499
+ } else if (model.scaleZero !== undefined) {
15500
+ target = model.scaleZero;
15501
+ } else if (scale.getBasePosition) {
15502
+ target = scale.getBasePosition();
15503
+ } else if (scale.getBasePixel) {
15504
+ target = scale.getBasePixel();
15505
+ }
15506
+
15507
+ if (target !== undefined && target !== null) {
15508
+ if (target.x !== undefined && target.y !== undefined) {
15509
+ return target;
15510
+ }
15511
+
15512
+ if (typeof target === 'number' && isFinite(target)) {
15513
+ horizontal = scale.isHorizontal();
15514
+ return {
15515
+ x: horizontal ? target : null,
15516
+ y: horizontal ? null : target
15517
+ };
15518
+ }
15519
+ }
15520
+
15521
+ return null;
15522
+ }
15523
+
15524
+ function resolveTarget(sources, index, propagate) {
15525
+ var source = sources[index];
15526
+ var fill = source.fill;
15527
+ var visited = [index];
15528
+ var target;
15529
+
15530
+ if (!propagate) {
15531
+ return fill;
15532
+ }
15533
+
15534
+ while (fill !== false && visited.indexOf(fill) === -1) {
15535
+ if (!isFinite(fill)) {
15536
+ return fill;
15537
+ }
15538
+
15539
+ target = sources[fill];
15540
+ if (!target) {
15541
+ return false;
15542
+ }
15543
+
15544
+ if (target.visible) {
15545
+ return fill;
15546
+ }
15547
+
15548
+ visited.push(fill);
15549
+ fill = target.fill;
15550
+ }
15551
+
15552
+ return false;
15553
+ }
15554
+
15555
+ function createMapper(source) {
15556
+ var fill = source.fill;
15557
+ var type = 'dataset';
15558
+
15559
+ if (fill === false) {
15560
+ return null;
15561
+ }
15562
+
15563
+ if (!isFinite(fill)) {
15564
+ type = 'boundary';
15565
+ }
15566
+
15567
+ return mappers[type](source);
15568
+ }
15569
+
15570
+ function isDrawable(point) {
15571
+ return point && !point.skip;
15572
+ }
15573
+
15574
+ function drawArea(ctx, curve0, curve1, len0, len1) {
15575
+ var i;
15576
+
15577
+ if (!len0 || !len1) {
15578
+ return;
15579
+ }
15580
+
15581
+ // building first area curve (normal)
15582
+ ctx.moveTo(curve0[0].x, curve0[0].y);
15583
+ for (i = 1; i < len0; ++i) {
15584
+ helpers.canvas.lineTo(ctx, curve0[i - 1], curve0[i]);
15585
+ }
15586
+
15587
+ // joining the two area curves
15588
+ ctx.lineTo(curve1[len1 - 1].x, curve1[len1 - 1].y);
15589
+
15590
+ // building opposite area curve (reverse)
15591
+ for (i = len1 - 1; i > 0; --i) {
15592
+ helpers.canvas.lineTo(ctx, curve1[i], curve1[i - 1], true);
15593
+ }
15594
+ }
15595
+
15596
+ function doFill(ctx, points, mapper, view, color, loop) {
15597
+ var count = points.length;
15598
+ var span = view.spanGaps;
15599
+ var curve0 = [];
15600
+ var curve1 = [];
15601
+ var len0 = 0;
15602
+ var len1 = 0;
15603
+ var i, ilen, index, p0, p1, d0, d1;
15604
+
15605
+ ctx.beginPath();
15606
+
15607
+ for (i = 0, ilen = (count + !!loop); i < ilen; ++i) {
15608
+ index = i % count;
15609
+ p0 = points[index]._view;
15610
+ p1 = mapper(p0, index, view);
15611
+ d0 = isDrawable(p0);
15612
+ d1 = isDrawable(p1);
15613
+
15614
+ if (d0 && d1) {
15615
+ len0 = curve0.push(p0);
15616
+ len1 = curve1.push(p1);
15617
+ } else if (len0 && len1) {
15618
+ if (!span) {
15619
+ drawArea(ctx, curve0, curve1, len0, len1);
15620
+ len0 = len1 = 0;
15621
+ curve0 = [];
15622
+ curve1 = [];
15623
+ } else {
15624
+ if (d0) {
15625
+ curve0.push(p0);
15626
+ }
15627
+ if (d1) {
15628
+ curve1.push(p1);
15629
+ }
15630
+ }
15631
+ }
15632
+ }
15633
+
15634
+ drawArea(ctx, curve0, curve1, len0, len1);
15635
+
15636
+ ctx.closePath();
15637
+ ctx.fillStyle = color;
15638
+ ctx.fill();
15639
+ }
15640
+
15641
+ return {
15642
+ id: 'filler',
15643
+
15644
+ afterDatasetsUpdate: function(chart, options) {
15645
+ var count = (chart.data.datasets || []).length;
15646
+ var propagate = options.propagate;
15647
+ var sources = [];
15648
+ var meta, i, el, source;
15649
+
15650
+ for (i = 0; i < count; ++i) {
15651
+ meta = chart.getDatasetMeta(i);
15652
+ el = meta.dataset;
15653
+ source = null;
15654
+
15655
+ if (el && el._model && el instanceof elements.Line) {
15656
+ source = {
15657
+ visible: chart.isDatasetVisible(i),
15658
+ fill: decodeFill(el, i, count),
15659
+ chart: chart,
15660
+ el: el
15661
+ };
15662
+ }
15663
+
15664
+ meta.$filler = source;
15665
+ sources.push(source);
15666
+ }
15667
+
15668
+ for (i = 0; i < count; ++i) {
15669
+ source = sources[i];
15670
+ if (!source) {
15671
+ continue;
15672
+ }
15673
+
15674
+ source.fill = resolveTarget(sources, i, propagate);
15675
+ source.boundary = computeBoundary(source);
15676
+ source.mapper = createMapper(source);
15677
+ }
15678
+ },
15679
+
15680
+ beforeDatasetDraw: function(chart, args) {
15681
+ var meta = args.meta.$filler;
15682
+ if (!meta) {
15683
+ return;
15684
+ }
15685
+
15686
+ var ctx = chart.ctx;
15687
+ var el = meta.el;
15688
+ var view = el._view;
15689
+ var points = el._children || [];
15690
+ var mapper = meta.mapper;
15691
+ var color = view.backgroundColor || defaults.global.defaultColor;
15692
+
15693
+ if (mapper && color && points.length) {
15694
+ helpers.canvas.clipArea(ctx, chart.chartArea);
15695
+ doFill(ctx, points, mapper, view, color, el._loop);
15696
+ helpers.canvas.unclipArea(ctx);
15697
+ }
15698
+ }
15699
+ };
15700
+ };
15701
+
15702
+ },{"25":25,"40":40,"45":45}],50:[function(require,module,exports){
15703
+ 'use strict';
15704
+
15705
+ var defaults = require(25);
15706
+ var Element = require(26);
15707
+ var helpers = require(45);
15708
+
15709
+ defaults._set('global', {
15710
+ legend: {
15711
+ display: true,
15712
+ position: 'top',
15713
+ fullWidth: true,
15714
+ reverse: false,
15715
+ weight: 1000,
15716
+
15717
+ // a callback that will handle
15718
+ onClick: function(e, legendItem) {
15719
+ var index = legendItem.datasetIndex;
15720
+ var ci = this.chart;
15721
+ var meta = ci.getDatasetMeta(index);
15722
+
15723
+ // See controller.isDatasetVisible comment
15724
+ meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null;
15725
+
15726
+ // We hid a dataset ... rerender the chart
15727
+ ci.update();
15728
+ },
15729
+
15730
+ onHover: null,
15731
+
15732
+ labels: {
15733
+ boxWidth: 40,
15734
+ padding: 10,
15735
+ // Generates labels shown in the legend
15736
+ // Valid properties to return:
15737
+ // text : text to display
15738
+ // fillStyle : fill of coloured box
15739
+ // strokeStyle: stroke of coloured box
15740
+ // hidden : if this legend item refers to a hidden item
15741
+ // lineCap : cap style for line
15742
+ // lineDash
15743
+ // lineDashOffset :
15744
+ // lineJoin :
15745
+ // lineWidth :
15746
+ generateLabels: function(chart) {
15747
+ var data = chart.data;
15748
+ return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) {
15749
+ return {
15750
+ text: dataset.label,
15751
+ fillStyle: (!helpers.isArray(dataset.backgroundColor) ? dataset.backgroundColor : dataset.backgroundColor[0]),
15752
+ hidden: !chart.isDatasetVisible(i),
15753
+ lineCap: dataset.borderCapStyle,
15754
+ lineDash: dataset.borderDash,
15755
+ lineDashOffset: dataset.borderDashOffset,
15756
+ lineJoin: dataset.borderJoinStyle,
15757
+ lineWidth: dataset.borderWidth,
15758
+ strokeStyle: dataset.borderColor,
15759
+ pointStyle: dataset.pointStyle,
15760
+
15761
+ // Below is extra data used for toggling the datasets
15762
+ datasetIndex: i
15763
+ };
15764
+ }, this) : [];
15765
+ }
15766
+ }
15767
+ },
15768
+
15769
+ legendCallback: function(chart) {
15770
+ var text = [];
15771
+ text.push('<ul class="' + chart.id + '-legend">');
15772
+ for (var i = 0; i < chart.data.datasets.length; i++) {
15773
+ text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"></span>');
15774
+ if (chart.data.datasets[i].label) {
15775
+ text.push(chart.data.datasets[i].label);
15776
+ }
15777
+ text.push('</li>');
15778
+ }
15779
+ text.push('</ul>');
15780
+ return text.join('');
15781
+ }
15782
+ });
15783
+
15784
+ module.exports = function(Chart) {
15785
+
15786
+ var layout = Chart.layoutService;
15787
+ var noop = helpers.noop;
15788
+
15789
+ /**
15790
+ * Helper function to get the box width based on the usePointStyle option
15791
+ * @param labelopts {Object} the label options on the legend
15792
+ * @param fontSize {Number} the label font size
15793
+ * @return {Number} width of the color box area
15794
+ */
15795
+ function getBoxWidth(labelOpts, fontSize) {
15796
+ return labelOpts.usePointStyle ?
15797
+ fontSize * Math.SQRT2 :
15798
+ labelOpts.boxWidth;
15799
+ }
15800
+
15801
+ Chart.Legend = Element.extend({
15802
+
15803
+ initialize: function(config) {
15804
+ helpers.extend(this, config);
15805
+
15806
+ // Contains hit boxes for each dataset (in dataset order)
15807
+ this.legendHitBoxes = [];
15808
+
15809
+ // Are we in doughnut mode which has a different data type
15810
+ this.doughnutMode = false;
15811
+ },
15812
+
15813
+ // These methods are ordered by lifecycle. Utilities then follow.
15814
+ // Any function defined here is inherited by all legend types.
15815
+ // Any function can be extended by the legend type
15816
+
15817
+ beforeUpdate: noop,
15818
+ update: function(maxWidth, maxHeight, margins) {
15819
+ var me = this;
15820
+
15821
+ // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
15822
+ me.beforeUpdate();
15823
+
15824
+ // Absorb the master measurements
15825
+ me.maxWidth = maxWidth;
15826
+ me.maxHeight = maxHeight;
15827
+ me.margins = margins;
15828
+
15829
+ // Dimensions
15830
+ me.beforeSetDimensions();
15831
+ me.setDimensions();
15832
+ me.afterSetDimensions();
15833
+ // Labels
15834
+ me.beforeBuildLabels();
15835
+ me.buildLabels();
15836
+ me.afterBuildLabels();
15837
+
15838
+ // Fit
15839
+ me.beforeFit();
15840
+ me.fit();
15841
+ me.afterFit();
15842
+ //
15843
+ me.afterUpdate();
15844
+
15845
+ return me.minSize;
15846
+ },
15847
+ afterUpdate: noop,
15848
+
15849
+ //
15850
+
15851
+ beforeSetDimensions: noop,
15852
+ setDimensions: function() {
15853
+ var me = this;
15854
+ // Set the unconstrained dimension before label rotation
15855
+ if (me.isHorizontal()) {
15856
+ // Reset position before calculating rotation
15857
+ me.width = me.maxWidth;
15858
+ me.left = 0;
15859
+ me.right = me.width;
15860
+ } else {
15861
+ me.height = me.maxHeight;
15862
+
15863
+ // Reset position before calculating rotation
15864
+ me.top = 0;
15865
+ me.bottom = me.height;
15866
+ }
15867
+
15868
+ // Reset padding
15869
+ me.paddingLeft = 0;
15870
+ me.paddingTop = 0;
15871
+ me.paddingRight = 0;
15872
+ me.paddingBottom = 0;
15873
+
15874
+ // Reset minSize
15875
+ me.minSize = {
15876
+ width: 0,
15877
+ height: 0
15878
+ };
15879
+ },
15880
+ afterSetDimensions: noop,
15881
+
15882
+ //
15883
+
15884
+ beforeBuildLabels: noop,
15885
+ buildLabels: function() {
15886
+ var me = this;
15887
+ var labelOpts = me.options.labels || {};
15888
+ var legendItems = helpers.callback(labelOpts.generateLabels, [me.chart], me) || [];
15889
+
15890
+ if (labelOpts.filter) {
15891
+ legendItems = legendItems.filter(function(item) {
15892
+ return labelOpts.filter(item, me.chart.data);
15893
+ });
15894
+ }
15895
+
15896
+ if (me.options.reverse) {
15897
+ legendItems.reverse();
15898
+ }
15899
+
15900
+ me.legendItems = legendItems;
15901
+ },
15902
+ afterBuildLabels: noop,
15903
+
15904
+ //
15905
+
15906
+ beforeFit: noop,
15907
+ fit: function() {
15908
+ var me = this;
15909
+ var opts = me.options;
15910
+ var labelOpts = opts.labels;
15911
+ var display = opts.display;
15912
+
15913
+ var ctx = me.ctx;
15914
+
15915
+ var globalDefault = defaults.global;
15916
+ var valueOrDefault = helpers.valueOrDefault;
15917
+ var fontSize = valueOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize);
15918
+ var fontStyle = valueOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle);
15919
+ var fontFamily = valueOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily);
15920
+ var labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
15921
+
15922
+ // Reset hit boxes
15923
+ var hitboxes = me.legendHitBoxes = [];
15924
+
15925
+ var minSize = me.minSize;
15926
+ var isHorizontal = me.isHorizontal();
15927
+
15928
+ if (isHorizontal) {
15929
+ minSize.width = me.maxWidth; // fill all the width
15930
+ minSize.height = display ? 10 : 0;
15931
+ } else {
15932
+ minSize.width = display ? 10 : 0;
15933
+ minSize.height = me.maxHeight; // fill all the height
15934
+ }
15935
+
15936
+ // Increase sizes here
15937
+ if (display) {
15938
+ ctx.font = labelFont;
15939
+
15940
+ if (isHorizontal) {
15941
+ // Labels
15942
+
15943
+ // Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one
15944
+ var lineWidths = me.lineWidths = [0];
15945
+ var totalHeight = me.legendItems.length ? fontSize + (labelOpts.padding) : 0;
15946
+
15947
+ ctx.textAlign = 'left';
15948
+ ctx.textBaseline = 'top';
15949
+
15950
+ helpers.each(me.legendItems, function(legendItem, i) {
15951
+ var boxWidth = getBoxWidth(labelOpts, fontSize);
15952
+ var width = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
15953
+
15954
+ if (lineWidths[lineWidths.length - 1] + width + labelOpts.padding >= me.width) {
15955
+ totalHeight += fontSize + (labelOpts.padding);
15956
+ lineWidths[lineWidths.length] = me.left;
15957
+ }
15958
+
15959
+ // Store the hitbox width and height here. Final position will be updated in `draw`
15960
+ hitboxes[i] = {
15961
+ left: 0,
15962
+ top: 0,
15963
+ width: width,
15964
+ height: fontSize
15965
+ };
15966
+
15967
+ lineWidths[lineWidths.length - 1] += width + labelOpts.padding;
15968
+ });
15969
+
15970
+ minSize.height += totalHeight;
15971
+
15972
+ } else {
15973
+ var vPadding = labelOpts.padding;
15974
+ var columnWidths = me.columnWidths = [];
15975
+ var totalWidth = labelOpts.padding;
15976
+ var currentColWidth = 0;
15977
+ var currentColHeight = 0;
15978
+ var itemHeight = fontSize + vPadding;
15979
+
15980
+ helpers.each(me.legendItems, function(legendItem, i) {
15981
+ var boxWidth = getBoxWidth(labelOpts, fontSize);
15982
+ var itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
15983
+
15984
+ // If too tall, go to new column
15985
+ if (currentColHeight + itemHeight > minSize.height) {
15986
+ totalWidth += currentColWidth + labelOpts.padding;
15987
+ columnWidths.push(currentColWidth); // previous column width
15988
+
15989
+ currentColWidth = 0;
15990
+ currentColHeight = 0;
15991
+ }
15992
+
15993
+ // Get max width
15994
+ currentColWidth = Math.max(currentColWidth, itemWidth);
15995
+ currentColHeight += itemHeight;
15996
+
15997
+ // Store the hitbox width and height here. Final position will be updated in `draw`
15998
+ hitboxes[i] = {
15999
+ left: 0,
16000
+ top: 0,
16001
+ width: itemWidth,
16002
+ height: fontSize
16003
+ };
16004
+ });
16005
+
16006
+ totalWidth += currentColWidth;
16007
+ columnWidths.push(currentColWidth);
16008
+ minSize.width += totalWidth;
16009
+ }
16010
+ }
16011
+
16012
+ me.width = minSize.width;
16013
+ me.height = minSize.height;
16014
+ },
16015
+ afterFit: noop,
16016
+
16017
+ // Shared Methods
16018
+ isHorizontal: function() {
16019
+ return this.options.position === 'top' || this.options.position === 'bottom';
16020
+ },
16021
+
16022
+ // Actually draw the legend on the canvas
16023
+ draw: function() {
16024
+ var me = this;
16025
+ var opts = me.options;
16026
+ var labelOpts = opts.labels;
16027
+ var globalDefault = defaults.global;
16028
+ var lineDefault = globalDefault.elements.line;
16029
+ var legendWidth = me.width;
16030
+ var lineWidths = me.lineWidths;
16031
+
16032
+ if (opts.display) {
16033
+ var ctx = me.ctx;
16034
+ var valueOrDefault = helpers.valueOrDefault;
16035
+ var fontColor = valueOrDefault(labelOpts.fontColor, globalDefault.defaultFontColor);
16036
+ var fontSize = valueOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize);
16037
+ var fontStyle = valueOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle);
16038
+ var fontFamily = valueOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily);
16039
+ var labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
16040
+ var cursor;
16041
+
16042
+ // Canvas setup
16043
+ ctx.textAlign = 'left';
16044
+ ctx.textBaseline = 'middle';
16045
+ ctx.lineWidth = 0.5;
16046
+ ctx.strokeStyle = fontColor; // for strikethrough effect
16047
+ ctx.fillStyle = fontColor; // render in correct colour
16048
+ ctx.font = labelFont;
16049
+
16050
+ var boxWidth = getBoxWidth(labelOpts, fontSize);
16051
+ var hitboxes = me.legendHitBoxes;
16052
+
16053
+ // current position
16054
+ var drawLegendBox = function(x, y, legendItem) {
16055
+ if (isNaN(boxWidth) || boxWidth <= 0) {
16056
+ return;
16057
+ }
16058
+
16059
+ // Set the ctx for the box
16060
+ ctx.save();
16061
+
16062
+ ctx.fillStyle = valueOrDefault(legendItem.fillStyle, globalDefault.defaultColor);
16063
+ ctx.lineCap = valueOrDefault(legendItem.lineCap, lineDefault.borderCapStyle);
16064
+ ctx.lineDashOffset = valueOrDefault(legendItem.lineDashOffset, lineDefault.borderDashOffset);
16065
+ ctx.lineJoin = valueOrDefault(legendItem.lineJoin, lineDefault.borderJoinStyle);
16066
+ ctx.lineWidth = valueOrDefault(legendItem.lineWidth, lineDefault.borderWidth);
16067
+ ctx.strokeStyle = valueOrDefault(legendItem.strokeStyle, globalDefault.defaultColor);
16068
+ var isLineWidthZero = (valueOrDefault(legendItem.lineWidth, lineDefault.borderWidth) === 0);
16069
+
16070
+ if (ctx.setLineDash) {
16071
+ // IE 9 and 10 do not support line dash
16072
+ ctx.setLineDash(valueOrDefault(legendItem.lineDash, lineDefault.borderDash));
16073
+ }
16074
+
16075
+ if (opts.labels && opts.labels.usePointStyle) {
16076
+ // Recalculate x and y for drawPoint() because its expecting
16077
+ // x and y to be center of figure (instead of top left)
16078
+ var radius = fontSize * Math.SQRT2 / 2;
16079
+ var offSet = radius / Math.SQRT2;
16080
+ var centerX = x + offSet;
16081
+ var centerY = y + offSet;
16082
+
16083
+ // Draw pointStyle as legend symbol
16084
+ helpers.canvas.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY);
16085
+ } else {
16086
+ // Draw box as legend symbol
16087
+ if (!isLineWidthZero) {
16088
+ ctx.strokeRect(x, y, boxWidth, fontSize);
16089
+ }
16090
+ ctx.fillRect(x, y, boxWidth, fontSize);
16091
+ }
16092
+
16093
+ ctx.restore();
16094
+ };
16095
+ var fillText = function(x, y, legendItem, textWidth) {
16096
+ var halfFontSize = fontSize / 2;
16097
+ var xLeft = boxWidth + halfFontSize + x;
16098
+ var yMiddle = y + halfFontSize;
16099
+
16100
+ ctx.fillText(legendItem.text, xLeft, yMiddle);
16101
+
16102
+ if (legendItem.hidden) {
16103
+ // Strikethrough the text if hidden
16104
+ ctx.beginPath();
16105
+ ctx.lineWidth = 2;
16106
+ ctx.moveTo(xLeft, yMiddle);
16107
+ ctx.lineTo(xLeft + textWidth, yMiddle);
16108
+ ctx.stroke();
16109
+ }
16110
+ };
16111
+
16112
+ // Horizontal
16113
+ var isHorizontal = me.isHorizontal();
16114
+ if (isHorizontal) {
16115
+ cursor = {
16116
+ x: me.left + ((legendWidth - lineWidths[0]) / 2),
16117
+ y: me.top + labelOpts.padding,
16118
+ line: 0
16119
+ };
16120
+ } else {
16121
+ cursor = {
16122
+ x: me.left + labelOpts.padding,
16123
+ y: me.top + labelOpts.padding,
16124
+ line: 0
16125
+ };
16126
+ }
16127
+
16128
+ var itemHeight = fontSize + labelOpts.padding;
16129
+ helpers.each(me.legendItems, function(legendItem, i) {
16130
+ var textWidth = ctx.measureText(legendItem.text).width;
16131
+ var width = boxWidth + (fontSize / 2) + textWidth;
16132
+ var x = cursor.x;
16133
+ var y = cursor.y;
16134
+
16135
+ if (isHorizontal) {
16136
+ if (x + width >= legendWidth) {
16137
+ y = cursor.y += itemHeight;
16138
+ cursor.line++;
16139
+ x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2);
16140
+ }
16141
+ } else if (y + itemHeight > me.bottom) {
16142
+ x = cursor.x = x + me.columnWidths[cursor.line] + labelOpts.padding;
16143
+ y = cursor.y = me.top + labelOpts.padding;
16144
+ cursor.line++;
16145
+ }
16146
+
16147
+ drawLegendBox(x, y, legendItem);
16148
+
16149
+ hitboxes[i].left = x;
16150
+ hitboxes[i].top = y;
16151
+
16152
+ // Fill the actual label
16153
+ fillText(x, y, legendItem, textWidth);
16154
+
16155
+ if (isHorizontal) {
16156
+ cursor.x += width + (labelOpts.padding);
16157
+ } else {
16158
+ cursor.y += itemHeight;
16159
+ }
16160
+
16161
+ });
16162
+ }
16163
+ },
16164
+
16165
+ /**
16166
+ * Handle an event
16167
+ * @private
16168
+ * @param {IEvent} event - The event to handle
16169
+ * @return {Boolean} true if a change occured
16170
+ */
16171
+ handleEvent: function(e) {
16172
+ var me = this;
16173
+ var opts = me.options;
16174
+ var type = e.type === 'mouseup' ? 'click' : e.type;
16175
+ var changed = false;
16176
+
16177
+ if (type === 'mousemove') {
16178
+ if (!opts.onHover) {
16179
+ return;
16180
+ }
16181
+ } else if (type === 'click') {
16182
+ if (!opts.onClick) {
16183
+ return;
16184
+ }
16185
+ } else {
16186
+ return;
16187
+ }
16188
+
16189
+ // Chart event already has relative position in it
16190
+ var x = e.x;
16191
+ var y = e.y;
16192
+
16193
+ if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) {
16194
+ // See if we are touching one of the dataset boxes
16195
+ var lh = me.legendHitBoxes;
16196
+ for (var i = 0; i < lh.length; ++i) {
16197
+ var hitBox = lh[i];
16198
+
16199
+ if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) {
16200
+ // Touching an element
16201
+ if (type === 'click') {
16202
+ // use e.native for backwards compatibility
16203
+ opts.onClick.call(me, e.native, me.legendItems[i]);
16204
+ changed = true;
16205
+ break;
16206
+ } else if (type === 'mousemove') {
16207
+ // use e.native for backwards compatibility
16208
+ opts.onHover.call(me, e.native, me.legendItems[i]);
16209
+ changed = true;
16210
+ break;
16211
+ }
16212
+ }
16213
+ }
16214
+ }
16215
+
16216
+ return changed;
16217
+ }
16218
+ });
16219
+
16220
+ function createNewLegendAndAttach(chart, legendOpts) {
16221
+ var legend = new Chart.Legend({
16222
+ ctx: chart.ctx,
16223
+ options: legendOpts,
16224
+ chart: chart
16225
+ });
16226
+
16227
+ layout.configure(chart, legend, legendOpts);
16228
+ layout.addBox(chart, legend);
16229
+ chart.legend = legend;
16230
+ }
16231
+
16232
+ return {
16233
+ id: 'legend',
16234
+
16235
+ beforeInit: function(chart) {
16236
+ var legendOpts = chart.options.legend;
16237
+
16238
+ if (legendOpts) {
16239
+ createNewLegendAndAttach(chart, legendOpts);
16240
+ }
16241
+ },
16242
+
16243
+ beforeUpdate: function(chart) {
16244
+ var legendOpts = chart.options.legend;
16245
+ var legend = chart.legend;
16246
+
16247
+ if (legendOpts) {
16248
+ helpers.mergeIf(legendOpts, defaults.global.legend);
16249
+
16250
+ if (legend) {
16251
+ layout.configure(chart, legend, legendOpts);
16252
+ legend.options = legendOpts;
16253
+ } else {
16254
+ createNewLegendAndAttach(chart, legendOpts);
16255
+ }
16256
+ } else if (legend) {
16257
+ layout.removeBox(chart, legend);
16258
+ delete chart.legend;
16259
+ }
16260
+ },
16261
+
16262
+ afterEvent: function(chart, e) {
16263
+ var legend = chart.legend;
16264
+ if (legend) {
16265
+ legend.handleEvent(e);
16266
+ }
16267
+ }
16268
+ };
16269
+ };
16270
+
16271
+ },{"25":25,"26":26,"45":45}],51:[function(require,module,exports){
16272
+ 'use strict';
16273
+
16274
+ var defaults = require(25);
16275
+ var Element = require(26);
16276
+ var helpers = require(45);
16277
+
16278
+ defaults._set('global', {
16279
+ title: {
16280
+ display: false,
16281
+ fontStyle: 'bold',
16282
+ fullWidth: true,
16283
+ lineHeight: 1.2,
16284
+ padding: 10,
16285
+ position: 'top',
16286
+ text: '',
16287
+ weight: 2000 // by default greater than legend (1000) to be above
16288
+ }
16289
+ });
16290
+
16291
+ module.exports = function(Chart) {
16292
+
16293
+ var layout = Chart.layoutService;
16294
+ var noop = helpers.noop;
16295
+
16296
+ Chart.Title = Element.extend({
16297
+ initialize: function(config) {
16298
+ var me = this;
16299
+ helpers.extend(me, config);
16300
+
16301
+ // Contains hit boxes for each dataset (in dataset order)
16302
+ me.legendHitBoxes = [];
16303
+ },
16304
+
16305
+ // These methods are ordered by lifecycle. Utilities then follow.
16306
+
16307
+ beforeUpdate: noop,
16308
+ update: function(maxWidth, maxHeight, margins) {
16309
+ var me = this;
16310
+
16311
+ // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
16312
+ me.beforeUpdate();
16313
+
16314
+ // Absorb the master measurements
16315
+ me.maxWidth = maxWidth;
16316
+ me.maxHeight = maxHeight;
16317
+ me.margins = margins;
16318
+
16319
+ // Dimensions
16320
+ me.beforeSetDimensions();
16321
+ me.setDimensions();
16322
+ me.afterSetDimensions();
16323
+ // Labels
16324
+ me.beforeBuildLabels();
16325
+ me.buildLabels();
16326
+ me.afterBuildLabels();
16327
+
16328
+ // Fit
16329
+ me.beforeFit();
16330
+ me.fit();
16331
+ me.afterFit();
16332
+ //
16333
+ me.afterUpdate();
16334
+
16335
+ return me.minSize;
16336
+
16337
+ },
16338
+ afterUpdate: noop,
16339
+
16340
+ //
16341
+
16342
+ beforeSetDimensions: noop,
16343
+ setDimensions: function() {
16344
+ var me = this;
16345
+ // Set the unconstrained dimension before label rotation
16346
+ if (me.isHorizontal()) {
16347
+ // Reset position before calculating rotation
16348
+ me.width = me.maxWidth;
16349
+ me.left = 0;
16350
+ me.right = me.width;
16351
+ } else {
16352
+ me.height = me.maxHeight;
16353
+
16354
+ // Reset position before calculating rotation
16355
+ me.top = 0;
16356
+ me.bottom = me.height;
16357
+ }
16358
+
16359
+ // Reset padding
16360
+ me.paddingLeft = 0;
16361
+ me.paddingTop = 0;
16362
+ me.paddingRight = 0;
16363
+ me.paddingBottom = 0;
16364
+
16365
+ // Reset minSize
16366
+ me.minSize = {
16367
+ width: 0,
16368
+ height: 0
16369
+ };
16370
+ },
16371
+ afterSetDimensions: noop,
16372
+
16373
+ //
16374
+
16375
+ beforeBuildLabels: noop,
16376
+ buildLabels: noop,
16377
+ afterBuildLabels: noop,
16378
+
16379
+ //
16380
+
16381
+ beforeFit: noop,
16382
+ fit: function() {
16383
+ var me = this;
16384
+ var valueOrDefault = helpers.valueOrDefault;
16385
+ var opts = me.options;
16386
+ var display = opts.display;
16387
+ var fontSize = valueOrDefault(opts.fontSize, defaults.global.defaultFontSize);
16388
+ var minSize = me.minSize;
16389
+ var lineCount = helpers.isArray(opts.text) ? opts.text.length : 1;
16390
+ var lineHeight = helpers.options.toLineHeight(opts.lineHeight, fontSize);
16391
+ var textSize = display ? (lineCount * lineHeight) + (opts.padding * 2) : 0;
16392
+
16393
+ if (me.isHorizontal()) {
16394
+ minSize.width = me.maxWidth; // fill all the width
16395
+ minSize.height = textSize;
16396
+ } else {
16397
+ minSize.width = textSize;
16398
+ minSize.height = me.maxHeight; // fill all the height
16399
+ }
16400
+
16401
+ me.width = minSize.width;
16402
+ me.height = minSize.height;
16403
+
16404
+ },
16405
+ afterFit: noop,
16406
+
16407
+ // Shared Methods
16408
+ isHorizontal: function() {
16409
+ var pos = this.options.position;
16410
+ return pos === 'top' || pos === 'bottom';
16411
+ },
16412
+
16413
+ // Actually draw the title block on the canvas
16414
+ draw: function() {
16415
+ var me = this;
16416
+ var ctx = me.ctx;
16417
+ var valueOrDefault = helpers.valueOrDefault;
16418
+ var opts = me.options;
16419
+ var globalDefaults = defaults.global;
16420
+
16421
+ if (opts.display) {
16422
+ var fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize);
16423
+ var fontStyle = valueOrDefault(opts.fontStyle, globalDefaults.defaultFontStyle);
16424
+ var fontFamily = valueOrDefault(opts.fontFamily, globalDefaults.defaultFontFamily);
16425
+ var titleFont = helpers.fontString(fontSize, fontStyle, fontFamily);
16426
+ var lineHeight = helpers.options.toLineHeight(opts.lineHeight, fontSize);
16427
+ var offset = lineHeight / 2 + opts.padding;
16428
+ var rotation = 0;
16429
+ var top = me.top;
16430
+ var left = me.left;
16431
+ var bottom = me.bottom;
16432
+ var right = me.right;
16433
+ var maxWidth, titleX, titleY;
16434
+
16435
+ ctx.fillStyle = valueOrDefault(opts.fontColor, globalDefaults.defaultFontColor); // render in correct colour
16436
+ ctx.font = titleFont;
16437
+
16438
+ // Horizontal
16439
+ if (me.isHorizontal()) {
16440
+ titleX = left + ((right - left) / 2); // midpoint of the width
16441
+ titleY = top + offset;
16442
+ maxWidth = right - left;
16443
+ } else {
16444
+ titleX = opts.position === 'left' ? left + offset : right - offset;
16445
+ titleY = top + ((bottom - top) / 2);
16446
+ maxWidth = bottom - top;
16447
+ rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5);
16448
+ }
16449
+
16450
+ ctx.save();
16451
+ ctx.translate(titleX, titleY);
16452
+ ctx.rotate(rotation);
16453
+ ctx.textAlign = 'center';
16454
+ ctx.textBaseline = 'middle';
16455
+
16456
+ var text = opts.text;
16457
+ if (helpers.isArray(text)) {
16458
+ var y = 0;
16459
+ for (var i = 0; i < text.length; ++i) {
16460
+ ctx.fillText(text[i], 0, y, maxWidth);
16461
+ y += lineHeight;
16462
+ }
16463
+ } else {
16464
+ ctx.fillText(text, 0, 0, maxWidth);
16465
+ }
16466
+
16467
+ ctx.restore();
16468
+ }
16469
+ }
16470
+ });
16471
+
16472
+ function createNewTitleBlockAndAttach(chart, titleOpts) {
16473
+ var title = new Chart.Title({
16474
+ ctx: chart.ctx,
16475
+ options: titleOpts,
16476
+ chart: chart
16477
+ });
16478
+
16479
+ layout.configure(chart, title, titleOpts);
16480
+ layout.addBox(chart, title);
16481
+ chart.titleBlock = title;
16482
+ }
16483
+
16484
+ return {
16485
+ id: 'title',
16486
+
16487
+ beforeInit: function(chart) {
16488
+ var titleOpts = chart.options.title;
16489
+
16490
+ if (titleOpts) {
16491
+ createNewTitleBlockAndAttach(chart, titleOpts);
16492
+ }
16493
+ },
16494
+
16495
+ beforeUpdate: function(chart) {
16496
+ var titleOpts = chart.options.title;
16497
+ var titleBlock = chart.titleBlock;
16498
+
16499
+ if (titleOpts) {
16500
+ helpers.mergeIf(titleOpts, defaults.global.title);
16501
+
16502
+ if (titleBlock) {
16503
+ layout.configure(chart, titleBlock, titleOpts);
16504
+ titleBlock.options = titleOpts;
16505
+ } else {
16506
+ createNewTitleBlockAndAttach(chart, titleOpts);
16507
+ }
16508
+ } else if (titleBlock) {
16509
+ Chart.layoutService.removeBox(chart, titleBlock);
16510
+ delete chart.titleBlock;
16511
+ }
16512
+ }
16513
+ };
16514
+ };
16515
+
16516
+ },{"25":25,"26":26,"45":45}],52:[function(require,module,exports){
16517
+ 'use strict';
16518
+
16519
+ module.exports = function(Chart) {
16520
+
16521
+ // Default config for a category scale
16522
+ var defaultConfig = {
16523
+ position: 'bottom'
16524
+ };
16525
+
16526
+ var DatasetScale = Chart.Scale.extend({
16527
+ /**
16528
+ * Internal function to get the correct labels. If data.xLabels or data.yLabels are defined, use those
16529
+ * else fall back to data.labels
16530
+ * @private
16531
+ */
16532
+ getLabels: function() {
16533
+ var data = this.chart.data;
16534
+ return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels;
16535
+ },
16536
+
16537
+ determineDataLimits: function() {
16538
+ var me = this;
16539
+ var labels = me.getLabels();
16540
+ me.minIndex = 0;
16541
+ me.maxIndex = labels.length - 1;
16542
+ var findIndex;
16543
+
16544
+ if (me.options.ticks.min !== undefined) {
16545
+ // user specified min value
16546
+ findIndex = labels.indexOf(me.options.ticks.min);
16547
+ me.minIndex = findIndex !== -1 ? findIndex : me.minIndex;
16548
+ }
16549
+
16550
+ if (me.options.ticks.max !== undefined) {
16551
+ // user specified max value
16552
+ findIndex = labels.indexOf(me.options.ticks.max);
16553
+ me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex;
16554
+ }
16555
+
16556
+ me.min = labels[me.minIndex];
16557
+ me.max = labels[me.maxIndex];
16558
+ },
16559
+
16560
+ buildTicks: function() {
16561
+ var me = this;
16562
+ var labels = me.getLabels();
16563
+ // If we are viewing some subset of labels, slice the original array
16564
+ me.ticks = (me.minIndex === 0 && me.maxIndex === labels.length - 1) ? labels : labels.slice(me.minIndex, me.maxIndex + 1);
16565
+ },
16566
+
16567
+ getLabelForIndex: function(index, datasetIndex) {
16568
+ var me = this;
16569
+ var data = me.chart.data;
16570
+ var isHorizontal = me.isHorizontal();
16571
+
16572
+ if (data.yLabels && !isHorizontal) {
16573
+ return me.getRightValue(data.datasets[datasetIndex].data[index]);
16574
+ }
16575
+ return me.ticks[index - me.minIndex];
16576
+ },
16577
+
16578
+ // Used to get data value locations. Value can either be an index or a numerical value
16579
+ getPixelForValue: function(value, index) {
16580
+ var me = this;
16581
+ var offset = me.options.offset;
16582
+ // 1 is added because we need the length but we have the indexes
16583
+ var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - (offset ? 0 : 1)), 1);
16584
+
16585
+ // If value is a data object, then index is the index in the data array,
16586
+ // not the index of the scale. We need to change that.
16587
+ var valueCategory;
16588
+ if (value !== undefined && value !== null) {
16589
+ valueCategory = me.isHorizontal() ? value.x : value.y;
16590
+ }
16591
+ if (valueCategory !== undefined || (value !== undefined && isNaN(index))) {
16592
+ var labels = me.getLabels();
16593
+ value = valueCategory || value;
16594
+ var idx = labels.indexOf(value);
16595
+ index = idx !== -1 ? idx : index;
16596
+ }
16597
+
16598
+ if (me.isHorizontal()) {
16599
+ var valueWidth = me.width / offsetAmt;
16600
+ var widthOffset = (valueWidth * (index - me.minIndex));
16601
+
16602
+ if (offset) {
16603
+ widthOffset += (valueWidth / 2);
16604
+ }
16605
+
16606
+ return me.left + Math.round(widthOffset);
16607
+ }
16608
+ var valueHeight = me.height / offsetAmt;
16609
+ var heightOffset = (valueHeight * (index - me.minIndex));
16610
+
16611
+ if (offset) {
16612
+ heightOffset += (valueHeight / 2);
16613
+ }
16614
+
16615
+ return me.top + Math.round(heightOffset);
16616
+ },
16617
+ getPixelForTick: function(index) {
16618
+ return this.getPixelForValue(this.ticks[index], index + this.minIndex, null);
16619
+ },
16620
+ getValueForPixel: function(pixel) {
16621
+ var me = this;
16622
+ var offset = me.options.offset;
16623
+ var value;
16624
+ var offsetAmt = Math.max((me._ticks.length - (offset ? 0 : 1)), 1);
16625
+ var horz = me.isHorizontal();
16626
+ var valueDimension = (horz ? me.width : me.height) / offsetAmt;
16627
+
16628
+ pixel -= horz ? me.left : me.top;
16629
+
16630
+ if (offset) {
16631
+ pixel -= (valueDimension / 2);
16632
+ }
16633
+
16634
+ if (pixel <= 0) {
16635
+ value = 0;
16636
+ } else {
16637
+ value = Math.round(pixel / valueDimension);
16638
+ }
16639
+
16640
+ return value + me.minIndex;
16641
+ },
16642
+ getBasePixel: function() {
16643
+ return this.bottom;
16644
+ }
16645
+ });
16646
+
16647
+ Chart.scaleService.registerScaleType('category', DatasetScale, defaultConfig);
16648
+
16649
+ };
16650
+
16651
+ },{}],53:[function(require,module,exports){
16652
+ 'use strict';
16653
+
16654
+ var defaults = require(25);
16655
+ var helpers = require(45);
16656
+ var Ticks = require(34);
16657
+
16658
+ module.exports = function(Chart) {
16659
+
16660
+ var defaultConfig = {
16661
+ position: 'left',
16662
+ ticks: {
16663
+ callback: Ticks.formatters.linear
16664
+ }
16665
+ };
16666
+
16667
+ var LinearScale = Chart.LinearScaleBase.extend({
16668
+
16669
+ determineDataLimits: function() {
16670
+ var me = this;
16671
+ var opts = me.options;
16672
+ var chart = me.chart;
16673
+ var data = chart.data;
16674
+ var datasets = data.datasets;
16675
+ var isHorizontal = me.isHorizontal();
16676
+ var DEFAULT_MIN = 0;
16677
+ var DEFAULT_MAX = 1;
16678
+
16679
+ function IDMatches(meta) {
16680
+ return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
16681
+ }
16682
+
16683
+ // First Calculate the range
16684
+ me.min = null;
16685
+ me.max = null;
16686
+
16687
+ var hasStacks = opts.stacked;
16688
+ if (hasStacks === undefined) {
16689
+ helpers.each(datasets, function(dataset, datasetIndex) {
16690
+ if (hasStacks) {
16691
+ return;
16692
+ }
16693
+
16694
+ var meta = chart.getDatasetMeta(datasetIndex);
16695
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) &&
16696
+ meta.stack !== undefined) {
16697
+ hasStacks = true;
16698
+ }
16699
+ });
16700
+ }
16701
+
16702
+ if (opts.stacked || hasStacks) {
16703
+ var valuesPerStack = {};
16704
+
16705
+ helpers.each(datasets, function(dataset, datasetIndex) {
16706
+ var meta = chart.getDatasetMeta(datasetIndex);
16707
+ var key = [
16708
+ meta.type,
16709
+ // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined
16710
+ ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''),
16711
+ meta.stack
16712
+ ].join('.');
16713
+
16714
+ if (valuesPerStack[key] === undefined) {
16715
+ valuesPerStack[key] = {
16716
+ positiveValues: [],
16717
+ negativeValues: []
16718
+ };
16719
+ }
16720
+
16721
+ // Store these per type
16722
+ var positiveValues = valuesPerStack[key].positiveValues;
16723
+ var negativeValues = valuesPerStack[key].negativeValues;
16724
+
16725
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
16726
+ helpers.each(dataset.data, function(rawValue, index) {
16727
+ var value = +me.getRightValue(rawValue);
16728
+ if (isNaN(value) || meta.data[index].hidden) {
16729
+ return;
16730
+ }
16731
+
16732
+ positiveValues[index] = positiveValues[index] || 0;
16733
+ negativeValues[index] = negativeValues[index] || 0;
16734
+
16735
+ if (opts.relativePoints) {
16736
+ positiveValues[index] = 100;
16737
+ } else if (value < 0) {
16738
+ negativeValues[index] += value;
16739
+ } else {
16740
+ positiveValues[index] += value;
16741
+ }
16742
+ });
16743
+ }
16744
+ });
16745
+
16746
+ helpers.each(valuesPerStack, function(valuesForType) {
16747
+ var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);
16748
+ var minVal = helpers.min(values);
16749
+ var maxVal = helpers.max(values);
16750
+ me.min = me.min === null ? minVal : Math.min(me.min, minVal);
16751
+ me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
16752
+ });
16753
+
16754
+ } else {
16755
+ helpers.each(datasets, function(dataset, datasetIndex) {
16756
+ var meta = chart.getDatasetMeta(datasetIndex);
16757
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
16758
+ helpers.each(dataset.data, function(rawValue, index) {
16759
+ var value = +me.getRightValue(rawValue);
16760
+ if (isNaN(value) || meta.data[index].hidden) {
16761
+ return;
16762
+ }
16763
+
16764
+ if (me.min === null) {
16765
+ me.min = value;
16766
+ } else if (value < me.min) {
16767
+ me.min = value;
16768
+ }
16769
+
16770
+ if (me.max === null) {
16771
+ me.max = value;
16772
+ } else if (value > me.max) {
16773
+ me.max = value;
16774
+ }
16775
+ });
16776
+ }
16777
+ });
16778
+ }
16779
+
16780
+ me.min = isFinite(me.min) && !isNaN(me.min) ? me.min : DEFAULT_MIN;
16781
+ me.max = isFinite(me.max) && !isNaN(me.max) ? me.max : DEFAULT_MAX;
16782
+
16783
+ // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
16784
+ this.handleTickRangeOptions();
16785
+ },
16786
+ getTickLimit: function() {
16787
+ var maxTicks;
16788
+ var me = this;
16789
+ var tickOpts = me.options.ticks;
16790
+
16791
+ if (me.isHorizontal()) {
16792
+ maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.width / 50));
16793
+ } else {
16794
+ // The factor of 2 used to scale the font size has been experimentally determined.
16795
+ var tickFontSize = helpers.valueOrDefault(tickOpts.fontSize, defaults.global.defaultFontSize);
16796
+ maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.height / (2 * tickFontSize)));
16797
+ }
16798
+
16799
+ return maxTicks;
16800
+ },
16801
+ // Called after the ticks are built. We need
16802
+ handleDirectionalChanges: function() {
16803
+ if (!this.isHorizontal()) {
16804
+ // We are in a vertical orientation. The top value is the highest. So reverse the array
16805
+ this.ticks.reverse();
16806
+ }
16807
+ },
16808
+ getLabelForIndex: function(index, datasetIndex) {
16809
+ return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
16810
+ },
16811
+ // Utils
16812
+ getPixelForValue: function(value) {
16813
+ // This must be called after fit has been run so that
16814
+ // this.left, this.top, this.right, and this.bottom have been defined
16815
+ var me = this;
16816
+ var start = me.start;
16817
+
16818
+ var rightValue = +me.getRightValue(value);
16819
+ var pixel;
16820
+ var range = me.end - start;
16821
+
16822
+ if (me.isHorizontal()) {
16823
+ pixel = me.left + (me.width / range * (rightValue - start));
16824
+ return Math.round(pixel);
16825
+ }
16826
+
16827
+ pixel = me.bottom - (me.height / range * (rightValue - start));
16828
+ return Math.round(pixel);
16829
+ },
16830
+ getValueForPixel: function(pixel) {
16831
+ var me = this;
16832
+ var isHorizontal = me.isHorizontal();
16833
+ var innerDimension = isHorizontal ? me.width : me.height;
16834
+ var offset = (isHorizontal ? pixel - me.left : me.bottom - pixel) / innerDimension;
16835
+ return me.start + ((me.end - me.start) * offset);
16836
+ },
16837
+ getPixelForTick: function(index) {
16838
+ return this.getPixelForValue(this.ticksAsNumbers[index]);
16839
+ }
16840
+ });
16841
+ Chart.scaleService.registerScaleType('linear', LinearScale, defaultConfig);
16842
+
16843
+ };
16844
+
16845
+ },{"25":25,"34":34,"45":45}],54:[function(require,module,exports){
16846
+ 'use strict';
16847
+
16848
+ var helpers = require(45);
16849
+ var Ticks = require(34);
16850
+
16851
+ module.exports = function(Chart) {
16852
+
16853
+ var noop = helpers.noop;
16854
+
16855
+ Chart.LinearScaleBase = Chart.Scale.extend({
16856
+ getRightValue: function(value) {
16857
+ if (typeof value === 'string') {
16858
+ return +value;
16859
+ }
16860
+ return Chart.Scale.prototype.getRightValue.call(this, value);
16861
+ },
16862
+
16863
+ handleTickRangeOptions: function() {
16864
+ var me = this;
16865
+ var opts = me.options;
16866
+ var tickOpts = opts.ticks;
16867
+
16868
+ // If we are forcing it to begin at 0, but 0 will already be rendered on the chart,
16869
+ // do nothing since that would make the chart weird. If the user really wants a weird chart
16870
+ // axis, they can manually override it
16871
+ if (tickOpts.beginAtZero) {
16872
+ var minSign = helpers.sign(me.min);
16873
+ var maxSign = helpers.sign(me.max);
16874
+
16875
+ if (minSign < 0 && maxSign < 0) {
16876
+ // move the top up to 0
16877
+ me.max = 0;
16878
+ } else if (minSign > 0 && maxSign > 0) {
16879
+ // move the bottom down to 0
16880
+ me.min = 0;
16881
+ }
16882
+ }
16883
+
16884
+ var setMin = tickOpts.min !== undefined || tickOpts.suggestedMin !== undefined;
16885
+ var setMax = tickOpts.max !== undefined || tickOpts.suggestedMax !== undefined;
16886
+
16887
+ if (tickOpts.min !== undefined) {
16888
+ me.min = tickOpts.min;
16889
+ } else if (tickOpts.suggestedMin !== undefined) {
16890
+ if (me.min === null) {
16891
+ me.min = tickOpts.suggestedMin;
16892
+ } else {
16893
+ me.min = Math.min(me.min, tickOpts.suggestedMin);
16894
+ }
16895
+ }
16896
+
16897
+ if (tickOpts.max !== undefined) {
16898
+ me.max = tickOpts.max;
16899
+ } else if (tickOpts.suggestedMax !== undefined) {
16900
+ if (me.max === null) {
16901
+ me.max = tickOpts.suggestedMax;
16902
+ } else {
16903
+ me.max = Math.max(me.max, tickOpts.suggestedMax);
16904
+ }
16905
+ }
16906
+
16907
+ if (setMin !== setMax) {
16908
+ // We set the min or the max but not both.
16909
+ // So ensure that our range is good
16910
+ // Inverted or 0 length range can happen when
16911
+ // ticks.min is set, and no datasets are visible
16912
+ if (me.min >= me.max) {
16913
+ if (setMin) {
16914
+ me.max = me.min + 1;
16915
+ } else {
16916
+ me.min = me.max - 1;
16917
+ }
16918
+ }
16919
+ }
16920
+
16921
+ if (me.min === me.max) {
16922
+ me.max++;
16923
+
16924
+ if (!tickOpts.beginAtZero) {
16925
+ me.min--;
16926
+ }
16927
+ }
16928
+ },
16929
+ getTickLimit: noop,
16930
+ handleDirectionalChanges: noop,
16931
+
16932
+ buildTicks: function() {
16933
+ var me = this;
16934
+ var opts = me.options;
16935
+ var tickOpts = opts.ticks;
16936
+
16937
+ // Figure out what the max number of ticks we can support it is based on the size of
16938
+ // the axis area. For now, we say that the minimum tick spacing in pixels must be 50
16939
+ // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
16940
+ // the graph. Make sure we always have at least 2 ticks
16941
+ var maxTicks = me.getTickLimit();
16942
+ maxTicks = Math.max(2, maxTicks);
16943
+
16944
+ var numericGeneratorOptions = {
16945
+ maxTicks: maxTicks,
16946
+ min: tickOpts.min,
16947
+ max: tickOpts.max,
16948
+ stepSize: helpers.valueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize)
16949
+ };
16950
+ var ticks = me.ticks = Ticks.generators.linear(numericGeneratorOptions, me);
16951
+
16952
+ me.handleDirectionalChanges();
16953
+
16954
+ // At this point, we need to update our max and min given the tick values since we have expanded the
16955
+ // range of the scale
16956
+ me.max = helpers.max(ticks);
16957
+ me.min = helpers.min(ticks);
16958
+
16959
+ if (tickOpts.reverse) {
16960
+ ticks.reverse();
16961
+
16962
+ me.start = me.max;
16963
+ me.end = me.min;
16964
+ } else {
16965
+ me.start = me.min;
16966
+ me.end = me.max;
16967
+ }
16968
+ },
16969
+ convertTicksToLabels: function() {
16970
+ var me = this;
16971
+ me.ticksAsNumbers = me.ticks.slice();
16972
+ me.zeroLineIndex = me.ticks.indexOf(0);
16973
+
16974
+ Chart.Scale.prototype.convertTicksToLabels.call(me);
16975
+ }
16976
+ });
16977
+ };
16978
+
16979
+ },{"34":34,"45":45}],55:[function(require,module,exports){
16980
+ 'use strict';
16981
+
16982
+ var helpers = require(45);
16983
+ var Ticks = require(34);
16984
+
16985
+ module.exports = function(Chart) {
16986
+
16987
+ var defaultConfig = {
16988
+ position: 'left',
16989
+
16990
+ // label settings
16991
+ ticks: {
16992
+ callback: Ticks.formatters.logarithmic
16993
+ }
16994
+ };
16995
+
16996
+ var LogarithmicScale = Chart.Scale.extend({
16997
+ determineDataLimits: function() {
16998
+ var me = this;
16999
+ var opts = me.options;
17000
+ var tickOpts = opts.ticks;
17001
+ var chart = me.chart;
17002
+ var data = chart.data;
17003
+ var datasets = data.datasets;
17004
+ var valueOrDefault = helpers.valueOrDefault;
17005
+ var isHorizontal = me.isHorizontal();
17006
+ function IDMatches(meta) {
17007
+ return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
17008
+ }
17009
+
17010
+ // Calculate Range
17011
+ me.min = null;
17012
+ me.max = null;
17013
+ me.minNotZero = null;
17014
+
17015
+ var hasStacks = opts.stacked;
17016
+ if (hasStacks === undefined) {
17017
+ helpers.each(datasets, function(dataset, datasetIndex) {
17018
+ if (hasStacks) {
17019
+ return;
17020
+ }
17021
+
17022
+ var meta = chart.getDatasetMeta(datasetIndex);
17023
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) &&
17024
+ meta.stack !== undefined) {
17025
+ hasStacks = true;
17026
+ }
17027
+ });
17028
+ }
17029
+
17030
+ if (opts.stacked || hasStacks) {
17031
+ var valuesPerStack = {};
17032
+
17033
+ helpers.each(datasets, function(dataset, datasetIndex) {
17034
+ var meta = chart.getDatasetMeta(datasetIndex);
17035
+ var key = [
17036
+ meta.type,
17037
+ // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined
17038
+ ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''),
17039
+ meta.stack
17040
+ ].join('.');
17041
+
17042
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
17043
+ if (valuesPerStack[key] === undefined) {
17044
+ valuesPerStack[key] = [];
17045
+ }
17046
+
17047
+ helpers.each(dataset.data, function(rawValue, index) {
17048
+ var values = valuesPerStack[key];
17049
+ var value = +me.getRightValue(rawValue);
17050
+ if (isNaN(value) || meta.data[index].hidden) {
17051
+ return;
17052
+ }
17053
+
17054
+ values[index] = values[index] || 0;
17055
+
17056
+ if (opts.relativePoints) {
17057
+ values[index] = 100;
17058
+ } else {
17059
+ // Don't need to split positive and negative since the log scale can't handle a 0 crossing
17060
+ values[index] += value;
17061
+ }
17062
+ });
17063
+ }
17064
+ });
17065
+
17066
+ helpers.each(valuesPerStack, function(valuesForType) {
17067
+ var minVal = helpers.min(valuesForType);
17068
+ var maxVal = helpers.max(valuesForType);
17069
+ me.min = me.min === null ? minVal : Math.min(me.min, minVal);
17070
+ me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
17071
+ });
17072
+
17073
+ } else {
17074
+ helpers.each(datasets, function(dataset, datasetIndex) {
17075
+ var meta = chart.getDatasetMeta(datasetIndex);
17076
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
17077
+ helpers.each(dataset.data, function(rawValue, index) {
17078
+ var value = +me.getRightValue(rawValue);
17079
+ if (isNaN(value) || meta.data[index].hidden) {
17080
+ return;
17081
+ }
17082
+
17083
+ if (me.min === null) {
17084
+ me.min = value;
17085
+ } else if (value < me.min) {
17086
+ me.min = value;
17087
+ }
17088
+
17089
+ if (me.max === null) {
17090
+ me.max = value;
17091
+ } else if (value > me.max) {
17092
+ me.max = value;
17093
+ }
17094
+
17095
+ if (value !== 0 && (me.minNotZero === null || value < me.minNotZero)) {
17096
+ me.minNotZero = value;
17097
+ }
17098
+ });
17099
+ }
17100
+ });
17101
+ }
17102
+
17103
+ me.min = valueOrDefault(tickOpts.min, me.min);
17104
+ me.max = valueOrDefault(tickOpts.max, me.max);
17105
+
17106
+ if (me.min === me.max) {
17107
+ if (me.min !== 0 && me.min !== null) {
17108
+ me.min = Math.pow(10, Math.floor(helpers.log10(me.min)) - 1);
17109
+ me.max = Math.pow(10, Math.floor(helpers.log10(me.max)) + 1);
17110
+ } else {
17111
+ me.min = 1;
17112
+ me.max = 10;
17113
+ }
17114
+ }
17115
+ },
17116
+ buildTicks: function() {
17117
+ var me = this;
17118
+ var opts = me.options;
17119
+ var tickOpts = opts.ticks;
17120
+
17121
+ var generationOptions = {
17122
+ min: tickOpts.min,
17123
+ max: tickOpts.max
17124
+ };
17125
+ var ticks = me.ticks = Ticks.generators.logarithmic(generationOptions, me);
17126
+
17127
+ if (!me.isHorizontal()) {
17128
+ // We are in a vertical orientation. The top value is the highest. So reverse the array
17129
+ ticks.reverse();
17130
+ }
17131
+
17132
+ // At this point, we need to update our max and min given the tick values since we have expanded the
17133
+ // range of the scale
17134
+ me.max = helpers.max(ticks);
17135
+ me.min = helpers.min(ticks);
17136
+
17137
+ if (tickOpts.reverse) {
17138
+ ticks.reverse();
17139
+
17140
+ me.start = me.max;
17141
+ me.end = me.min;
17142
+ } else {
17143
+ me.start = me.min;
17144
+ me.end = me.max;
17145
+ }
17146
+ },
17147
+ convertTicksToLabels: function() {
17148
+ this.tickValues = this.ticks.slice();
17149
+
17150
+ Chart.Scale.prototype.convertTicksToLabels.call(this);
17151
+ },
17152
+ // Get the correct tooltip label
17153
+ getLabelForIndex: function(index, datasetIndex) {
17154
+ return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
17155
+ },
17156
+ getPixelForTick: function(index) {
17157
+ return this.getPixelForValue(this.tickValues[index]);
17158
+ },
17159
+ getPixelForValue: function(value) {
17160
+ var me = this;
17161
+ var start = me.start;
17162
+ var newVal = +me.getRightValue(value);
17163
+ var opts = me.options;
17164
+ var tickOpts = opts.ticks;
17165
+ var innerDimension, pixel, range;
17166
+
17167
+ if (me.isHorizontal()) {
17168
+ range = helpers.log10(me.end) - helpers.log10(start); // todo: if start === 0
17169
+ if (newVal === 0) {
17170
+ pixel = me.left;
17171
+ } else {
17172
+ innerDimension = me.width;
17173
+ pixel = me.left + (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));
17174
+ }
17175
+ } else {
17176
+ // Bottom - top since pixels increase downward on a screen
17177
+ innerDimension = me.height;
17178
+ if (start === 0 && !tickOpts.reverse) {
17179
+ range = helpers.log10(me.end) - helpers.log10(me.minNotZero);
17180
+ if (newVal === start) {
17181
+ pixel = me.bottom;
17182
+ } else if (newVal === me.minNotZero) {
17183
+ pixel = me.bottom - innerDimension * 0.02;
17184
+ } else {
17185
+ pixel = me.bottom - innerDimension * 0.02 - (innerDimension * 0.98 / range * (helpers.log10(newVal) - helpers.log10(me.minNotZero)));
17186
+ }
17187
+ } else if (me.end === 0 && tickOpts.reverse) {
17188
+ range = helpers.log10(me.start) - helpers.log10(me.minNotZero);
17189
+ if (newVal === me.end) {
17190
+ pixel = me.top;
17191
+ } else if (newVal === me.minNotZero) {
17192
+ pixel = me.top + innerDimension * 0.02;
17193
+ } else {
17194
+ pixel = me.top + innerDimension * 0.02 + (innerDimension * 0.98 / range * (helpers.log10(newVal) - helpers.log10(me.minNotZero)));
17195
+ }
17196
+ } else if (newVal === 0) {
17197
+ pixel = tickOpts.reverse ? me.top : me.bottom;
17198
+ } else {
17199
+ range = helpers.log10(me.end) - helpers.log10(start);
17200
+ innerDimension = me.height;
17201
+ pixel = me.bottom - (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));
17202
+ }
17203
+ }
17204
+ return pixel;
17205
+ },
17206
+ getValueForPixel: function(pixel) {
17207
+ var me = this;
17208
+ var range = helpers.log10(me.end) - helpers.log10(me.start);
17209
+ var value, innerDimension;
17210
+
17211
+ if (me.isHorizontal()) {
17212
+ innerDimension = me.width;
17213
+ value = me.start * Math.pow(10, (pixel - me.left) * range / innerDimension);
17214
+ } else { // todo: if start === 0
17215
+ innerDimension = me.height;
17216
+ value = Math.pow(10, (me.bottom - pixel) * range / innerDimension) / me.start;
17217
+ }
17218
+ return value;
17219
+ }
17220
+ });
17221
+ Chart.scaleService.registerScaleType('logarithmic', LogarithmicScale, defaultConfig);
17222
+
17223
+ };
17224
+
17225
+ },{"34":34,"45":45}],56:[function(require,module,exports){
17226
+ 'use strict';
17227
+
17228
+ var defaults = require(25);
17229
+ var helpers = require(45);
17230
+ var Ticks = require(34);
17231
+
17232
+ module.exports = function(Chart) {
17233
+
17234
+ var globalDefaults = defaults.global;
17235
+
17236
+ var defaultConfig = {
17237
+ display: true,
17238
+
17239
+ // Boolean - Whether to animate scaling the chart from the centre
17240
+ animate: true,
17241
+ position: 'chartArea',
17242
+
17243
+ angleLines: {
17244
+ display: true,
17245
+ color: 'rgba(0, 0, 0, 0.1)',
17246
+ lineWidth: 1
17247
+ },
17248
+
17249
+ gridLines: {
17250
+ circular: false
17251
+ },
17252
+
17253
+ // label settings
17254
+ ticks: {
17255
+ // Boolean - Show a backdrop to the scale label
17256
+ showLabelBackdrop: true,
17257
+
17258
+ // String - The colour of the label backdrop
17259
+ backdropColor: 'rgba(255,255,255,0.75)',
17260
+
17261
+ // Number - The backdrop padding above & below the label in pixels
17262
+ backdropPaddingY: 2,
17263
+
17264
+ // Number - The backdrop padding to the side of the label in pixels
17265
+ backdropPaddingX: 2,
17266
+
17267
+ callback: Ticks.formatters.linear
17268
+ },
17269
+
17270
+ pointLabels: {
17271
+ // Boolean - if true, show point labels
17272
+ display: true,
17273
+
17274
+ // Number - Point label font size in pixels
17275
+ fontSize: 10,
17276
+
17277
+ // Function - Used to convert point labels
17278
+ callback: function(label) {
17279
+ return label;
17280
+ }
17281
+ }
17282
+ };
17283
+
17284
+ function getValueCount(scale) {
17285
+ var opts = scale.options;
17286
+ return opts.angleLines.display || opts.pointLabels.display ? scale.chart.data.labels.length : 0;
17287
+ }
17288
+
17289
+ function getPointLabelFontOptions(scale) {
17290
+ var pointLabelOptions = scale.options.pointLabels;
17291
+ var fontSize = helpers.valueOrDefault(pointLabelOptions.fontSize, globalDefaults.defaultFontSize);
17292
+ var fontStyle = helpers.valueOrDefault(pointLabelOptions.fontStyle, globalDefaults.defaultFontStyle);
17293
+ var fontFamily = helpers.valueOrDefault(pointLabelOptions.fontFamily, globalDefaults.defaultFontFamily);
17294
+ var font = helpers.fontString(fontSize, fontStyle, fontFamily);
17295
+
17296
+ return {
17297
+ size: fontSize,
17298
+ style: fontStyle,
17299
+ family: fontFamily,
17300
+ font: font
17301
+ };
17302
+ }
17303
+
17304
+ function measureLabelSize(ctx, fontSize, label) {
17305
+ if (helpers.isArray(label)) {
17306
+ return {
17307
+ w: helpers.longestText(ctx, ctx.font, label),
17308
+ h: (label.length * fontSize) + ((label.length - 1) * 1.5 * fontSize)
17309
+ };
17310
+ }
17311
+
17312
+ return {
17313
+ w: ctx.measureText(label).width,
17314
+ h: fontSize
17315
+ };
17316
+ }
17317
+
17318
+ function determineLimits(angle, pos, size, min, max) {
17319
+ if (angle === min || angle === max) {
17320
+ return {
17321
+ start: pos - (size / 2),
17322
+ end: pos + (size / 2)
17323
+ };
17324
+ } else if (angle < min || angle > max) {
17325
+ return {
17326
+ start: pos - size - 5,
17327
+ end: pos
17328
+ };
17329
+ }
17330
+
17331
+ return {
17332
+ start: pos,
17333
+ end: pos + size + 5
17334
+ };
17335
+ }
17336
+
17337
+ /**
17338
+ * Helper function to fit a radial linear scale with point labels
17339
+ */
17340
+ function fitWithPointLabels(scale) {
17341
+ /*
17342
+ * Right, this is really confusing and there is a lot of maths going on here
17343
+ * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
17344
+ *
17345
+ * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif
17346
+ *
17347
+ * Solution:
17348
+ *
17349
+ * We assume the radius of the polygon is half the size of the canvas at first
17350
+ * at each index we check if the text overlaps.
17351
+ *
17352
+ * Where it does, we store that angle and that index.
17353
+ *
17354
+ * After finding the largest index and angle we calculate how much we need to remove
17355
+ * from the shape radius to move the point inwards by that x.
17356
+ *
17357
+ * We average the left and right distances to get the maximum shape radius that can fit in the box
17358
+ * along with labels.
17359
+ *
17360
+ * Once we have that, we can find the centre point for the chart, by taking the x text protrusion
17361
+ * on each side, removing that from the size, halving it and adding the left x protrusion width.
17362
+ *
17363
+ * This will mean we have a shape fitted to the canvas, as large as it can be with the labels
17364
+ * and position it in the most space efficient manner
17365
+ *
17366
+ * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif
17367
+ */
17368
+
17369
+ var plFont = getPointLabelFontOptions(scale);
17370
+
17371
+ // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.
17372
+ // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points
17373
+ var largestPossibleRadius = Math.min(scale.height / 2, scale.width / 2);
17374
+ var furthestLimits = {
17375
+ r: scale.width,
17376
+ l: 0,
17377
+ t: scale.height,
17378
+ b: 0
17379
+ };
17380
+ var furthestAngles = {};
17381
+ var i, textSize, pointPosition;
17382
+
17383
+ scale.ctx.font = plFont.font;
17384
+ scale._pointLabelSizes = [];
17385
+
17386
+ var valueCount = getValueCount(scale);
17387
+ for (i = 0; i < valueCount; i++) {
17388
+ pointPosition = scale.getPointPosition(i, largestPossibleRadius);
17389
+ textSize = measureLabelSize(scale.ctx, plFont.size, scale.pointLabels[i] || '');
17390
+ scale._pointLabelSizes[i] = textSize;
17391
+
17392
+ // Add quarter circle to make degree 0 mean top of circle
17393
+ var angleRadians = scale.getIndexAngle(i);
17394
+ var angle = helpers.toDegrees(angleRadians) % 360;
17395
+ var hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180);
17396
+ var vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270);
17397
+
17398
+ if (hLimits.start < furthestLimits.l) {
17399
+ furthestLimits.l = hLimits.start;
17400
+ furthestAngles.l = angleRadians;
17401
+ }
17402
+
17403
+ if (hLimits.end > furthestLimits.r) {
17404
+ furthestLimits.r = hLimits.end;
17405
+ furthestAngles.r = angleRadians;
17406
+ }
17407
+
17408
+ if (vLimits.start < furthestLimits.t) {
17409
+ furthestLimits.t = vLimits.start;
17410
+ furthestAngles.t = angleRadians;
17411
+ }
17412
+
17413
+ if (vLimits.end > furthestLimits.b) {
17414
+ furthestLimits.b = vLimits.end;
17415
+ furthestAngles.b = angleRadians;
17416
+ }
17417
+ }
17418
+
17419
+ scale.setReductions(largestPossibleRadius, furthestLimits, furthestAngles);
17420
+ }
17421
+
17422
+ /**
17423
+ * Helper function to fit a radial linear scale with no point labels
17424
+ */
17425
+ function fit(scale) {
17426
+ var largestPossibleRadius = Math.min(scale.height / 2, scale.width / 2);
17427
+ scale.drawingArea = Math.round(largestPossibleRadius);
17428
+ scale.setCenterPoint(0, 0, 0, 0);
17429
+ }
17430
+
17431
+ function getTextAlignForAngle(angle) {
17432
+ if (angle === 0 || angle === 180) {
17433
+ return 'center';
17434
+ } else if (angle < 180) {
17435
+ return 'left';
17436
+ }
17437
+
17438
+ return 'right';
17439
+ }
17440
+
17441
+ function fillText(ctx, text, position, fontSize) {
17442
+ if (helpers.isArray(text)) {
17443
+ var y = position.y;
17444
+ var spacing = 1.5 * fontSize;
17445
+
17446
+ for (var i = 0; i < text.length; ++i) {
17447
+ ctx.fillText(text[i], position.x, y);
17448
+ y += spacing;
17449
+ }
17450
+ } else {
17451
+ ctx.fillText(text, position.x, position.y);
17452
+ }
17453
+ }
17454
+
17455
+ function adjustPointPositionForLabelHeight(angle, textSize, position) {
17456
+ if (angle === 90 || angle === 270) {
17457
+ position.y -= (textSize.h / 2);
17458
+ } else if (angle > 270 || angle < 90) {
17459
+ position.y -= textSize.h;
17460
+ }
17461
+ }
17462
+
17463
+ function drawPointLabels(scale) {
17464
+ var ctx = scale.ctx;
17465
+ var valueOrDefault = helpers.valueOrDefault;
17466
+ var opts = scale.options;
17467
+ var angleLineOpts = opts.angleLines;
17468
+ var pointLabelOpts = opts.pointLabels;
17469
+
17470
+ ctx.lineWidth = angleLineOpts.lineWidth;
17471
+ ctx.strokeStyle = angleLineOpts.color;
17472
+
17473
+ var outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max);
17474
+
17475
+ // Point Label Font
17476
+ var plFont = getPointLabelFontOptions(scale);
17477
+
17478
+ ctx.textBaseline = 'top';
17479
+
17480
+ for (var i = getValueCount(scale) - 1; i >= 0; i--) {
17481
+ if (angleLineOpts.display) {
17482
+ var outerPosition = scale.getPointPosition(i, outerDistance);
17483
+ ctx.beginPath();
17484
+ ctx.moveTo(scale.xCenter, scale.yCenter);
17485
+ ctx.lineTo(outerPosition.x, outerPosition.y);
17486
+ ctx.stroke();
17487
+ ctx.closePath();
17488
+ }
17489
+
17490
+ if (pointLabelOpts.display) {
17491
+ // Extra 3px out for some label spacing
17492
+ var pointLabelPosition = scale.getPointPosition(i, outerDistance + 5);
17493
+
17494
+ // Keep this in loop since we may support array properties here
17495
+ var pointLabelFontColor = valueOrDefault(pointLabelOpts.fontColor, globalDefaults.defaultFontColor);
17496
+ ctx.font = plFont.font;
17497
+ ctx.fillStyle = pointLabelFontColor;
17498
+
17499
+ var angleRadians = scale.getIndexAngle(i);
17500
+ var angle = helpers.toDegrees(angleRadians);
17501
+ ctx.textAlign = getTextAlignForAngle(angle);
17502
+ adjustPointPositionForLabelHeight(angle, scale._pointLabelSizes[i], pointLabelPosition);
17503
+ fillText(ctx, scale.pointLabels[i] || '', pointLabelPosition, plFont.size);
17504
+ }
17505
+ }
17506
+ }
17507
+
17508
+ function drawRadiusLine(scale, gridLineOpts, radius, index) {
17509
+ var ctx = scale.ctx;
17510
+ ctx.strokeStyle = helpers.valueAtIndexOrDefault(gridLineOpts.color, index - 1);
17511
+ ctx.lineWidth = helpers.valueAtIndexOrDefault(gridLineOpts.lineWidth, index - 1);
17512
+
17513
+ if (scale.options.gridLines.circular) {
17514
+ // Draw circular arcs between the points
17515
+ ctx.beginPath();
17516
+ ctx.arc(scale.xCenter, scale.yCenter, radius, 0, Math.PI * 2);
17517
+ ctx.closePath();
17518
+ ctx.stroke();
17519
+ } else {
17520
+ // Draw straight lines connecting each index
17521
+ var valueCount = getValueCount(scale);
17522
+
17523
+ if (valueCount === 0) {
17524
+ return;
17525
+ }
17526
+
17527
+ ctx.beginPath();
17528
+ var pointPosition = scale.getPointPosition(0, radius);
17529
+ ctx.moveTo(pointPosition.x, pointPosition.y);
17530
+
17531
+ for (var i = 1; i < valueCount; i++) {
17532
+ pointPosition = scale.getPointPosition(i, radius);
17533
+ ctx.lineTo(pointPosition.x, pointPosition.y);
17534
+ }
17535
+
17536
+ ctx.closePath();
17537
+ ctx.stroke();
17538
+ }
17539
+ }
17540
+
17541
+ function numberOrZero(param) {
17542
+ return helpers.isNumber(param) ? param : 0;
17543
+ }
17544
+
17545
+ var LinearRadialScale = Chart.LinearScaleBase.extend({
17546
+ setDimensions: function() {
17547
+ var me = this;
17548
+ var opts = me.options;
17549
+ var tickOpts = opts.ticks;
17550
+ // Set the unconstrained dimension before label rotation
17551
+ me.width = me.maxWidth;
17552
+ me.height = me.maxHeight;
17553
+ me.xCenter = Math.round(me.width / 2);
17554
+ me.yCenter = Math.round(me.height / 2);
17555
+
17556
+ var minSize = helpers.min([me.height, me.width]);
17557
+ var tickFontSize = helpers.valueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
17558
+ me.drawingArea = opts.display ? (minSize / 2) - (tickFontSize / 2 + tickOpts.backdropPaddingY) : (minSize / 2);
17559
+ },
17560
+ determineDataLimits: function() {
17561
+ var me = this;
17562
+ var chart = me.chart;
17563
+ var min = Number.POSITIVE_INFINITY;
17564
+ var max = Number.NEGATIVE_INFINITY;
17565
+
17566
+ helpers.each(chart.data.datasets, function(dataset, datasetIndex) {
17567
+ if (chart.isDatasetVisible(datasetIndex)) {
17568
+ var meta = chart.getDatasetMeta(datasetIndex);
17569
+
17570
+ helpers.each(dataset.data, function(rawValue, index) {
17571
+ var value = +me.getRightValue(rawValue);
17572
+ if (isNaN(value) || meta.data[index].hidden) {
17573
+ return;
17574
+ }
17575
+
17576
+ min = Math.min(value, min);
17577
+ max = Math.max(value, max);
17578
+ });
17579
+ }
17580
+ });
17581
+
17582
+ me.min = (min === Number.POSITIVE_INFINITY ? 0 : min);
17583
+ me.max = (max === Number.NEGATIVE_INFINITY ? 0 : max);
17584
+
17585
+ // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
17586
+ me.handleTickRangeOptions();
17587
+ },
17588
+ getTickLimit: function() {
17589
+ var tickOpts = this.options.ticks;
17590
+ var tickFontSize = helpers.valueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
17591
+ return Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(this.drawingArea / (1.5 * tickFontSize)));
17592
+ },
17593
+ convertTicksToLabels: function() {
17594
+ var me = this;
17595
+
17596
+ Chart.LinearScaleBase.prototype.convertTicksToLabels.call(me);
17597
+
17598
+ // Point labels
17599
+ me.pointLabels = me.chart.data.labels.map(me.options.pointLabels.callback, me);
17600
+ },
17601
+ getLabelForIndex: function(index, datasetIndex) {
17602
+ return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
17603
+ },
17604
+ fit: function() {
17605
+ if (this.options.pointLabels.display) {
17606
+ fitWithPointLabels(this);
17607
+ } else {
17608
+ fit(this);
17609
+ }
17610
+ },
17611
+ /**
17612
+ * Set radius reductions and determine new radius and center point
17613
+ * @private
17614
+ */
17615
+ setReductions: function(largestPossibleRadius, furthestLimits, furthestAngles) {
17616
+ var me = this;
17617
+ var radiusReductionLeft = furthestLimits.l / Math.sin(furthestAngles.l);
17618
+ var radiusReductionRight = Math.max(furthestLimits.r - me.width, 0) / Math.sin(furthestAngles.r);
17619
+ var radiusReductionTop = -furthestLimits.t / Math.cos(furthestAngles.t);
17620
+ var radiusReductionBottom = -Math.max(furthestLimits.b - me.height, 0) / Math.cos(furthestAngles.b);
17621
+
17622
+ radiusReductionLeft = numberOrZero(radiusReductionLeft);
17623
+ radiusReductionRight = numberOrZero(radiusReductionRight);
17624
+ radiusReductionTop = numberOrZero(radiusReductionTop);
17625
+ radiusReductionBottom = numberOrZero(radiusReductionBottom);
17626
+
17627
+ me.drawingArea = Math.min(
17628
+ Math.round(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2),
17629
+ Math.round(largestPossibleRadius - (radiusReductionTop + radiusReductionBottom) / 2));
17630
+ me.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom);
17631
+ },
17632
+ setCenterPoint: function(leftMovement, rightMovement, topMovement, bottomMovement) {
17633
+ var me = this;
17634
+ var maxRight = me.width - rightMovement - me.drawingArea;
17635
+ var maxLeft = leftMovement + me.drawingArea;
17636
+ var maxTop = topMovement + me.drawingArea;
17637
+ var maxBottom = me.height - bottomMovement - me.drawingArea;
17638
+
17639
+ me.xCenter = Math.round(((maxLeft + maxRight) / 2) + me.left);
17640
+ me.yCenter = Math.round(((maxTop + maxBottom) / 2) + me.top);
17641
+ },
17642
+
17643
+ getIndexAngle: function(index) {
17644
+ var angleMultiplier = (Math.PI * 2) / getValueCount(this);
17645
+ var startAngle = this.chart.options && this.chart.options.startAngle ?
17646
+ this.chart.options.startAngle :
17647
+ 0;
17648
+
17649
+ var startAngleRadians = startAngle * Math.PI * 2 / 360;
17650
+
17651
+ // Start from the top instead of right, so remove a quarter of the circle
17652
+ return index * angleMultiplier + startAngleRadians;
17653
+ },
17654
+ getDistanceFromCenterForValue: function(value) {
17655
+ var me = this;
17656
+
17657
+ if (value === null) {
17658
+ return 0; // null always in center
17659
+ }
17660
+
17661
+ // Take into account half font size + the yPadding of the top value
17662
+ var scalingFactor = me.drawingArea / (me.max - me.min);
17663
+ if (me.options.ticks.reverse) {
17664
+ return (me.max - value) * scalingFactor;
17665
+ }
17666
+ return (value - me.min) * scalingFactor;
17667
+ },
17668
+ getPointPosition: function(index, distanceFromCenter) {
17669
+ var me = this;
17670
+ var thisAngle = me.getIndexAngle(index) - (Math.PI / 2);
17671
+ return {
17672
+ x: Math.round(Math.cos(thisAngle) * distanceFromCenter) + me.xCenter,
17673
+ y: Math.round(Math.sin(thisAngle) * distanceFromCenter) + me.yCenter
17674
+ };
17675
+ },
17676
+ getPointPositionForValue: function(index, value) {
17677
+ return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));
17678
+ },
17679
+
17680
+ getBasePosition: function() {
17681
+ var me = this;
17682
+ var min = me.min;
17683
+ var max = me.max;
17684
+
17685
+ return me.getPointPositionForValue(0,
17686
+ me.beginAtZero ? 0 :
17687
+ min < 0 && max < 0 ? max :
17688
+ min > 0 && max > 0 ? min :
17689
+ 0);
17690
+ },
17691
+
17692
+ draw: function() {
17693
+ var me = this;
17694
+ var opts = me.options;
17695
+ var gridLineOpts = opts.gridLines;
17696
+ var tickOpts = opts.ticks;
17697
+ var valueOrDefault = helpers.valueOrDefault;
17698
+
17699
+ if (opts.display) {
17700
+ var ctx = me.ctx;
17701
+ var startAngle = this.getIndexAngle(0);
17702
+
17703
+ // Tick Font
17704
+ var tickFontSize = valueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
17705
+ var tickFontStyle = valueOrDefault(tickOpts.fontStyle, globalDefaults.defaultFontStyle);
17706
+ var tickFontFamily = valueOrDefault(tickOpts.fontFamily, globalDefaults.defaultFontFamily);
17707
+ var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
17708
+
17709
+ helpers.each(me.ticks, function(label, index) {
17710
+ // Don't draw a centre value (if it is minimum)
17711
+ if (index > 0 || tickOpts.reverse) {
17712
+ var yCenterOffset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]);
17713
+
17714
+ // Draw circular lines around the scale
17715
+ if (gridLineOpts.display && index !== 0) {
17716
+ drawRadiusLine(me, gridLineOpts, yCenterOffset, index);
17717
+ }
17718
+
17719
+ if (tickOpts.display) {
17720
+ var tickFontColor = valueOrDefault(tickOpts.fontColor, globalDefaults.defaultFontColor);
17721
+ ctx.font = tickLabelFont;
17722
+
17723
+ ctx.save();
17724
+ ctx.translate(me.xCenter, me.yCenter);
17725
+ ctx.rotate(startAngle);
17726
+
17727
+ if (tickOpts.showLabelBackdrop) {
17728
+ var labelWidth = ctx.measureText(label).width;
17729
+ ctx.fillStyle = tickOpts.backdropColor;
17730
+ ctx.fillRect(
17731
+ -labelWidth / 2 - tickOpts.backdropPaddingX,
17732
+ -yCenterOffset - tickFontSize / 2 - tickOpts.backdropPaddingY,
17733
+ labelWidth + tickOpts.backdropPaddingX * 2,
17734
+ tickFontSize + tickOpts.backdropPaddingY * 2
17735
+ );
17736
+ }
17737
+
17738
+ ctx.textAlign = 'center';
17739
+ ctx.textBaseline = 'middle';
17740
+ ctx.fillStyle = tickFontColor;
17741
+ ctx.fillText(label, 0, -yCenterOffset);
17742
+ ctx.restore();
17743
+ }
17744
+ }
17745
+ });
17746
+
17747
+ if (opts.angleLines.display || opts.pointLabels.display) {
17748
+ drawPointLabels(me);
17749
+ }
17750
+ }
17751
+ }
17752
+ });
17753
+ Chart.scaleService.registerScaleType('radialLinear', LinearRadialScale, defaultConfig);
17754
+
17755
+ };
17756
+
17757
+ },{"25":25,"34":34,"45":45}],57:[function(require,module,exports){
17758
+ /* global window: false */
17759
+ 'use strict';
17760
+
17761
+ var moment = require(6);
17762
+ moment = typeof moment === 'function' ? moment : window.moment;
17763
+
17764
+ var defaults = require(25);
17765
+ var helpers = require(45);
17766
+
17767
+ // Integer constants are from the ES6 spec.
17768
+ var MIN_INTEGER = Number.MIN_SAFE_INTEGER || -9007199254740991;
17769
+ var MAX_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;
17770
+
17771
+ var INTERVALS = {
17772
+ millisecond: {
17773
+ major: true,
17774
+ size: 1,
17775
+ steps: [1, 2, 5, 10, 20, 50, 100, 250, 500]
17776
+ },
17777
+ second: {
17778
+ major: true,
17779
+ size: 1000,
17780
+ steps: [1, 2, 5, 10, 30]
17781
+ },
17782
+ minute: {
17783
+ major: true,
17784
+ size: 60000,
17785
+ steps: [1, 2, 5, 10, 30]
17786
+ },
17787
+ hour: {
17788
+ major: true,
17789
+ size: 3600000,
17790
+ steps: [1, 2, 3, 6, 12]
17791
+ },
17792
+ day: {
17793
+ major: true,
17794
+ size: 86400000,
17795
+ steps: [1, 2, 5]
17796
+ },
17797
+ week: {
17798
+ major: false,
17799
+ size: 604800000,
17800
+ steps: [1, 2, 3, 4]
17801
+ },
17802
+ month: {
17803
+ major: true,
17804
+ size: 2.628e9,
17805
+ steps: [1, 2, 3]
17806
+ },
17807
+ quarter: {
17808
+ major: false,
17809
+ size: 7.884e9,
17810
+ steps: [1, 2, 3, 4]
17811
+ },
17812
+ year: {
17813
+ major: true,
17814
+ size: 3.154e10
17815
+ }
17816
+ };
17817
+
17818
+ var UNITS = Object.keys(INTERVALS);
17819
+
17820
+ function sorter(a, b) {
17821
+ return a - b;
17822
+ }
17823
+
17824
+ function arrayUnique(items) {
17825
+ var hash = {};
17826
+ var out = [];
17827
+ var i, ilen, item;
17828
+
17829
+ for (i = 0, ilen = items.length; i < ilen; ++i) {
17830
+ item = items[i];
17831
+ if (!hash[item]) {
17832
+ hash[item] = true;
17833
+ out.push(item);
17834
+ }
17835
+ }
17836
+
17837
+ return out;
17838
+ }
17839
+
17840
+ /**
17841
+ * Returns an array of {time, pos} objects used to interpolate a specific `time` or position
17842
+ * (`pos`) on the scale, by searching entries before and after the requested value. `pos` is
17843
+ * a decimal between 0 and 1: 0 being the start of the scale (left or top) and 1 the other
17844
+ * extremity (left + width or top + height). Note that it would be more optimized to directly
17845
+ * store pre-computed pixels, but the scale dimensions are not guaranteed at the time we need
17846
+ * to create the lookup table. The table ALWAYS contains at least two items: min and max.
17847
+ *
17848
+ * @param {Number[]} timestamps - timestamps sorted from lowest to highest.
17849
+ * @param {String} distribution - If 'linear', timestamps will be spread linearly along the min
17850
+ * and max range, so basically, the table will contains only two items: {min, 0} and {max, 1}.
17851
+ * If 'series', timestamps will be positioned at the same distance from each other. In this
17852
+ * case, only timestamps that break the time linearity are registered, meaning that in the
17853
+ * best case, all timestamps are linear, the table contains only min and max.
17854
+ */
17855
+ function buildLookupTable(timestamps, min, max, distribution) {
17856
+ if (distribution === 'linear' || !timestamps.length) {
17857
+ return [
17858
+ {time: min, pos: 0},
17859
+ {time: max, pos: 1}
17860
+ ];
17861
+ }
17862
+
17863
+ var table = [];
17864
+ var items = [min];
17865
+ var i, ilen, prev, curr, next;
17866
+
17867
+ for (i = 0, ilen = timestamps.length; i < ilen; ++i) {
17868
+ curr = timestamps[i];
17869
+ if (curr > min && curr < max) {
17870
+ items.push(curr);
17871
+ }
17872
+ }
17873
+
17874
+ items.push(max);
17875
+
17876
+ for (i = 0, ilen = items.length; i < ilen; ++i) {
17877
+ next = items[i + 1];
17878
+ prev = items[i - 1];
17879
+ curr = items[i];
17880
+
17881
+ // only add points that breaks the scale linearity
17882
+ if (prev === undefined || next === undefined || Math.round((next + prev) / 2) !== curr) {
17883
+ table.push({time: curr, pos: i / (ilen - 1)});
17884
+ }
17885
+ }
17886
+
17887
+ return table;
17888
+ }
17889
+
17890
+ // @see adapted from http://www.anujgakhar.com/2014/03/01/binary-search-in-javascript/
17891
+ function lookup(table, key, value) {
17892
+ var lo = 0;
17893
+ var hi = table.length - 1;
17894
+ var mid, i0, i1;
17895
+
17896
+ while (lo >= 0 && lo <= hi) {
17897
+ mid = (lo + hi) >> 1;
17898
+ i0 = table[mid - 1] || null;
17899
+ i1 = table[mid];
17900
+
17901
+ if (!i0) {
17902
+ // given value is outside table (before first item)
17903
+ return {lo: null, hi: i1};
17904
+ } else if (i1[key] < value) {
17905
+ lo = mid + 1;
17906
+ } else if (i0[key] > value) {
17907
+ hi = mid - 1;
17908
+ } else {
17909
+ return {lo: i0, hi: i1};
17910
+ }
17911
+ }
17912
+
17913
+ // given value is outside table (after last item)
17914
+ return {lo: i1, hi: null};
17915
+ }
17916
+
17917
+ /**
17918
+ * Linearly interpolates the given source `value` using the table items `skey` values and
17919
+ * returns the associated `tkey` value. For example, interpolate(table, 'time', 42, 'pos')
17920
+ * returns the position for a timestamp equal to 42. If value is out of bounds, values at
17921
+ * index [0, 1] or [n - 1, n] are used for the interpolation.
17922
+ */
17923
+ function interpolate(table, skey, sval, tkey) {
17924
+ var range = lookup(table, skey, sval);
17925
+
17926
+ // Note: the lookup table ALWAYS contains at least 2 items (min and max)
17927
+ var prev = !range.lo ? table[0] : !range.hi ? table[table.length - 2] : range.lo;
17928
+ var next = !range.lo ? table[1] : !range.hi ? table[table.length - 1] : range.hi;
17929
+
17930
+ var span = next[skey] - prev[skey];
17931
+ var ratio = span ? (sval - prev[skey]) / span : 0;
17932
+ var offset = (next[tkey] - prev[tkey]) * ratio;
17933
+
17934
+ return prev[tkey] + offset;
17935
+ }
17936
+
17937
+ /**
17938
+ * Convert the given value to a moment object using the given time options.
17939
+ * @see http://momentjs.com/docs/#/parsing/
17940
+ */
17941
+ function momentify(value, options) {
17942
+ var parser = options.parser;
17943
+ var format = options.parser || options.format;
17944
+
17945
+ if (typeof parser === 'function') {
17946
+ return parser(value);
17947
+ }
17948
+
17949
+ if (typeof value === 'string' && typeof format === 'string') {
17950
+ return moment(value, format);
17951
+ }
17952
+
17953
+ if (!(value instanceof moment)) {
17954
+ value = moment(value);
17955
+ }
17956
+
17957
+ if (value.isValid()) {
17958
+ return value;
17959
+ }
17960
+
17961
+ // Labels are in an incompatible moment format and no `parser` has been provided.
17962
+ // The user might still use the deprecated `format` option to convert his inputs.
17963
+ if (typeof format === 'function') {
17964
+ return format(value);
17965
+ }
17966
+
17967
+ return value;
17968
+ }
17969
+
17970
+ function parse(input, scale) {
17971
+ if (helpers.isNullOrUndef(input)) {
17972
+ return null;
17973
+ }
17974
+
17975
+ var options = scale.options.time;
17976
+ var value = momentify(scale.getRightValue(input), options);
17977
+ if (!value.isValid()) {
17978
+ return null;
17979
+ }
17980
+
17981
+ if (options.round) {
17982
+ value.startOf(options.round);
17983
+ }
17984
+
17985
+ return value.valueOf();
17986
+ }
17987
+
17988
+ /**
17989
+ * Returns the number of unit to skip to be able to display up to `capacity` number of ticks
17990
+ * in `unit` for the given `min` / `max` range and respecting the interval steps constraints.
17991
+ */
17992
+ function determineStepSize(min, max, unit, capacity) {
17993
+ var range = max - min;
17994
+ var interval = INTERVALS[unit];
17995
+ var milliseconds = interval.size;
17996
+ var steps = interval.steps;
17997
+ var i, ilen, factor;
17998
+
17999
+ if (!steps) {
18000
+ return Math.ceil(range / ((capacity || 1) * milliseconds));
18001
+ }
18002
+
18003
+ for (i = 0, ilen = steps.length; i < ilen; ++i) {
18004
+ factor = steps[i];
18005
+ if (Math.ceil(range / (milliseconds * factor)) <= capacity) {
18006
+ break;
18007
+ }
18008
+ }
18009
+
18010
+ return factor;
18011
+ }
18012
+
18013
+ function determineUnit(minUnit, min, max, capacity) {
18014
+ var ilen = UNITS.length;
18015
+ var i, interval, factor;
18016
+
18017
+ for (i = UNITS.indexOf(minUnit); i < ilen - 1; ++i) {
18018
+ interval = INTERVALS[UNITS[i]];
18019
+ factor = interval.steps ? interval.steps[interval.steps.length - 1] : MAX_INTEGER;
18020
+
18021
+ if (Math.ceil((max - min) / (factor * interval.size)) <= capacity) {
18022
+ return UNITS[i];
18023
+ }
18024
+ }
18025
+
18026
+ return UNITS[ilen - 1];
18027
+ }
18028
+
18029
+ function determineMajorUnit(unit) {
18030
+ for (var i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i) {
18031
+ if (INTERVALS[UNITS[i]].major) {
18032
+ return UNITS[i];
18033
+ }
18034
+ }
18035
+ }
18036
+
18037
+ /**
18038
+ * Generates a maximum of `capacity` timestamps between min and max, rounded to the
18039
+ * `minor` unit, aligned on the `major` unit and using the given scale time `options`.
18040
+ * Important: this method can return ticks outside the min and max range, it's the
18041
+ * responsibility of the calling code to clamp values if needed.
18042
+ */
18043
+ function generate(min, max, minor, major, capacity, options) {
18044
+ var timeOpts = options.time;
18045
+ var stepSize = helpers.valueOrDefault(timeOpts.stepSize, timeOpts.unitStepSize);
18046
+ var weekday = minor === 'week' ? timeOpts.isoWeekday : false;
18047
+ var majorTicksEnabled = options.ticks.major.enabled;
18048
+ var interval = INTERVALS[minor];
18049
+ var first = moment(min);
18050
+ var last = moment(max);
18051
+ var ticks = [];
18052
+ var time;
18053
+
18054
+ if (!stepSize) {
18055
+ stepSize = determineStepSize(min, max, minor, capacity);
18056
+ }
18057
+
18058
+ // For 'week' unit, handle the first day of week option
18059
+ if (weekday) {
18060
+ first = first.isoWeekday(weekday);
18061
+ last = last.isoWeekday(weekday);
18062
+ }
18063
+
18064
+ // Align first/last ticks on unit
18065
+ first = first.startOf(weekday ? 'day' : minor);
18066
+ last = last.startOf(weekday ? 'day' : minor);
18067
+
18068
+ // Make sure that the last tick include max
18069
+ if (last < max) {
18070
+ last.add(1, minor);
18071
+ }
18072
+
18073
+ time = moment(first);
18074
+
18075
+ if (majorTicksEnabled && major && !weekday && !timeOpts.round) {
18076
+ // Align the first tick on the previous `minor` unit aligned on the `major` unit:
18077
+ // we first aligned time on the previous `major` unit then add the number of full
18078
+ // stepSize there is between first and the previous major time.
18079
+ time.startOf(major);
18080
+ time.add(~~((first - time) / (interval.size * stepSize)) * stepSize, minor);
18081
+ }
18082
+
18083
+ for (; time < last; time.add(stepSize, minor)) {
18084
+ ticks.push(+time);
18085
+ }
18086
+
18087
+ ticks.push(+time);
18088
+
18089
+ return ticks;
18090
+ }
18091
+
18092
+ /**
18093
+ * Returns the right and left offsets from edges in the form of {left, right}.
18094
+ * Offsets are added when the `offset` option is true.
18095
+ */
18096
+ function computeOffsets(table, ticks, min, max, options) {
18097
+ var left = 0;
18098
+ var right = 0;
18099
+ var upper, lower;
18100
+
18101
+ if (options.offset && ticks.length) {
18102
+ if (!options.time.min) {
18103
+ upper = ticks.length > 1 ? ticks[1] : max;
18104
+ lower = ticks[0];
18105
+ left = (
18106
+ interpolate(table, 'time', upper, 'pos') -
18107
+ interpolate(table, 'time', lower, 'pos')
18108
+ ) / 2;
18109
+ }
18110
+ if (!options.time.max) {
18111
+ upper = ticks[ticks.length - 1];
18112
+ lower = ticks.length > 1 ? ticks[ticks.length - 2] : min;
18113
+ right = (
18114
+ interpolate(table, 'time', upper, 'pos') -
18115
+ interpolate(table, 'time', lower, 'pos')
18116
+ ) / 2;
18117
+ }
18118
+ }
18119
+
18120
+ return {left: left, right: right};
18121
+ }
18122
+
18123
+ function ticksFromTimestamps(values, majorUnit) {
18124
+ var ticks = [];
18125
+ var i, ilen, value, major;
18126
+
18127
+ for (i = 0, ilen = values.length; i < ilen; ++i) {
18128
+ value = values[i];
18129
+ major = majorUnit ? value === +moment(value).startOf(majorUnit) : false;
18130
+
18131
+ ticks.push({
18132
+ value: value,
18133
+ major: major
18134
+ });
18135
+ }
18136
+
18137
+ return ticks;
18138
+ }
18139
+
18140
+ module.exports = function(Chart) {
18141
+
18142
+ var defaultConfig = {
18143
+ position: 'bottom',
18144
+
18145
+ /**
18146
+ * Data distribution along the scale:
18147
+ * - 'linear': data are spread according to their time (distances can vary),
18148
+ * - 'series': data are spread at the same distance from each other.
18149
+ * @see https://github.com/chartjs/Chart.js/pull/4507
18150
+ * @since 2.7.0
18151
+ */
18152
+ distribution: 'linear',
18153
+
18154
+ /**
18155
+ * Scale boundary strategy (bypassed by min/max time options)
18156
+ * - `data`: make sure data are fully visible, ticks outside are removed
18157
+ * - `ticks`: make sure ticks are fully visible, data outside are truncated
18158
+ * @see https://github.com/chartjs/Chart.js/pull/4556
18159
+ * @since 2.7.0
18160
+ */
18161
+ bounds: 'data',
18162
+
18163
+ time: {
18164
+ parser: false, // false == a pattern string from http://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment
18165
+ format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from http://momentjs.com/docs/#/parsing/string-format/
18166
+ unit: false, // false == automatic or override with week, month, year, etc.
18167
+ round: false, // none, or override with week, month, year, etc.
18168
+ displayFormat: false, // DEPRECATED
18169
+ isoWeekday: false, // override week start day - see http://momentjs.com/docs/#/get-set/iso-weekday/
18170
+ minUnit: 'millisecond',
18171
+
18172
+ // defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/
18173
+ displayFormats: {
18174
+ millisecond: 'h:mm:ss.SSS a', // 11:20:01.123 AM,
18175
+ second: 'h:mm:ss a', // 11:20:01 AM
18176
+ minute: 'h:mm a', // 11:20 AM
18177
+ hour: 'hA', // 5PM
18178
+ day: 'MMM D', // Sep 4
18179
+ week: 'll', // Week 46, or maybe "[W]WW - YYYY" ?
18180
+ month: 'MMM YYYY', // Sept 2015
18181
+ quarter: '[Q]Q - YYYY', // Q3
18182
+ year: 'YYYY' // 2015
18183
+ },
18184
+ },
18185
+ ticks: {
18186
+ autoSkip: false,
18187
+
18188
+ /**
18189
+ * Ticks generation input values:
18190
+ * - 'auto': generates "optimal" ticks based on scale size and time options.
18191
+ * - 'data': generates ticks from data (including labels from data {t|x|y} objects).
18192
+ * - 'labels': generates ticks from user given `data.labels` values ONLY.
18193
+ * @see https://github.com/chartjs/Chart.js/pull/4507
18194
+ * @since 2.7.0
18195
+ */
18196
+ source: 'auto',
18197
+
18198
+ major: {
18199
+ enabled: false
18200
+ }
18201
+ }
18202
+ };
18203
+
18204
+ var TimeScale = Chart.Scale.extend({
18205
+ initialize: function() {
18206
+ if (!moment) {
18207
+ throw new Error('Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com');
18208
+ }
18209
+
18210
+ this.mergeTicksOptions();
18211
+
18212
+ Chart.Scale.prototype.initialize.call(this);
18213
+ },
18214
+
18215
+ update: function() {
18216
+ var me = this;
18217
+ var options = me.options;
18218
+
18219
+ // DEPRECATIONS: output a message only one time per update
18220
+ if (options.time && options.time.format) {
18221
+ console.warn('options.time.format is deprecated and replaced by options.time.parser.');
18222
+ }
18223
+
18224
+ return Chart.Scale.prototype.update.apply(me, arguments);
18225
+ },
18226
+
18227
+ /**
18228
+ * Allows data to be referenced via 't' attribute
18229
+ */
18230
+ getRightValue: function(rawValue) {
18231
+ if (rawValue && rawValue.t !== undefined) {
18232
+ rawValue = rawValue.t;
18233
+ }
18234
+ return Chart.Scale.prototype.getRightValue.call(this, rawValue);
18235
+ },
18236
+
18237
+ determineDataLimits: function() {
18238
+ var me = this;
18239
+ var chart = me.chart;
18240
+ var timeOpts = me.options.time;
18241
+ var min = parse(timeOpts.min, me) || MAX_INTEGER;
18242
+ var max = parse(timeOpts.max, me) || MIN_INTEGER;
18243
+ var timestamps = [];
18244
+ var datasets = [];
18245
+ var labels = [];
18246
+ var i, j, ilen, jlen, data, timestamp;
18247
+
18248
+ // Convert labels to timestamps
18249
+ for (i = 0, ilen = chart.data.labels.length; i < ilen; ++i) {
18250
+ labels.push(parse(chart.data.labels[i], me));
18251
+ }
18252
+
18253
+ // Convert data to timestamps
18254
+ for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
18255
+ if (chart.isDatasetVisible(i)) {
18256
+ data = chart.data.datasets[i].data;
18257
+
18258
+ // Let's consider that all data have the same format.
18259
+ if (helpers.isObject(data[0])) {
18260
+ datasets[i] = [];
18261
+
18262
+ for (j = 0, jlen = data.length; j < jlen; ++j) {
18263
+ timestamp = parse(data[j], me);
18264
+ timestamps.push(timestamp);
18265
+ datasets[i][j] = timestamp;
18266
+ }
18267
+ } else {
18268
+ timestamps.push.apply(timestamps, labels);
18269
+ datasets[i] = labels.slice(0);
18270
+ }
18271
+ } else {
18272
+ datasets[i] = [];
18273
+ }
18274
+ }
18275
+
18276
+ if (labels.length) {
18277
+ // Sort labels **after** data have been converted
18278
+ labels = arrayUnique(labels).sort(sorter);
18279
+ min = Math.min(min, labels[0]);
18280
+ max = Math.max(max, labels[labels.length - 1]);
18281
+ }
18282
+
18283
+ if (timestamps.length) {
18284
+ timestamps = arrayUnique(timestamps).sort(sorter);
18285
+ min = Math.min(min, timestamps[0]);
18286
+ max = Math.max(max, timestamps[timestamps.length - 1]);
18287
+ }
18288
+
18289
+ // In case there is no valid min/max, let's use today limits
18290
+ min = min === MAX_INTEGER ? +moment().startOf('day') : min;
18291
+ max = max === MIN_INTEGER ? +moment().endOf('day') + 1 : max;
18292
+
18293
+ // Make sure that max is strictly higher than min (required by the lookup table)
18294
+ me.min = Math.min(min, max);
18295
+ me.max = Math.max(min + 1, max);
18296
+
18297
+ // PRIVATE
18298
+ me._horizontal = me.isHorizontal();
18299
+ me._table = [];
18300
+ me._timestamps = {
18301
+ data: timestamps,
18302
+ datasets: datasets,
18303
+ labels: labels
18304
+ };
18305
+ },
18306
+
18307
+ buildTicks: function() {
18308
+ var me = this;
18309
+ var min = me.min;
18310
+ var max = me.max;
18311
+ var options = me.options;
18312
+ var timeOpts = options.time;
18313
+ var formats = timeOpts.displayFormats;
18314
+ var capacity = me.getLabelCapacity(min);
18315
+ var unit = timeOpts.unit || determineUnit(timeOpts.minUnit, min, max, capacity);
18316
+ var majorUnit = determineMajorUnit(unit);
18317
+ var timestamps = [];
18318
+ var ticks = [];
18319
+ var i, ilen, timestamp;
18320
+
18321
+ switch (options.ticks.source) {
18322
+ case 'data':
18323
+ timestamps = me._timestamps.data;
18324
+ break;
18325
+ case 'labels':
18326
+ timestamps = me._timestamps.labels;
18327
+ break;
18328
+ case 'auto':
18329
+ default:
18330
+ timestamps = generate(min, max, unit, majorUnit, capacity, options);
18331
+ }
18332
+
18333
+ if (options.bounds === 'ticks' && timestamps.length) {
18334
+ min = timestamps[0];
18335
+ max = timestamps[timestamps.length - 1];
18336
+ }
18337
+
18338
+ // Enforce limits with user min/max options
18339
+ min = parse(timeOpts.min, me) || min;
18340
+ max = parse(timeOpts.max, me) || max;
18341
+
18342
+ // Remove ticks outside the min/max range
18343
+ for (i = 0, ilen = timestamps.length; i < ilen; ++i) {
18344
+ timestamp = timestamps[i];
18345
+ if (timestamp >= min && timestamp <= max) {
18346
+ ticks.push(timestamp);
18347
+ }
18348
+ }
18349
+
18350
+ me.min = min;
18351
+ me.max = max;
18352
+
18353
+ // PRIVATE
18354
+ me._unit = unit;
18355
+ me._majorUnit = majorUnit;
18356
+ me._minorFormat = formats[unit];
18357
+ me._majorFormat = formats[majorUnit];
18358
+ me._table = buildLookupTable(me._timestamps.data, min, max, options.distribution);
18359
+ me._offsets = computeOffsets(me._table, ticks, min, max, options);
18360
+
18361
+ return ticksFromTimestamps(ticks, majorUnit);
18362
+ },
18363
+
18364
+ getLabelForIndex: function(index, datasetIndex) {
18365
+ var me = this;
18366
+ var data = me.chart.data;
18367
+ var timeOpts = me.options.time;
18368
+ var label = data.labels && index < data.labels.length ? data.labels[index] : '';
18369
+ var value = data.datasets[datasetIndex].data[index];
18370
+
18371
+ if (helpers.isObject(value)) {
18372
+ label = me.getRightValue(value);
18373
+ }
18374
+ if (timeOpts.tooltipFormat) {
18375
+ label = momentify(label, timeOpts).format(timeOpts.tooltipFormat);
18376
+ }
18377
+
18378
+ return label;
18379
+ },
18380
+
18381
+ /**
18382
+ * Function to format an individual tick mark
18383
+ * @private
18384
+ */
18385
+ tickFormatFunction: function(tick, index, ticks) {
18386
+ var me = this;
18387
+ var options = me.options;
18388
+ var time = tick.valueOf();
18389
+ var majorUnit = me._majorUnit;
18390
+ var majorFormat = me._majorFormat;
18391
+ var majorTime = tick.clone().startOf(me._majorUnit).valueOf();
18392
+ var majorTickOpts = options.ticks.major;
18393
+ var major = majorTickOpts.enabled && majorUnit && majorFormat && time === majorTime;
18394
+ var label = tick.format(major ? majorFormat : me._minorFormat);
18395
+ var tickOpts = major ? majorTickOpts : options.ticks.minor;
18396
+ var formatter = helpers.valueOrDefault(tickOpts.callback, tickOpts.userCallback);
18397
+
18398
+ return formatter ? formatter(label, index, ticks) : label;
18399
+ },
18400
+
18401
+ convertTicksToLabels: function(ticks) {
18402
+ var labels = [];
18403
+ var i, ilen;
18404
+
18405
+ for (i = 0, ilen = ticks.length; i < ilen; ++i) {
18406
+ labels.push(this.tickFormatFunction(moment(ticks[i].value), i, ticks));
18407
+ }
18408
+
18409
+ return labels;
18410
+ },
18411
+
18412
+ /**
18413
+ * @private
18414
+ */
18415
+ getPixelForOffset: function(time) {
18416
+ var me = this;
18417
+ var size = me._horizontal ? me.width : me.height;
18418
+ var start = me._horizontal ? me.left : me.top;
18419
+ var pos = interpolate(me._table, 'time', time, 'pos');
18420
+
18421
+ return start + size * (me._offsets.left + pos) / (me._offsets.left + 1 + me._offsets.right);
18422
+ },
18423
+
18424
+ getPixelForValue: function(value, index, datasetIndex) {
18425
+ var me = this;
18426
+ var time = null;
18427
+
18428
+ if (index !== undefined && datasetIndex !== undefined) {
18429
+ time = me._timestamps.datasets[datasetIndex][index];
18430
+ }
18431
+
18432
+ if (time === null) {
18433
+ time = parse(value, me);
18434
+ }
18435
+
18436
+ if (time !== null) {
18437
+ return me.getPixelForOffset(time);
18438
+ }
18439
+ },
18440
+
18441
+ getPixelForTick: function(index) {
18442
+ var ticks = this.getTicks();
18443
+ return index >= 0 && index < ticks.length ?
18444
+ this.getPixelForOffset(ticks[index].value) :
18445
+ null;
18446
+ },
18447
+
18448
+ getValueForPixel: function(pixel) {
18449
+ var me = this;
18450
+ var size = me._horizontal ? me.width : me.height;
18451
+ var start = me._horizontal ? me.left : me.top;
18452
+ var pos = (size ? (pixel - start) / size : 0) * (me._offsets.left + 1 + me._offsets.left) - me._offsets.right;
18453
+ var time = interpolate(me._table, 'pos', pos, 'time');
18454
+
18455
+ return moment(time);
18456
+ },
18457
+
18458
+ /**
18459
+ * Crude approximation of what the label width might be
18460
+ * @private
18461
+ */
18462
+ getLabelWidth: function(label) {
18463
+ var me = this;
18464
+ var ticksOpts = me.options.ticks;
18465
+ var tickLabelWidth = me.ctx.measureText(label).width;
18466
+ var angle = helpers.toRadians(ticksOpts.maxRotation);
18467
+ var cosRotation = Math.cos(angle);
18468
+ var sinRotation = Math.sin(angle);
18469
+ var tickFontSize = helpers.valueOrDefault(ticksOpts.fontSize, defaults.global.defaultFontSize);
18470
+
18471
+ return (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation);
18472
+ },
18473
+
18474
+ /**
18475
+ * @private
18476
+ */
18477
+ getLabelCapacity: function(exampleTime) {
18478
+ var me = this;
18479
+
18480
+ me._minorFormat = me.options.time.displayFormats.millisecond; // Pick the longest format for guestimation
18481
+
18482
+ var exampleLabel = me.tickFormatFunction(moment(exampleTime), 0, []);
18483
+ var tickLabelWidth = me.getLabelWidth(exampleLabel);
18484
+ var innerWidth = me.isHorizontal() ? me.width : me.height;
18485
+
18486
+ return Math.floor(innerWidth / tickLabelWidth);
18487
+ }
18488
+ });
18489
+
18490
+ Chart.scaleService.registerScaleType('time', TimeScale, defaultConfig);
18491
+ };
18492
+
18493
+ },{"25":25,"45":45,"6":6}]},{},[7])(7)
18494
+ });
includes/assets/js/uncompressed/jQuery-Chart/LICENSE.md ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013-2017 Nick Downie
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
includes/assets/js/wp-insert.js CHANGED
@@ -1,4 +1,22 @@
1
- jQuery(document).ready(function() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  wp_insert_click_handler(
3
  'wp_insert_abtesting_configuration',
4
  'Multiple Ad Networks / A-B Testing : Configuration',
@@ -158,6 +176,41 @@ jQuery(document).ready(function() {
158
  function() { }
159
  );
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  wp_insert_inpostads_click_handler('above');
162
  wp_insert_inpostads_click_handler('middle');
163
  wp_insert_inpostads_click_handler('below');
@@ -211,8 +264,61 @@ jQuery(document).ready(function() {
211
  },
212
  function() { }
213
  );
 
 
 
 
 
 
214
  });
215
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
 
217
  function wp_insert_inpostads_click_handler(location) {
218
  wp_insert_click_handler(
@@ -229,6 +335,9 @@ function wp_insert_inpostads_click_handler(location) {
229
  args['wp_insert_nonce'] = jQuery('#wp_insert_nonce').val();
230
  args['wp_insert_inpostads_'+location+'_status'] = jQuery('#wp_insert_inpostads_'+location+'_status').prop('checked');
231
 
 
 
 
232
  args['wp_insert_inpostads_'+location+'_primary_ad_code'] = jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code').val();
233
  args['wp_insert_inpostads_'+location+'_secondary_ad_code'] = jQuery('#wp_insert_inpostads_'+location+'_secondary_ad_code').val();
234
  args['wp_insert_inpostads_'+location+'_tertiary_ad_code'] = jQuery('#wp_insert_inpostads_'+location+'_tertiary_ad_code').val();
@@ -563,12 +672,23 @@ function wp_insert_click_handler(target, title, width, height, openAction, Updat
563
  );
564
  },
565
  buttons: {
566
- 'Update': function() {
567
- UpdateAction();
568
- jQuery(this).dialog('close');
 
 
 
 
 
569
  },
570
- Cancel: function() {
571
- jQuery(this).dialog('close');
 
 
 
 
 
 
572
  }
573
  },
574
  close: function() {
@@ -578,4 +698,379 @@ function wp_insert_click_handler(target, title, width, height, openAction, Updat
578
  })
579
  });
580
  }
581
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function() {
2
+ jQuery(window).resize(function() {
3
+ jQuery('.wp-insert .plugin-card').each(function() {
4
+ jQuery(this).css('height', 'auto');
5
+ });
6
+ jQuery('.wp-insert .plugin-card').each(function() {
7
+ var initialCard = jQuery(this);
8
+ var rowTop = initialCard.position().top;
9
+ jQuery('.wp-insert .plugin-card').each(function() {
10
+ if(rowTop == jQuery(this).position().top) {
11
+ if(initialCard.height() < jQuery(this).height()) {
12
+ initialCard.height(jQuery(this).height());
13
+ }
14
+ }
15
+ });
16
+ });
17
+ });
18
+ jQuery(window).resize();
19
+
20
  wp_insert_click_handler(
21
  'wp_insert_abtesting_configuration',
22
  'Multiple Ad Networks / A-B Testing : Configuration',
176
  function() { }
177
  );
178
 
179
+ wp_insert_click_handler(
180
+ 'wp_insert_adstxt_generate',
181
+ 'Create / Update ads.txt',
182
+ jQuery("body").width() * 0.8,
183
+ jQuery("body").height() * 0.8,
184
+ function() {
185
+ jQuery('#wp_insert_adstxt_content').css('height', (jQuery('body').height() * 0.5)+'px');
186
+ jQuery('.ui-dialog-buttonset').find('button').first().unbind('click').click(function() {
187
+ jQuery('.ui-dialog-buttonset').find('button').last().button('disable');
188
+ jQuery('.ui-dialog-titlebar').find('button').last().button('disable');
189
+ var wp_insert_adstxt_content = jQuery('#wp_insert_adstxt_content').val();
190
+ jQuery('.ui-dialog-content').html('<div class="wp_insert_ajaxloader"></div>');
191
+ jQuery('.wp_insert_ajaxloader').show();
192
+ jQuery.post(
193
+ jQuery('#wp_insert_admin_ajax').val(), {
194
+ 'action': 'wp_insert_adstxt_generate_form_save_action',
195
+ 'wp_insert_nonce': jQuery('#wp_insert_nonce').val(),
196
+ 'wp_insert_adstxt_content': wp_insert_adstxt_content,
197
+ }, function(response) {
198
+ if(response == '###SUCCESS###') {
199
+ jQuery('.ui-dialog-titlebar').find('button').last().button('enable').click();
200
+ } else {
201
+ jQuery('.ui-dialog-buttonset').find('button').first().button('disable');
202
+ jQuery('.ui-dialog-buttonset').find('button').last().button('enable');
203
+ jQuery('.ui-dialog-titlebar').find('button').last().button('enable');
204
+ jQuery('.ui-dialog-content').html(response);
205
+ }
206
+ }
207
+ );
208
+ });
209
+ },
210
+ function() { },
211
+ function() { }
212
+ );
213
+
214
  wp_insert_inpostads_click_handler('above');
215
  wp_insert_inpostads_click_handler('middle');
216
  wp_insert_inpostads_click_handler('below');
264
  },
265
  function() { }
266
  );
267
+
268
+ wp_insert_vi_signup_handler();
269
+ wp_insert_vi_login_handler();
270
+ wp_insert_vi_logout_handler();
271
+ wp_insert_vi_customize_adcode();
272
+ wp_insert_vi_chart_draw()
273
  });
274
 
275
+ function primary_ad_code_type_change() {
276
+ var location = '';
277
+ if(jQuery('#wp_insert_inpostads_above_primary_ad_code_type').length != 0) {
278
+ location = 'above';
279
+ } else if(jQuery('#wp_insert_inpostads_middle_primary_ad_code_type').length != 0) {
280
+ location = 'middle';
281
+ } else {
282
+ location = '';
283
+ }
284
+ if(location != '') {
285
+ jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code_type').parent().hide();
286
+ jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code_type').change(function() {
287
+ jQuery('.isSelectedIndicator').removeClass('active');
288
+ jQuery('#primary_ad_code_type_'+jQuery(this).val()).addClass('active');
289
+ });
290
+ jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code_type').change();
291
+
292
+ jQuery('#primary_ad_code_type_generic').click(function() {
293
+ jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code_type').val('generic');
294
+ jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code_type').change();
295
+ });
296
+ jQuery('#primary_ad_code_type_generic').parent().click(function() {
297
+ jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code_type').val('generic');
298
+ jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code_type').change();
299
+ });
300
+
301
+ jQuery('#primary_ad_code_type_vicode').click(function() {
302
+ if(!jQuery('#primary_ad_code_type_vicode').hasClass('disabled')) {
303
+ jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code_type').val('vicode');
304
+ jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code_type').change();
305
+ }
306
+ });
307
+ jQuery('#primary_ad_code_type_vicode').parent().click(function() {
308
+ if(!jQuery('#primary_ad_code_type_vicode').hasClass('disabled')) {
309
+ jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code_type').val('vicode');
310
+ jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code_type').change();
311
+ }
312
+ });
313
+ }
314
+ }
315
+
316
+ function wp_insert_inpostads_vi_customize_adcode() {
317
+ jQuery('#wp_insert_inpostads_vi_customize_adcode').click(function() {
318
+ jQuery('.ui-dialog-titlebar').find('button').last().button('enable').click();
319
+ jQuery('#wp_insert_vi_customize_adcode').click();
320
+ });
321
+ }
322
 
323
  function wp_insert_inpostads_click_handler(location) {
324
  wp_insert_click_handler(
335
  args['wp_insert_nonce'] = jQuery('#wp_insert_nonce').val();
336
  args['wp_insert_inpostads_'+location+'_status'] = jQuery('#wp_insert_inpostads_'+location+'_status').prop('checked');
337
 
338
+ if(location == 'above' || location == 'middle') {
339
+ args['wp_insert_inpostads_'+location+'_primary_ad_code_type'] = jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code_type').val();
340
+ }
341
  args['wp_insert_inpostads_'+location+'_primary_ad_code'] = jQuery('#wp_insert_inpostads_'+location+'_primary_ad_code').val();
342
  args['wp_insert_inpostads_'+location+'_secondary_ad_code'] = jQuery('#wp_insert_inpostads_'+location+'_secondary_ad_code').val();
343
  args['wp_insert_inpostads_'+location+'_tertiary_ad_code'] = jQuery('#wp_insert_inpostads_'+location+'_tertiary_ad_code').val();
672
  );
673
  },
674
  buttons: {
675
+ 'Update': {
676
+ text: 'Update',
677
+ icons: { primary: "ui-icon-gear" },
678
+ click: function() {
679
+ if(UpdateAction() != 'false') {
680
+ jQuery(this).dialog('close');
681
+ }
682
+ }
683
  },
684
+ Cancel: {
685
+ text: 'Cancel',
686
+ icons: { primary: "ui-icon-cancel" },
687
+ click: function() {
688
+ if(closeAction() != 'false') {
689
+ jQuery(this).dialog('close');
690
+ }
691
+ }
692
  }
693
  },
694
  close: function() {
698
  })
699
  });
700
  }
701
+
702
+ function wp_insert_adstxt_add_entry() {
703
+ var wp_insert_adstxt_new_entry_domain = jQuery("#wp_insert_adstxt_new_entry_domain").val();
704
+ var wp_insert_adstxt_new_entry_pid = jQuery("#wp_insert_adstxt_new_entry_pid").val();
705
+ var wp_insert_adstxt_new_entry_type = jQuery("#wp_insert_adstxt_new_entry_type").val();
706
+ var wp_insert_adstxt_new_entry_certauthority = jQuery("#wp_insert_adstxt_new_entry_certauthority").val();
707
+ var wp_insert_adstxt_content = jQuery("#wp_insert_adstxt_content").val();
708
+ var defaultBorderColor = jQuery("#wp_insert_adstxt_new_entry_domain").css("border-color");
709
+ var defaultLabelColor = jQuery("#wp_insert_adstxt_new_entry_domain").parent().find("small").css("color");
710
+
711
+ var isValidated = true;
712
+ jQuery("#wp_insert_adstxt_new_entry_domain").css({"border-color": defaultBorderColor}).parent().find("small").css({"color": defaultLabelColor});
713
+ jQuery("#wp_insert_adstxt_new_entry_pid").css({"border-color": defaultBorderColor}).parent().find("small").css({"color": defaultLabelColor});
714
+
715
+
716
+ if(wp_insert_adstxt_new_entry_domain == '') {
717
+ jQuery("#wp_insert_adstxt_new_entry_domain").css({"border-color": "#B20303"}).parent().find("small").css({"color": "#B20303"});
718
+ isValidated = false;
719
+ }
720
+ if(wp_insert_adstxt_new_entry_pid == '') {
721
+ jQuery("#wp_insert_adstxt_new_entry_pid").css({"border-color": "#B20303"}).parent().find("small").css({"color": "#B20303"});
722
+ isValidated = false;
723
+ }
724
+
725
+ if(isValidated) {
726
+ if((wp_insert_adstxt_content != '') && (jQuery.inArray((wp_insert_adstxt_content[wp_insert_adstxt_content.length -1]), ["\r", "\n"]) == -1)) {
727
+ wp_insert_adstxt_content += '\r\n';
728
+ }
729
+ wp_insert_adstxt_content += wp_insert_adstxt_new_entry_domain + ', ' + wp_insert_adstxt_new_entry_pid + ', ' + wp_insert_adstxt_new_entry_type;
730
+ if(wp_insert_adstxt_new_entry_certauthority != '') {
731
+ wp_insert_adstxt_content += ', ' + wp_insert_adstxt_new_entry_certauthority;
732
+ }
733
+ jQuery("#wp_insert_adstxt_content").val(wp_insert_adstxt_content);
734
+
735
+ jQuery("#wp_insert_adstxt_new_entry_domain").val('');
736
+ jQuery("#wp_insert_adstxt_new_entry_pid").val('');
737
+ jQuery("#wp_insert_adstxt_new_entry_type").val('DIRECT');
738
+ jQuery("#wp_insert_adstxt_new_entry_certauthority").val('');
739
+
740
+ jQuery("#wp_insert_adstxt_accordion").accordion({active: 0});
741
+ jQuery("#wp_insert_adstxt_content").focus();
742
+ }
743
+ }
744
+
745
+ function wp_insert_adstxt_content_download() {
746
+ var blob = new Blob([jQuery("#wp_insert_adstxt_content").val()], {type: 'text/csv'});
747
+ if(window.navigator.msSaveOrOpenBlob) {
748
+ window.navigator.msSaveBlob(blob, 'ads.txt');
749
+ }
750
+ else{
751
+ var elem = window.document.createElement('a');
752
+ elem.href = window.URL.createObjectURL(blob);
753
+ elem.download = 'ads.txt';
754
+ document.body.appendChild(elem);
755
+ elem.click();
756
+ document.body.removeChild(elem);
757
+ }
758
+ }
759
+
760
+ function wp_insert_vi_signup_handler() {
761
+ wp_insert_click_handler(
762
+ 'wp_insert_vi_signup',
763
+ 'video intelligence: Signup',
764
+ '870',
765
+ '554',
766
+ function() { },
767
+ function() { },
768
+ function() { }
769
+ );
770
+ }
771
+
772
+ function wp_insert_vi_login_handler() {
773
+ wp_insert_click_handler(
774
+ 'wp_insert_vi_login',
775
+ 'video intelligence: Login',
776
+ '540',
777
+ '540',
778
+ function() {
779
+ jQuery('.ui-dialog-buttonset').find('button').first().unbind('click').click(function() {
780
+ if((jQuery('#wp_insert_vi_login_username').val() != '') && (jQuery('#wp_insert_vi_login_password').val() != '')) {
781
+ jQuery('.ui-dialog-buttonset').find('button').first().button('disable');
782
+ jQuery('.ui-dialog-buttonset').find('button').last().button('disable');
783
+ jQuery('.ui-dialog-titlebar').find('button').last().button('disable');
784
+ var wp_insert_vi_login_username = jQuery('#wp_insert_vi_login_username').val();
785
+ var wp_insert_vi_login_password = jQuery('#wp_insert_vi_login_password').val();
786
+ jQuery('.ui-dialog-content').html('<div class="wp_insert_ajaxloader"></div>');
787
+ jQuery('.wp_insert_ajaxloader').show();
788
+ jQuery.post(
789
+ jQuery('#wp_insert_admin_ajax').val(), {
790
+ 'action': 'wp_insert_vi_login_form_save_action',
791
+ 'wp_insert_nonce': jQuery('#wp_insert_nonce').val(),
792
+ 'wp_insert_vi_login_username': wp_insert_vi_login_username,
793
+ 'wp_insert_vi_login_password': wp_insert_vi_login_password,
794
+ }, function(response) {
795
+ if(response.indexOf('###SUCCESS###') !== -1) {
796
+ jQuery.post(
797
+ jQuery('#wp_insert_admin_ajax').val(), {
798
+ 'action': 'wp_insert_vi_update_adstxt',
799
+ 'wp_insert_nonce': jQuery('#wp_insert_nonce').val(),
800
+ }, function(response) {
801
+ if(response.indexOf('###SUCCESS###') !== -1) {
802
+ jQuery('.wrap #wp_insert_title').after(response.replace('###SUCCESS###', ''));
803
+ } else if(response.indexOf('###FAIL###') !== -1) {
804
+ jQuery('.wrap #wp_insert_title').after(response.replace('###FAIL###', ''));
805
+ } else {
806
+ }
807
+ }
808
+ );
809
+ jQuery('.vi-card .plugin-card-bottom, .vi-card .plugin-card-top-content').animate({'opacity': 0}, 1000);
810
+ jQuery('.vi-card').html(response.replace('###SUCCESS###', ''));
811
+ wp_insert_vi_logout_handler();
812
+ wp_insert_vi_customize_adcode();
813
+ wp_insert_vi_chart_draw();
814
+ jQuery(window).resize();
815
+ jQuery('.vi-card .plugin-card-bottom, .vi-card .plugin-card-top-content').animate({'opacity': 1}, 1000);
816
+ jQuery('.ui-dialog-titlebar').find('button').last().button('enable').click();
817
+ } else {
818
+ jQuery('.ui-dialog-buttonset').find('button').first().button('enable');
819
+ jQuery('.ui-dialog-buttonset').find('button').last().button('enable');
820
+ jQuery('.ui-dialog-titlebar').find('button').last().button('enable');
821
+ jQuery('.ui-dialog-content').html(response);
822
+ }
823
+ }
824
+ );
825
+ } else {
826
+ jQuery('#wp_insert_vi_login_username').css('border-color', '#dddddd');
827
+ jQuery('#wp_insert_vi_login_password').css('border-color', '#dddddd');
828
+ if(jQuery('#wp_insert_vi_login_username').val() == '') {
829
+ jQuery('#wp_insert_vi_login_username').css('border-color', '#ff0000');
830
+ }
831
+ if(jQuery('#wp_insert_vi_login_password').val() == '') {
832
+ jQuery('#wp_insert_vi_login_password').css('border-color', '#ff0000');
833
+ }
834
+ }
835
+ });
836
+ },
837
+ function() { },
838
+ function() { }
839
+ );
840
+ }
841
+
842
+ function wp_insert_vi_customize_adcode() {
843
+ wp_insert_click_handler(
844
+ 'wp_insert_vi_customize_adcode',
845
+ 'video intelligence: Customize vi Code',
846
+ jQuery("body").width() * 0.8,
847
+ jQuery("body").height() * 0.8,
848
+ function() {
849
+ jQuery('#wp_insert_vi_code_settings_keywords').attr('maxlength', '200');
850
+ jQuery('#wp_insert_vi_code_settings_optional_1').attr('maxlength', '200');
851
+ jQuery('#wp_insert_vi_code_settings_optional_2').attr('maxlength', '200');
852
+ jQuery('#wp_insert_vi_code_settings_optional_3').attr('maxlength', '200');
853
+ jQuery('.ui-dialog-buttonset').find('button').first().unbind('click').click(function() {
854
+ var keywordsRegex = /[ ,a-zA-Z0-9-’'‘\u00C6\u00D0\u018E\u018F\u0190\u0194\u0132\u014A\u0152\u1E9E\u00DE\u01F7\u021C\u00E6\u00F0\u01DD\u0259\u025B\u0263\u0133\u014B\u0153\u0138\u017F\u00DF\u00FE\u01BF\u021D\u0104\u0181\u00C7\u0110\u018A\u0118\u0126\u012E\u0198\u0141\u00D8\u01A0\u015E\u0218\u0162\u021A\u0166\u0172\u01AFY\u0328\u01B3\u0105\u0253\u00E7\u0111\u0257\u0119\u0127\u012F\u0199\u0142\u00F8\u01A1\u015F\u0219\u0163\u021B\u0167\u0173\u01B0y\u0328\u01B4\u00C1\u00C0\u00C2\u00C4\u01CD\u0102\u0100\u00C3\u00C5\u01FA\u0104\u00C6\u01FC\u01E2\u0181\u0106\u010A\u0108\u010C\u00C7\u010E\u1E0C\u0110\u018A\u00D0\u00C9\u00C8\u0116\u00CA\u00CB\u011A\u0114\u0112\u0118\u1EB8\u018E\u018F\u0190\u0120\u011C\u01E6\u011E\u0122\u0194\u00E1\u00E0\u00E2\u00E4\u01CE\u0103\u0101\u00E3\u00E5\u01FB\u0105\u00E6\u01FD\u01E3\u0253\u0107\u010B\u0109\u010D\u00E7\u010F\u1E0D\u0111\u0257\u00F0\u00E9\u00E8\u0117\u00EA\u00EB\u011B\u0115\u0113\u0119\u1EB9\u01DD\u0259\u025B\u0121\u011D\u01E7\u011F\u0123\u0263\u0124\u1E24\u0126I\u00CD\u00CC\u0130\u00CE\u00CF\u01CF\u012C\u012A\u0128\u012E\u1ECA\u0132\u0134\u0136\u0198\u0139\u013B\u0141\u013D\u013F\u02BCN\u0143N\u0308\u0147\u00D1\u0145\u014A\u00D3\u00D2\u00D4\u00D6\u01D1\u014E\u014C\u00D5\u0150\u1ECC\u00D8\u01FE\u01A0\u0152\u0125\u1E25\u0127\u0131\u00ED\u00ECi\u00EE\u00EF\u01D0\u012D\u012B\u0129\u012F\u1ECB\u0133\u0135\u0137\u0199\u0138\u013A\u013C\u0142\u013E\u0140\u0149\u0144n\u0308\u0148\u00F1\u0146\u014B\u00F3\u00F2\u00F4\u00F6\u01D2\u014F\u014D\u00F5\u0151\u1ECD\u00F8\u01FF\u01A1\u0153\u0154\u0158\u0156\u015A\u015C\u0160\u015E\u0218\u1E62\u1E9E\u0164\u0162\u1E6C\u0166\u00DE\u00DA\u00D9\u00DB\u00DC\u01D3\u016C\u016A\u0168\u0170\u016E\u0172\u1EE4\u01AF\u1E82\u1E80\u0174\u1E84\u01F7\u00DD\u1EF2\u0176\u0178\u0232\u1EF8\u01B3\u0179\u017B\u017D\u1E92\u0155\u0159\u0157\u017F\u015B\u015D\u0161\u015F\u0219\u1E63\u00DF\u0165\u0163\u1E6D\u0167\u00FE\u00FA\u00F9\u00FB\u00FC\u01D4\u016D\u016B\u0169\u0171\u016F\u0173\u1EE5\u01B0\u1E83\u1E81\u0175\u1E85\u01BF\u00FD\u1EF3\u0177\u00FF\u0233\u1EF9\u01B4\u017A\u017C\u017E\u1E93]/g;
855
+ if(
856
+ (jQuery('#wp_insert_vi_code_settings_ad_unit_type').val() != 'select') &&
857
+ (jQuery('#wp_insert_vi_code_settings_iab_category_child').val() != 'select') &&
858
+ (jQuery('#wp_insert_vi_code_settings_language').val() != 'select') &&
859
+ ((jQuery('#wp_insert_vi_code_settings_keywords').val() == '') || ((jQuery(jQuery('#wp_insert_vi_code_settings_keywords').val().match(/./g)).not(jQuery('#wp_insert_vi_code_settings_keywords').val().match(keywordsRegex)).get().length == 0) && (jQuery('#wp_insert_vi_code_settings_keywords').val().length < 200)))
860
+ ) {
861
+ jQuery('.ui-dialog-buttonset').find('button').first().button('disable');
862
+ jQuery('.ui-dialog-buttonset').find('button').last().button('disable');
863
+ jQuery('.ui-dialog-titlebar').find('button').last().button('disable');
864
+ var wp_insert_vi_code_settings_ad_unit_type = jQuery('#wp_insert_vi_code_settings_ad_unit_type').val();
865
+ var wp_insert_vi_code_settings_keywords = jQuery('#wp_insert_vi_code_settings_keywords').val();
866
+ var wp_insert_vi_code_settings_iab_category_parent = jQuery('#wp_insert_vi_code_settings_iab_category_parent').val();
867
+ var wp_insert_vi_code_settings_iab_category_child = jQuery('#wp_insert_vi_code_settings_iab_category_child').val();
868
+ var wp_insert_vi_code_settings_language = jQuery('#wp_insert_vi_code_settings_language').val();
869
+ var wp_insert_vi_code_settings_native_bg_color = jQuery('#wp_insert_vi_code_settings_native_bg_color').val();
870
+ var wp_insert_vi_code_settings_native_text_color = jQuery('#wp_insert_vi_code_settings_native_text_color').val();
871
+ var wp_insert_vi_code_settings_font_family = jQuery('#wp_insert_vi_code_settings_font_family').val();
872
+ var wp_insert_vi_code_settings_font_size = jQuery('#wp_insert_vi_code_settings_font_size').val();
873
+ var wp_insert_vi_code_settings_optional_1 = jQuery('#wp_insert_vi_code_settings_optional_1').val();
874
+ var wp_insert_vi_code_settings_optional_2 = jQuery('#wp_insert_vi_code_settings_optional_2').val();
875
+ var wp_insert_vi_code_settings_optional_3 = jQuery('#wp_insert_vi_code_settings_optional_3').val();
876
+ jQuery('.ui-dialog-content').html('<div class="wp_insert_ajaxloader"></div>');
877
+ jQuery('.wp_insert_ajaxloader').show();
878
+ jQuery.post(
879
+ jQuery('#wp_insert_admin_ajax').val(), {
880
+ 'action': 'wp_insert_vi_customize_adcode_form_save_action',
881
+ 'wp_insert_nonce': jQuery('#wp_insert_nonce').val(),
882
+ 'wp_insert_vi_code_settings_ad_unit_type': wp_insert_vi_code_settings_ad_unit_type,
883
+ 'wp_insert_vi_code_settings_keywords': wp_insert_vi_code_settings_keywords,
884
+ 'wp_insert_vi_code_settings_iab_category_parent': wp_insert_vi_code_settings_iab_category_parent,
885
+ 'wp_insert_vi_code_settings_iab_category_child': wp_insert_vi_code_settings_iab_category_child,
886
+ 'wp_insert_vi_code_settings_language': wp_insert_vi_code_settings_language,
887
+ 'wp_insert_vi_code_settings_native_bg_color': wp_insert_vi_code_settings_native_bg_color,
888
+ 'wp_insert_vi_code_settings_native_text_color': wp_insert_vi_code_settings_native_text_color,
889
+ 'wp_insert_vi_code_settings_font_family': wp_insert_vi_code_settings_font_family,
890
+ 'wp_insert_vi_code_settings_font_size': wp_insert_vi_code_settings_font_size,
891
+ 'wp_insert_vi_code_settings_optional_1': wp_insert_vi_code_settings_optional_1,
892
+ 'wp_insert_vi_code_settings_optional_2': wp_insert_vi_code_settings_optional_2,
893
+ 'wp_insert_vi_code_settings_optional_3': wp_insert_vi_code_settings_optional_3,
894
+ }, function(response) {
895
+ if(response.indexOf('###SUCCESS###') !== -1) {
896
+ jQuery('.ui-dialog-titlebar').find('button').last().button('enable').click();
897
+ } else {
898
+ jQuery('.ui-dialog-buttonset').find('button').first().button('disable');
899
+ jQuery('.ui-dialog-buttonset').find('button').last().button('enable');
900
+ jQuery('.ui-dialog-titlebar').find('button').last().button('enable');
901
+ jQuery('.ui-dialog-content').html(response.replace('###FAIL###', ''));
902
+ }
903
+ }
904
+ );
905
+ } else {
906
+ jQuery('#wp_insert_vi_customize_adcode_keywords_required_error').hide();
907
+ jQuery('#wp_insert_vi_customize_adcode_keywords_error').hide();
908
+ jQuery('#wp_insert_vi_customize_adcode_required_error').hide();
909
+ jQuery('#wp_insert_vi_code_settings_ad_unit_type').css('border-color', '#dddddd');
910
+ jQuery('#wp_insert_vi_code_settings_iab_category_parent').css('border-color', '#dddddd');
911
+ jQuery('#wp_insert_vi_code_settings_iab_category_child').css('border-color', '#dddddd');
912
+ jQuery('#wp_insert_vi_code_settings_language').css('border-color', '#dddddd');
913
+ jQuery('#wp_insert_vi_code_settings_keywords').css('border-color', '#dddddd');
914
+ var wp_insert_vi_customize_adcode_keywords_error = false;
915
+ var wp_insert_vi_customize_adcode_required_error = false;
916
+ if(jQuery('#wp_insert_vi_code_settings_ad_unit_type').val() == 'select') {
917
+ jQuery('#wp_insert_vi_code_settings_ad_unit_type').css('border-color', '#ff0000');
918
+ wp_insert_vi_customize_adcode_required_error = true;
919
+ }
920
+ if(jQuery('#wp_insert_vi_code_settings_iab_category_parent').val() == 'select') {
921
+ jQuery('#wp_insert_vi_code_settings_iab_category_parent').css('border-color', '#ff0000');
922
+ wp_insert_vi_customize_adcode_required_error = true;
923
+ }
924
+ if(jQuery('#wp_insert_vi_code_settings_iab_category_child').val() == 'select') {
925
+ jQuery('#wp_insert_vi_code_settings_iab_category_child').css('border-color', '#ff0000');
926
+ wp_insert_vi_customize_adcode_required_error = true;
927
+ }
928
+ if(jQuery('#wp_insert_vi_code_settings_language').val() == 'select') {
929
+ jQuery('#wp_insert_vi_code_settings_language').css('border-color', '#ff0000');
930
+ wp_insert_vi_customize_adcode_required_error = true;
931
+ }
932
+ if(jQuery('#wp_insert_vi_code_settings_keywords').val() != '') {
933
+ if(jQuery('#wp_insert_vi_code_settings_keywords').val().length > 200) {
934
+ jQuery('#wp_insert_vi_code_settings_keywords').css('border-color', '#ff0000');
935
+ wp_insert_vi_customize_adcode_keywords_error = true;
936
+ }
937
+ if(jQuery(jQuery('#wp_insert_vi_code_settings_keywords').val().match(/./g)).not(jQuery('#wp_insert_vi_code_settings_keywords').val().match(keywordsRegex)).get().length != 0) {
938
+ jQuery('#wp_insert_vi_code_settings_keywords').css('border-color', '#ff0000');
939
+ wp_insert_vi_customize_adcode_keywords_error = true;
940
+ }
941
+ }
942
+ if(wp_insert_vi_customize_adcode_keywords_error && wp_insert_vi_customize_adcode_required_error) {
943
+ jQuery('#wp_insert_vi_customize_adcode_keywords_required_error').show();
944
+ } else if(wp_insert_vi_customize_adcode_keywords_error) {
945
+ jQuery('#wp_insert_vi_customize_adcode_keywords_error').show();
946
+ } else if(wp_insert_vi_customize_adcode_required_error) {
947
+ jQuery('#wp_insert_vi_customize_adcode_required_error').show();
948
+ } else {}
949
+ }
950
+ });
951
+ },
952
+ function() { },
953
+ function() { }
954
+ );
955
+ }
956
+
957
+ function wp_insert_vi_code_iab_category_parent_change() {
958
+ jQuery('#wp_insert_vi_code_settings_iab_category_parent').change(function() {
959
+ var wp_insert_vi_code_iab_category = jQuery(this).val();
960
+ jQuery('#wp_insert_vi_code_settings_iab_category_child option').prop('disabled', true).hide();
961
+ jQuery('#wp_insert_vi_code_settings_iab_category_child option').each(function() {
962
+ if((jQuery(this).attr('data-parent') == wp_insert_vi_code_iab_category) || (jQuery(this).val() == 'select')) {
963
+ jQuery(this).prop('disabled', false).show();
964
+ }
965
+ });
966
+ if(jQuery('#wp_insert_vi_code_settings_iab_category_child option:selected').prop('disabled') != false) {
967
+ jQuery('#wp_insert_vi_code_settings_iab_category_child').val('select');
968
+ }
969
+ });
970
+ jQuery('#wp_insert_vi_code_settings_iab_category_parent').change();
971
+ }
972
+
973
+ function wp_insert_vi_logout_handler() {
974
+ jQuery('#wp_insert_vi_logout').click(function() {
975
+ jQuery.post(
976
+ jQuery('#wp_insert_admin_ajax').val(), {
977
+ 'action': 'wp_insert_vi_logout_action',
978
+ 'wp_insert_nonce': jQuery('#wp_insert_nonce').val(),
979
+ }, function(response) {
980
+ if(response.indexOf('###SUCCESS###') !== -1) {
981
+ jQuery('.vi-card').html(response.replace('###SUCCESS###', ''));
982
+ wp_insert_vi_signup_handler();
983
+ wp_insert_vi_login_handler();
984
+ jQuery(window).resize();
985
+ }
986
+ jQuery('.vi-card .plugin-card-bottom, .vi-card .plugin-card-top-content').animate({'opacity': 1}, 1000);
987
+ }
988
+ );
989
+ jQuery('.vi-card .plugin-card-bottom, .vi-card .plugin-card-top-content').animate({'opacity': 0}, 1000);
990
+
991
+ });
992
+ }
993
+
994
+ function wp_insert_vi_chart_draw() {
995
+ if(jQuery('#wp_insert_vi_earnings_wrapper').length) {
996
+ jQuery.post(
997
+ jQuery('#wp_insert_admin_ajax').val(), {
998
+ 'action': 'wp_insert_vi_get_chart',
999
+ 'wp_insert_nonce': jQuery('#wp_insert_nonce').val(),
1000
+ }, function(response) {
1001
+ if(response.indexOf('###SUCCESS###') !== -1) {
1002
+ jQuery('#wp_insert_vi_earnings_wrapper').html(response.replace('###SUCCESS###', ''));
1003
+ if(jQuery('#wp_insert_vi_chart_data').length) {
1004
+ var ctx = document.getElementById("myChart");
1005
+ var wp_insert_vi_chart = new Chart(jQuery('#wp_insert_vi_chart'), {
1006
+ type: 'line',
1007
+ data: {
1008
+ datasets: [{
1009
+ data: JSON.parse(jQuery('#wp_insert_vi_chart_data').val()),
1010
+ backgroundColor: '#EDF5FB',
1011
+ borderColor: '#186EAE',/*E8EBEF*/
1012
+ borderWidth: 1
1013
+ }]
1014
+ },
1015
+ options: {
1016
+ title: {
1017
+ display: false,
1018
+ backgroundColor: '#EDF5FB'
1019
+ },
1020
+ legend: {
1021
+ display: false,
1022
+ },
1023
+ scales: {
1024
+ xAxes: [{
1025
+ type: "time",
1026
+ display: true,
1027
+ scaleLabel: {
1028
+ display: false
1029
+ },
1030
+ gridLines: {
1031
+ display: false,
1032
+ drawTicks: false
1033
+ },
1034
+ ticks: {
1035
+ display: false
1036
+ }
1037
+ }],
1038
+ yAxes: [{
1039
+ display: true,
1040
+ scaleLabel: {
1041
+ display: false
1042
+ },
1043
+ gridLines: {
1044
+ display: true,
1045
+ drawTicks: false
1046
+ },
1047
+ ticks: {
1048
+ display: false
1049
+ }
1050
+ }]
1051
+ },
1052
+ tooltips: {
1053
+ displayColors: false,
1054
+ callbacks: {
1055
+ label: function(tooltipItem, data) {
1056
+ return '$ '+parseFloat(tooltipItem.yLabel).toFixed(2);
1057
+ },
1058
+ title: function(tooltipItem, data) {
1059
+ var monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
1060
+ var dateParts = tooltipItem[0].xLabel.split('/');
1061
+ var date = new Date(dateParts[2], dateParts[0]-1, dateParts[1]);
1062
+ return monthNames[date.getMonth()]+' '+date.getDate();
1063
+ }
1064
+ }
1065
+ }
1066
+ }
1067
+ });
1068
+ }
1069
+ } else {
1070
+ jQuery('#wp_insert_vi_earnings_wrapper').parent().html(response);
1071
+ }
1072
+ jQuery(window).resize();
1073
+ }
1074
+ );
1075
+ }
1076
+ }
includes/common/abtesting.php CHANGED
@@ -1,15 +1,33 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /* Begin AB Testing Content */
3
  add_action('wp_ajax_wp_insert_abtesting_configuration_form_get_content', 'wp_insert_abtesting_configuration_form_get_content');
4
  function wp_insert_abtesting_configuration_form_get_content() {
5
  check_ajax_referer('wp-insert', 'wp_insert_nonce');
 
6
  $abtestingMode = get_option('wp_insert_abtesting_mode', 1);
7
  $abtestingModes = array(
8
  array('value' => '1', 'text' => 'Primary Ad Network'),
9
  array('value' => '2', 'text' => 'Primary and Secondary Ad Networks'),
10
  array('value' => '3', 'text' => 'All Ad Networks'),
11
  );
12
-
13
  echo '<div class="wp_insert_popup_content_wrapper">';
14
  $control = new smartlogixControls(array('type' => 'radio-group', 'id' => 'wp_insert_abtesting_mode', 'name' => 'wp_insert_abtesting_mode', 'label' => 'Select the Ad Network Setup that best suits you', 'value' => $abtestingMode, 'options' => $abtestingModes));
15
  $control->add_control();
1
  <?php
2
+ /* Begin Add Card in Admin Panel */
3
+ add_action('wp_insert_plugin_card', 'wp_insert_abtesting_plugin_card', 60);
4
+ function wp_insert_abtesting_plugin_card() {
5
+ echo '<div class="plugin-card">';
6
+ echo '<div class="plugin-card-top">';
7
+ echo '<h4>Multiple Ad Networks / A-B Testing</h4>';
8
+ echo '<p>Multiple Ad Networks can be setup to display ads from different networks without infringing the terms of any network.';
9
+ echo 'At a time only ads from one network (Randomly Choosen) will be shown.';
10
+ echo 'This feature can also be used to randomly display different sized Ads from the same network.';
11
+ echo 'Please note that this option is global and applied to In-Post Ads, Ad Widgets and In-Theme Ads.</p>';
12
+ echo '</div>';
13
+ echo '<div class="plugin-card-bottom">';
14
+ echo '<p><a id="wp_insert_abtesting_configuration" href="javascript:;">Configuration</a></p>';
15
+ echo '</div>';
16
+ echo '</div>';
17
+ }
18
+ /* End Add Card in Admin Panel */
19
+
20
  /* Begin AB Testing Content */
21
  add_action('wp_ajax_wp_insert_abtesting_configuration_form_get_content', 'wp_insert_abtesting_configuration_form_get_content');
22
  function wp_insert_abtesting_configuration_form_get_content() {
23
  check_ajax_referer('wp-insert', 'wp_insert_nonce');
24
+
25
  $abtestingMode = get_option('wp_insert_abtesting_mode', 1);
26
  $abtestingModes = array(
27
  array('value' => '1', 'text' => 'Primary Ad Network'),
28
  array('value' => '2', 'text' => 'Primary and Secondary Ad Networks'),
29
  array('value' => '3', 'text' => 'All Ad Networks'),
30
  );
 
31
  echo '<div class="wp_insert_popup_content_wrapper">';
32
  $control = new smartlogixControls(array('type' => 'radio-group', 'id' => 'wp_insert_abtesting_mode', 'name' => 'wp_insert_abtesting_mode', 'label' => 'Select the Ad Network Setup that best suits you', 'value' => $abtestingMode, 'options' => $abtestingModes));
33
  $control->add_control();
includes/common/adstxt.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ function wp_insert_adstxt_file_exists() {
3
+ if(file_exists(trailingslashit(get_home_path()).'ads.txt')) {
4
+ return true;
5
+ }
6
+ return false;
7
+ }
8
+
9
+ function wp_insert_adstxt_get_content() {
10
+ if(wp_insert_adstxt_file_exists()) {
11
+ return @file_get_contents(trailingslashit(get_home_path()).'ads.txt');
12
+ }
13
+ return '';
14
+ }
15
+
16
+ function wp_insert_adstxt_update_content($content) {
17
+ if(get_filesystem_method() === 'direct') {
18
+ $creds = request_filesystem_credentials(site_url().'/wp-admin/', '', false, false, array());
19
+ if(!WP_Filesystem($creds)) {
20
+ return false;
21
+ }
22
+ global $wp_filesystem;
23
+ if(!$wp_filesystem->put_contents(trailingslashit(get_home_path()).'ads.txt', $content, FS_CHMOD_FILE)) {
24
+ return false;
25
+ }
26
+ } else {
27
+ return false;
28
+ }
29
+ return true;
30
+ }
31
+
32
+ function wp_insert_adstxt_updation_failed_message($content) {
33
+ $output = '<div class="wp_insert_popup_content_wrapper">';
34
+ $output .= '<p>Auto Creation / Updation of ads.txt failed due to access permission restrictions on the server.</p>';
35
+ $output .= '<p>You have to manually upload the file using your Host\'s File manager or your favourite FTP program</p>';
36
+ $output .= '<p>ads.txt should be located in the root of your server. After manually uploading the file click <a href="'.site_url().'/ads.txt">here</a> to check if its accessible from the correct location</p>';
37
+ $output .= '<textarea style="display: none;" id="wp_insert_adstxt_content">'.$content.'</textarea>';
38
+ $output .= '<p><a onclick="wp_insert_adstxt_content_download()" class="button button-primary" href="javascript:;">Download ads.txt</a></p>';
39
+ $output .= '</div>';
40
+ return $output;
41
+ }
42
+ ?>
includes/common/common.php CHANGED
@@ -21,5 +21,14 @@ function wp_insert_add_ordinal_number_suffix($num) {
21
  }
22
  return $num.'th';
23
  }
 
 
 
 
 
 
 
 
 
24
  /* End Misc Functions */
25
  ?>
21
  }
22
  return $num.'th';
23
  }
24
+
25
+ function wp_insert_get_domain_name_from_url($url){
26
+ $pieces = parse_url($url);
27
+ $domain = isset($pieces['host']) ? $pieces['host'] : '';
28
+ if(preg_match('/(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', $domain, $regs)){
29
+ return $regs['domain'];
30
+ }
31
+ return false;
32
+ }
33
  /* End Misc Functions */
34
  ?>
includes/common/control-panel.php CHANGED
@@ -9,12 +9,14 @@ function wp_insert_admin_enqueue_scripts($page) {
9
  wp_register_script('wp-insert-global-js', WP_INSERT_URL.'includes/assets/js/wp-insert-global.js', array('jquery'), WP_INSERT_VERSION);
10
  wp_enqueue_script('wp-insert-global-js');
11
  if($page == 'toplevel_page_wp-insert') {
12
- wp_register_style('wp-insert-css', WP_INSERT_URL.'includes/assets/css/wp-insert.css', array(), WP_INSERT_VERSION);
13
  wp_enqueue_style('wp-insert-css');
14
  wp_register_style('wp-insert-jquery-ui', 'https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css', array(), WP_INSERT_VERSION);
15
  wp_enqueue_style('wp-insert-jquery-ui');
16
- wp_register_script('wp-insert-js', WP_INSERT_URL.'includes/assets/js/wp-insert.js', array('jquery', 'jquery-ui-core', 'jquery-ui-accordion', 'jquery-ui-dialog'), WP_INSERT_VERSION);
17
  wp_enqueue_script('wp-insert-js');
 
 
18
  smartlogixControls::enqueue_assets(WP_INSERT_URL.'includes/controls', WP_INSERT_VERSION);
19
  wp_enqueue_script('editor');
20
  wp_enqueue_script('quicktags');
@@ -24,117 +26,9 @@ function wp_insert_admin_enqueue_scripts($page) {
24
 
25
  function wp_insert_admin_page() { ?>
26
  <div class="wrap wp-insert">
27
- <h1></h1>
28
  <div class="wp-list-table widefat plugin-install">
29
- <div class="plugin-card">
30
- <div class="plugin-card-top">
31
- <a id="wpInsertLogo" href="http://www.wp-insert.smartlogix.co.in"><img src="<?php echo WP_INSERT_URL; ?>/includes/assets/images/header-banner.png" /></a>
32
- </div>
33
- <div class="plugin-card-bottom">
34
- <div id="wpInsertMeta">
35
- <p><b>Donate :</b><br /><a target="_blank" href="http://wpinsert.smartlogix.co.in/support/">Click Here</a> to Donate and Promote further development of this plugin.</p>
36
- <p><b>Like Us :</b><br /><a target="_blank" href="https://www.facebook.com/SmartLogix/">Click here</a> to like and support us on Facebook</p>
37
- <p><b>Hire Me :</b><br /><a target="_blank" title="Hire me! on Freelancer.com" href="https://www.freelancer.com/affiliates/email/899781/" target="_blank">Hire Me on Freelancer</a> (<i>Hourly : $30 Minimum Hire Period 2 Hour / $60</i>)</p>
38
- <p><b>Rate and Review :</b><br />If you find this plugin useful do leave a honest <a target="_blank" href="http://wordpress.org/plugins/wp-insert">RATING</a> and <a target="_blank" href="https://wordpress.org/support/view/plugin-reviews/wp-insert#postform">REVIEW</a></p>
39
- </div>
40
- </div>
41
- </div>
42
-
43
- <div class="plugin-card">
44
- <div class="plugin-card-top">
45
- <h4>In-Post Ads</h4>
46
- <p>Ads shown within the post content.</p>
47
- </div>
48
- <div class="plugin-card-bottom">
49
- <p><a id="wp_insert_inpostads_above" href="javascript:;">Ad - Above Post Content</a></p>
50
- <p><a id="wp_insert_inpostads_middle" href="javascript:;">Ad - Middle of Post Content</a></p>
51
- <p><a id="wp_insert_inpostads_below" href="javascript:;">Ad - Below Post Content</a></p>
52
- <p><a id="wp_insert_inpostads_left" href="javascript:;">Ad - Left of Post Content</a></p>
53
- <p><a id="wp_insert_inpostads_right" href="javascript:;">Ad - Right of Post Content</a></p>
54
- </div>
55
- </div>
56
-
57
- <div class="plugin-card">
58
- <div class="plugin-card-top">
59
- <h4>Ad Widgets</h4>
60
- <p>Ads shown inside widget enabled areas.</p>
61
- </div>
62
- <div class="plugin-card-bottom">
63
- <?php
64
- $adwidgets = get_option('wp_insert_adwidgets');
65
- if(isset($adwidgets) && is_array($adwidgets)) {
66
- foreach($adwidgets as $key => $value) {
67
- echo '<p>';
68
- echo '<a id="wp_insert_adwidgets_'.$key.'" href="javascript:;" onclick="wp_insert_adwidgets_click_handler(\''.$key.'\', \''.$value['title'].'\')">Ad Widget : '.$value['title'].'</a>';
69
- echo '<span class="dashicons dashicons-dismiss wp_insert_delete_icon" onclick="wp_insert_adwidgets_remove(\''.$key.'\')"></span>';
70
- echo '</p>';
71
- }
72
- }
73
- ?>
74
- <p style="text-align: center; padding: 20px 0 10px;"><a id="wp_insert_adwidgets_new" href="#" class="button-secondary">Add New Ad Widget</a></p>
75
- </div>
76
- </div>
77
-
78
- <div class="plugin-card">
79
- <div class="plugin-card-top">
80
- <h4>In-Theme Ads</h4>
81
- <p>Ads embedded directly inside theme files (Advanced Users Only).</p>
82
- </div>
83
- <div class="plugin-card-bottom">
84
- <?php
85
- $inthemeads = get_option('wp_insert_inthemeads');
86
- if(isset($inthemeads) && is_array($inthemeads)) {
87
- foreach($inthemeads as $key => $value) {
88
- echo '<p>';
89
- echo '<a id="wp_insert_inthemeads_'.$key.'" href="javascript:;" onclick="wp_insert_inthemeads_click_handler(\''.$key.'\', \''.$value['title'].'\')">In-Theme Ad : '.$value['title'].'</a>';
90
- echo '<span class="dashicons dashicons-dismiss wp_insert_delete_icon" onclick="wp_insert_inthemeads_remove(\''.$key.'\')"></span>';
91
- echo '</p>';
92
- }
93
- }
94
- ?>
95
- <p style="text-align: center; padding: 20px 0 10px;"><a id="wp_insert_inthemeads_new" href="#" class="button-secondary">Add New In-Theme Ad</a></p>
96
- </div>
97
- </div>
98
-
99
- <div class="plugin-card">
100
- <div class="plugin-card-top">
101
- <h4>Legal Pages</h4>
102
- <p>Legal Page Templates to kick start your Legal Notices.</p>
103
- </div>
104
- <div class="plugin-card-bottom">
105
- <p><a id="wp_insert_legalpages_privacy_policy" href="javascript:;">Privacy Policy</a></p>
106
- <p><a id="wp_insert_legalpages_terms_conditions" href="javascript:;">Terms and Conditions</a></p>
107
- <p><a id="wp_insert_legalpages_disclaimer" href="javascript:;">Disclaimer</a></p>
108
- <p><a id="wp_insert_legalpages_copyright" href="javascript:;">Copyright Notice</a></p>
109
- <!--<p><a href="#">EU Cookie Compliance</a></p>-->
110
- </div>
111
- </div>
112
-
113
- <div class="plugin-card">
114
- <div class="plugin-card-top">
115
- <h4>Tracking Codes</h4>
116
- <p>Google Analytics and other embeddable codes directly inserted into the site.</p>
117
- </div>
118
- <div class="plugin-card-bottom">
119
- <p><a id="wp_insert_trackingcodes_google_analytics" href="javascript:;">Google Analytics</a></p>
120
- <p><a id="wp_insert_trackingcodes_header" href="javascript:;">Embed Code in Header</a></p>
121
- <p><a id="wp_insert_trackingcodes_footer" href="javascript:;">Embed Code in Footer</a></p>
122
- </div>
123
- </div>
124
-
125
- <div class="plugin-card">
126
- <div class="plugin-card-top">
127
- <h4>Multiple Ad Networks / A-B Testing</h4>
128
- <p>Multiple Ad Networks can be setup to display ads from different networks without infringing the terms of any network.
129
- At a time only ads from one network (Randomly Choosen) will be shown.
130
- This feature can also be used to randomly display different sized Ads from the same network.
131
- Please note that this option is global and applied to In-Post Ads, Ad Widgets and In-Theme Ads.</p>
132
- </div>
133
- <div class="plugin-card-bottom">
134
- <p><a id="wp_insert_abtesting_configuration" href="javascript:;">Configuration</a></p>
135
- </div>
136
- </div>
137
-
138
  <input type="hidden" id="wp_insert_admin_ajax" name="wp_insert_admin_ajax" value="<?php echo admin_url('admin-ajax.php'); ?>" />
139
  <input type="hidden" id="wp_insert_nonce" name="wp_insert_nonce" value="<?php echo wp_create_nonce('wp-insert'); ?>" />
140
  </div>
@@ -142,16 +36,36 @@ function wp_insert_admin_page() { ?>
142
  <?php
143
  }
144
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  /* Begin Admin Notice */
146
  add_action('admin_notices', 'wp_insert_admin_notices');
147
  function wp_insert_admin_notices() {
148
  if(current_user_can('manage_options')) {
149
  $userId = get_current_user_id();
150
- if(!get_user_meta($userId, 'wp_insert_admin_notice_dismissed', true)) {
151
- echo '<div class="notice wp_insert_notice is-dismissible" style="padding: 15px;">';
152
- echo '<img style="float: left; margin-right: 20px;" src="'.WP_INSERT_URL.'includes/assets/images/wpinsert-vi.png" />';
153
- echo '<p style="float: left; font-size: 14px; margin: 7px 0px;">Coming soon: The next update to <b>WP-INSERT</b> plugin will feature native video ad units for upto 10x higher revenue (RPM) powered by video intelligence.<br /><a href="https://www.vi.ai/publisher-video-monetization/" target="_blank">https://www.vi.ai/publisher-video-monetization/</a></p>';
154
- echo '<a style="float: right; vertical-align: middle; height: 36px; font-size: 16px; padding: 0px 25px; line-height: 32px; margin: 12px 40px 0px 20px;" href="https://www.vi.ai/publisher-video-monetization/" class="button button-primary" target="_blank">Learn More</a>';
 
 
155
  echo '<div class="clear"></div>';
156
  echo '<input type="hidden" id="wp_insert_admin_notice_nonce" name="wp_insert_admin_notice_nonce" value="'.wp_create_nonce('wp-insert-admin-notice').'" />';
157
  echo '<input type="hidden" id="wp_insert_admin_notice_ajax" name="wp_insert_admin_notice_ajax" value="'.admin_url('admin-ajax.php').'" />';
@@ -164,7 +78,7 @@ add_action('wp_ajax_wp_insert_admin_notice_dismiss', 'wp_insert_admin_notice_dis
164
  function wp_insert_admin_notice_dismiss() {
165
  check_ajax_referer('wp-insert-admin-notice', 'wp_insert_admin_notice_nonce');
166
  $userId = get_current_user_id();
167
- update_user_meta($userId, 'wp_insert_admin_notice_dismissed', 'true');
168
  die();
169
  }
170
  /* End Admin Notice */
9
  wp_register_script('wp-insert-global-js', WP_INSERT_URL.'includes/assets/js/wp-insert-global.js', array('jquery'), WP_INSERT_VERSION);
10
  wp_enqueue_script('wp-insert-global-js');
11
  if($page == 'toplevel_page_wp-insert') {
12
+ wp_register_style('wp-insert-css', WP_INSERT_URL.'includes/assets/css/wp-insert.css', array(), WP_INSERT_VERSION.rand(0,9999));
13
  wp_enqueue_style('wp-insert-css');
14
  wp_register_style('wp-insert-jquery-ui', 'https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css', array(), WP_INSERT_VERSION);
15
  wp_enqueue_style('wp-insert-jquery-ui');
16
+ wp_register_script('wp-insert-js', WP_INSERT_URL.'includes/assets/js/wp-insert.js', array('jquery', 'jquery-ui-core', 'jquery-ui-accordion', 'jquery-ui-dialog'), WP_INSERT_VERSION.rand(0,9999));
17
  wp_enqueue_script('wp-insert-js');
18
+ wp_register_script('chart-js', WP_INSERT_URL.'includes/assets/js/Chart.bundle.min.js', array('jquery'), WP_INSERT_VERSION);
19
+ wp_enqueue_script('chart-js');
20
  smartlogixControls::enqueue_assets(WP_INSERT_URL.'includes/controls', WP_INSERT_VERSION);
21
  wp_enqueue_script('editor');
22
  wp_enqueue_script('quicktags');
26
 
27
  function wp_insert_admin_page() { ?>
28
  <div class="wrap wp-insert">
29
+ <h2 id="wp_insert_title" style="display: none;"></h2>
30
  <div class="wp-list-table widefat plugin-install">
31
+ <?php do_action('wp_insert_plugin_card'); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  <input type="hidden" id="wp_insert_admin_ajax" name="wp_insert_admin_ajax" value="<?php echo admin_url('admin-ajax.php'); ?>" />
33
  <input type="hidden" id="wp_insert_nonce" name="wp_insert_nonce" value="<?php echo wp_create_nonce('wp-insert'); ?>" />
34
  </div>
36
  <?php
37
  }
38
 
39
+ /* Begin Add Card in Admin Panel */
40
+ add_action('wp_insert_plugin_card', 'wp_insert_title_plugin_card', 0);
41
+ function wp_insert_title_plugin_card() {
42
+ echo '<div class="plugin-card">';
43
+ echo '<div class="plugin-card-top">';
44
+ echo '<a id="wpInsertLogo" href="http://www.wp-insert.smartlogix.co.in"><img src="'.WP_INSERT_URL.'/includes/assets/images/header-banner.png?'.WP_INSERT_VERSION.'" /></a>';
45
+ echo '</div>';
46
+ echo '<div class="plugin-card-bottom">';
47
+ echo '<div id="wpInsertMeta">';
48
+ echo '<p><b>Donate :</b><br /><a target="_blank" href="http://wpinsert.smartlogix.co.in/support/">Click Here</a> to Donate and Promote further development of this plugin.</p>';
49
+ echo '<p><b>Like Us :</b><br /><a target="_blank" href="https://www.facebook.com/SmartLogix/">Click here</a> to like and support us on Facebook</p>';
50
+ echo '<p><b>Rate and Review :</b><br />If you find this plugin useful do leave a honest <a target="_blank" href="http://wordpress.org/plugins/wp-insert">RATING</a> and <a target="_blank" href="https://wordpress.org/support/view/plugin-reviews/wp-insert#postform">REVIEW</a><br /><span style="font-size: 15px; font-weight: 600;">You spending a few minutes to let us know your appreciation for the project will motivate us further in improving the plugin and adding new features.</span></p>';
51
+ echo '</div>';
52
+ echo '</div>';
53
+ echo '</div>';
54
+ }
55
+ /* End Add Card in Admin Panel */
56
+
57
  /* Begin Admin Notice */
58
  add_action('admin_notices', 'wp_insert_admin_notices');
59
  function wp_insert_admin_notices() {
60
  if(current_user_can('manage_options')) {
61
  $userId = get_current_user_id();
62
+ if(!get_user_meta($userId, 'wp_insert_'.WP_INSERT_VERSION.'_admin_notice_dismissed', true)) {
63
+ echo '<div class="notice notice-success wp_insert_notice is-dismissible" style="padding: 15px;">';
64
+ echo '<div style="float: left; max-width: 875px; font-size: 14px; font-family: Arial; line-height: 18px; color: #232323;">';
65
+ echo '<p>Thank you for updating <b>Wp-Insert</b>.</p>';
66
+ echo '<p>This update features <b>vi stories</b> from video intelligence. A video player that will supply both video content and video advertising. Install it now to increase time-on-page, and your revenue thanks to high CPMs. Read the <a target="_blank" href="https://www.vi.ai/frequently-asked-questions-vi-stories-for-wordpress/?utm_source=WordPress&utm_medium=Plugin%20FAQ&utm_campaign=WP%20Insert">FAQ</a>.</p>';
67
+ echo '</div>';
68
+ echo '<img style="float: right; margin-right: 20px; margin-top: 13px;" src="'.WP_INSERT_URL.'includes/assets/images/vi-big-logo.png?'.WP_INSERT_VERSION.'" />';
69
  echo '<div class="clear"></div>';
70
  echo '<input type="hidden" id="wp_insert_admin_notice_nonce" name="wp_insert_admin_notice_nonce" value="'.wp_create_nonce('wp-insert-admin-notice').'" />';
71
  echo '<input type="hidden" id="wp_insert_admin_notice_ajax" name="wp_insert_admin_notice_ajax" value="'.admin_url('admin-ajax.php').'" />';
78
  function wp_insert_admin_notice_dismiss() {
79
  check_ajax_referer('wp-insert-admin-notice', 'wp_insert_admin_notice_nonce');
80
  $userId = get_current_user_id();
81
+ update_user_meta($userId, 'wp_insert_'.WP_INSERT_VERSION.'_admin_notice_dismissed', 'true');
82
  die();
83
  }
84
  /* End Admin Notice */
includes/common/geotargeting.php CHANGED
@@ -1,5 +1,6 @@
1
  <?php
2
  $wpInsertGeoLocation = false;
 
3
  /* Begin Generate Country List */
4
  function wp_insert_get_countries() {
5
  $data = array(
@@ -262,7 +263,8 @@ function wp_insert_get_countries() {
262
  function wp_insert_get_geotargeted_adcode($adOptions) {
263
  global $wpInsertGeoLocation;
264
  global $wpInsertABTestingMode;
265
- if(($wpInsertGeoLocation != false) && ($wpInsertGeoLocation != '') && (is_array($adOptions['geo_group1_countries']) || is_array($adOptions['geo_group2_countries']))) {
 
266
  if(($adOptions['geo_group1_adcode'] != '') && in_array($wpInsertGeoLocation, $adOptions['geo_group1_countries'])) {
267
  return do_shortcode(stripslashes($adOptions['geo_group1_adcode']));
268
  }
@@ -271,8 +273,17 @@ function wp_insert_get_geotargeted_adcode($adOptions) {
271
  }
272
  }
273
  switch($wpInsertABTestingMode) {
274
- case 1:
275
- return do_shortcode(stripslashes($adOptions['primary_ad_code']));
 
 
 
 
 
 
 
 
 
276
  case 2:
277
  return do_shortcode(stripslashes($adOptions['secondary_ad_code']));
278
  case 3:
@@ -282,7 +293,7 @@ function wp_insert_get_geotargeted_adcode($adOptions) {
282
  }
283
  }
284
 
285
- //add_action('init', 'wp_insert_ip_to_country');
286
  function wp_insert_ip_to_country() {
287
  global $wpInsertGeoLocation;
288
  $userIp = $_SERVER["REMOTE_ADDR"];
@@ -291,15 +302,62 @@ function wp_insert_ip_to_country() {
291
  } else {
292
  $countryCode = get_transient('wp_insert_ip_'.$userIp);
293
  if($countryCode === false) {
294
- $response = wp_remote_get('http://api.hostip.info/country.php?ip='.$userIp, array('timeout' => 5));
295
- if(!is_wp_error($response) && isset($response['response']['code']) && ($response['response']['code'] == 200) && isset($response['body']) && ($response['body'] != '') && ($response['body'] != 'XX')) {
296
- $wpInsertGeoLocation = $response['body'];
297
- set_transient('wp_insert_ip_'.$userIp, $wpInsertGeoLocation, WEEK_IN_SECONDS);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
  }
299
  } else {
300
  $wpInsertGeoLocation = $countryCode;
301
  }
302
  }
303
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
  /* End Get Geo Targeted Ad Code */
305
  ?>
1
  <?php
2
  $wpInsertGeoLocation = false;
3
+ $wpInsertVIAdDisplayed = false;
4
  /* Begin Generate Country List */
5
  function wp_insert_get_countries() {
6
  $data = array(
263
  function wp_insert_get_geotargeted_adcode($adOptions) {
264
  global $wpInsertGeoLocation;
265
  global $wpInsertABTestingMode;
266
+ global $wpInsertVIAdDisplayed;
267
+ if(($wpInsertGeoLocation != false) && ($wpInsertGeoLocation != '') && ((is_array($adOptions['geo_group1_countries']) && (count($adOptions['geo_group1_countries']) > 0)) || (is_array($adOptions['geo_group2_countries']) && (count($adOptions['geo_group1_countries']) > 0)))) {
268
  if(($adOptions['geo_group1_adcode'] != '') && in_array($wpInsertGeoLocation, $adOptions['geo_group1_countries'])) {
269
  return do_shortcode(stripslashes($adOptions['geo_group1_adcode']));
270
  }
273
  }
274
  }
275
  switch($wpInsertABTestingMode) {
276
+ case 1:
277
+ if(isset($adOptions['primary_ad_code_type']) && ($adOptions['primary_ad_code_type'] == 'vicode')) {
278
+ if($wpInsertVIAdDisplayed !== true) {
279
+ $wpInsertVIAdDisplayed = true;
280
+ return '<div id="wp_insert_vi_ad">'.wp_insert_vi_api_get_vi_code('wp_insert_vi_code_settings').'</div>';
281
+ } else {
282
+ return '';
283
+ }
284
+ } else {
285
+ return do_shortcode(stripslashes($adOptions['primary_ad_code']));
286
+ }
287
  case 2:
288
  return do_shortcode(stripslashes($adOptions['secondary_ad_code']));
289
  case 3:
293
  }
294
  }
295
 
296
+ add_action('init', 'wp_insert_ip_to_country');
297
  function wp_insert_ip_to_country() {
298
  global $wpInsertGeoLocation;
299
  $userIp = $_SERVER["REMOTE_ADDR"];
302
  } else {
303
  $countryCode = get_transient('wp_insert_ip_'.$userIp);
304
  if($countryCode === false) {
305
+ if(wp_insert_is_geoip_enabled()) {
306
+ try {
307
+ $response = wp_remote_get('http://freegeoip.net/json/'.$userIp, array('timeout' => 10));
308
+ if(!is_wp_error($response)) {
309
+ if(200 == wp_remote_retrieve_response_code($response)) {
310
+ $responseBody = json_decode($response['body']);
311
+ if((json_last_error() == JSON_ERROR_NONE) && isset($responseBody->country_code)) {
312
+ $wpInsertGeoLocation = $responseBody->country_code;
313
+ set_transient('wp_insert_ip_'.$userIp, $wpInsertGeoLocation, WEEK_IN_SECONDS);
314
+ }
315
+ } else { //Geoip service seems to have hit your hourly query limit, clear the request and cache for an hour it so that we dont slow down the website or overburden the service.
316
+ $wpInsertGeoLocation = '';
317
+ set_transient('wp_insert_ip_'.$userIp, $wpInsertGeoLocation, HOUR_IN_SECONDS);
318
+ }
319
+ } else { //Geoip service seems to be down, clear the request and cache it for a day so that we dont slow down the website or overburden the service.
320
+ $wpInsertGeoLocation = '';
321
+ set_transient('wp_insert_ip_'.$userIp, $wpInsertGeoLocation, DAY_IN_SECONDS);
322
+ }
323
+ } catch(Exception $ex) {
324
+ return '';
325
+ }
326
  }
327
  } else {
328
  $wpInsertGeoLocation = $countryCode;
329
  }
330
  }
331
  }
332
+
333
+ function wp_insert_is_geoip_enabled() {
334
+ $inpostads = get_option('wp_insert_inpostads');
335
+ if(isset($inpostads) && is_array($inpostads)) {
336
+ foreach($inpostads as $inpostad) {
337
+ if(isset($inpostad['geo_group1_countries']) && isset($inpostad['geo_group2_countries']) && ((is_array($inpostad['geo_group1_countries']) && (count($inpostad['geo_group1_countries']) > 0)) || (is_array($inpostad['geo_group2_countries']) && (count($inpostad['geo_group2_countries']) > 0)))) {
338
+ return true;
339
+ }
340
+ }
341
+ }
342
+
343
+ $adwidgets = get_option('wp_insert_adwidgets');
344
+ if(isset($adwidgets) && is_array($adwidgets)) {
345
+ foreach($adwidgets as $adwidget) {
346
+ if(isset($adwidget['geo_group1_countries']) && isset($adwidget['geo_group2_countries']) && ((is_array($adwidget['geo_group1_countries']) && (count($adwidget['geo_group1_countries']) > 0)) || (is_array($adwidget['geo_group2_countries']) && (count($adwidget['geo_group2_countries']) > 0)))) {
347
+ return true;
348
+ }
349
+ }
350
+ }
351
+
352
+ $inthemeads = get_option('wp_insert_inthemeads');
353
+ if(isset($inthemeads) && is_array($inthemeads)) {
354
+ foreach($inthemeads as $inthemead) {
355
+ if(isset($inthemead['geo_group1_countries']) && isset($inthemead['geo_group2_countries']) && ((is_array($inthemead['geo_group1_countries']) && (count($inthemead['geo_group1_countries']) > 0)) || (is_array($inthemead['geo_group2_countries']) && (count($inthemead['geo_group2_countries']) > 0)))) {
356
+ return true;
357
+ }
358
+ }
359
+ }
360
+ return false;
361
+ }
362
  /* End Get Geo Targeted Ad Code */
363
  ?>
includes/controls/assets/css/controls.css CHANGED
@@ -1,7 +1,7 @@
1
  .smartlogixControlsSectionWrapper {
2
  margin: 15px 0;
3
  padding: 5px;
4
- border: 1px solid #DDDDDD;
5
  border-radius: 5px;
6
  position: relative;
7
  }
@@ -10,18 +10,30 @@
10
  font-weight: bold;
11
  position: absolute;
12
  left: 15px;
 
13
  top: -10px;
14
  background: #FFFFFF;
 
15
  padding: 0px 10px;
16
  }
17
 
18
  .smartlogixControlsSectionWrapper .smartlogixControlsSectionInner {
19
- background: #EFEFEF;
20
- margin: 10px 0;
21
- padding: 10px;
22
  position: relative;
23
  }
24
 
 
 
 
 
 
 
 
 
 
 
 
25
  .ipcheckbox{
26
  background: #C8161B;
27
  border: none;
@@ -92,7 +104,7 @@
92
  border: 1px solid #aaa;
93
  border-top: 0;
94
  background: #fff;
95
- box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15);
96
  }
97
 
98
  .chosen-container.chosen-with-drop .chosen-drop {
@@ -538,7 +550,7 @@
538
  }
539
 
540
  .jqte {
541
- margin:30px 0;
542
  border:#bbb 1px solid;
543
  overflow:hidden;
544
  }
@@ -1076,4 +1088,324 @@ only screen and (min-resolution: 1.5dppx) {
1076
 
1077
  }
1078
 
1079
- /* @end */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  .smartlogixControlsSectionWrapper {
2
  margin: 15px 0;
3
  padding: 5px;
4
+ border: 1px solid #999999;
5
  border-radius: 5px;
6
  position: relative;
7
  }
10
  font-weight: bold;
11
  position: absolute;
12
  left: 15px;
13
+ right: 15px;
14
  top: -10px;
15
  background: #FFFFFF;
16
+ color: #111111;
17
  padding: 0px 10px;
18
  }
19
 
20
  .smartlogixControlsSectionWrapper .smartlogixControlsSectionInner {
21
+ margin: 10px 0 10px;
22
+ padding: 0 10px;
 
23
  position: relative;
24
  }
25
 
26
+ @media screen and (min-width: 768px) and (max-width: 1200px) {
27
+ .smartlogixControlsSectionWrapper .smartlogixControlsSectionInner {
28
+ margin-top: 30px;
29
+ }
30
+ }
31
+
32
+ .smartlogixControlsSectionWrapper .smartlogixControlsSectionInner p {
33
+ margin: 0 0 10px;
34
+ }
35
+
36
+
37
  .ipcheckbox{
38
  background: #C8161B;
39
  border: none;
104
  border: 1px solid #aaa;
105
  border-top: 0;
106
  background: #fff;
107
+ /*box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15);*/
108
  }
109
 
110
  .chosen-container.chosen-with-drop .chosen-drop {
550
  }
551
 
552
  .jqte {
553
+ margin: 0;
554
  border:#bbb 1px solid;
555
  overflow:hidden;
556
  }
1088
 
1089
  }
1090
 
1091
+ /* @end */
1092
+
1093
+ .minicolors {
1094
+ position: relative;
1095
+ }
1096
+
1097
+ .minicolors-sprite {
1098
+ background-image: url(../images/jquery.minicolors.png);
1099
+ }
1100
+
1101
+ .minicolors-swatch {
1102
+ position: absolute;
1103
+ vertical-align: middle;
1104
+ background-position: -80px 0;
1105
+ border: solid 1px #ccc;
1106
+ cursor: text;
1107
+ padding: 0;
1108
+ margin: 0;
1109
+ display: inline-block;
1110
+ }
1111
+
1112
+ .minicolors-swatch-color {
1113
+ position: absolute;
1114
+ top: 0;
1115
+ left: 0;
1116
+ right: 0;
1117
+ bottom: 0;
1118
+ }
1119
+
1120
+ .minicolors input[type=hidden] + .minicolors-swatch {
1121
+ width: 28px;
1122
+ position: static;
1123
+ cursor: pointer;
1124
+ }
1125
+
1126
+ .minicolors input[type=hidden][disabled] + .minicolors-swatch {
1127
+ cursor: default;
1128
+ }
1129
+
1130
+ /* Panel */
1131
+ .minicolors-panel {
1132
+ position: absolute;
1133
+ width: 173px;
1134
+ background: white;
1135
+ border: solid 1px #CCC;
1136
+ box-shadow: 0 0 20px rgba(0, 0, 0, .2);
1137
+ z-index: 99999;
1138
+ box-sizing: content-box;
1139
+ display: none;
1140
+ }
1141
+
1142
+ .minicolors-panel.minicolors-visible {
1143
+ display: block;
1144
+ }
1145
+
1146
+ /* Panel positioning */
1147
+ .minicolors-position-top .minicolors-panel {
1148
+ top: -154px;
1149
+ }
1150
+
1151
+ .minicolors-position-right .minicolors-panel {
1152
+ right: 0;
1153
+ }
1154
+
1155
+ .minicolors-position-bottom .minicolors-panel {
1156
+ top: 30px;
1157
+ }
1158
+
1159
+ .minicolors-position-left .minicolors-panel {
1160
+ left: 0;
1161
+ }
1162
+
1163
+ .minicolors-with-opacity .minicolors-panel {
1164
+ width: 194px;
1165
+ }
1166
+
1167
+ .minicolors .minicolors-grid {
1168
+ position: relative;
1169
+ top: 1px;
1170
+ left: 1px;
1171
+ width: 150px;
1172
+ height: 150px;
1173
+ background-position: -120px 0;
1174
+ cursor: crosshair;
1175
+ }
1176
+
1177
+ .minicolors .minicolors-grid-inner {
1178
+ position: absolute;
1179
+ top: 0;
1180
+ left: 0;
1181
+ width: 150px;
1182
+ height: 150px;
1183
+ }
1184
+
1185
+ .minicolors-slider-saturation .minicolors-grid {
1186
+ background-position: -420px 0;
1187
+ }
1188
+
1189
+ .minicolors-slider-saturation .minicolors-grid-inner {
1190
+ background-position: -270px 0;
1191
+ background-image: inherit;
1192
+ }
1193
+
1194
+ .minicolors-slider-brightness .minicolors-grid {
1195
+ background-position: -570px 0;
1196
+ }
1197
+
1198
+ .minicolors-slider-brightness .minicolors-grid-inner {
1199
+ background-color: black;
1200
+ }
1201
+
1202
+ .minicolors-slider-wheel .minicolors-grid {
1203
+ background-position: -720px 0;
1204
+ }
1205
+
1206
+ .minicolors-slider,
1207
+ .minicolors-opacity-slider {
1208
+ position: absolute;
1209
+ top: 1px;
1210
+ left: 152px;
1211
+ width: 20px;
1212
+ height: 150px;
1213
+ background-color: white;
1214
+ background-position: 0 0;
1215
+ cursor: row-resize;
1216
+ }
1217
+
1218
+ .minicolors-slider-saturation .minicolors-slider {
1219
+ background-position: -60px 0;
1220
+ }
1221
+
1222
+ .minicolors-slider-brightness .minicolors-slider {
1223
+ background-position: -20px 0;
1224
+ }
1225
+
1226
+ .minicolors-slider-wheel .minicolors-slider {
1227
+ background-position: -20px 0;
1228
+ }
1229
+
1230
+ .minicolors-opacity-slider {
1231
+ left: 173px;
1232
+ background-position: -40px 0;
1233
+ display: none;
1234
+ }
1235
+
1236
+ .minicolors-with-opacity .minicolors-opacity-slider {
1237
+ display: block;
1238
+ }
1239
+
1240
+ /* Pickers */
1241
+ .minicolors-grid .minicolors-picker {
1242
+ position: absolute;
1243
+ top: 70px;
1244
+ left: 70px;
1245
+ width: 12px;
1246
+ height: 12px;
1247
+ border: solid 1px black;
1248
+ border-radius: 10px;
1249
+ margin-top: -6px;
1250
+ margin-left: -6px;
1251
+ background: none;
1252
+ }
1253
+
1254
+ .minicolors-grid .minicolors-picker > div {
1255
+ position: absolute;
1256
+ top: 0;
1257
+ left: 0;
1258
+ width: 8px;
1259
+ height: 8px;
1260
+ border-radius: 8px;
1261
+ border: solid 2px white;
1262
+ box-sizing: content-box;
1263
+ }
1264
+
1265
+ .minicolors-picker {
1266
+ position: absolute;
1267
+ top: 0;
1268
+ left: 0;
1269
+ width: 18px;
1270
+ height: 2px;
1271
+ background: white;
1272
+ border: solid 1px black;
1273
+ margin-top: -2px;
1274
+ box-sizing: content-box;
1275
+ }
1276
+
1277
+ /* Swatches */
1278
+ .minicolors-swatches,
1279
+ .minicolors-swatches li {
1280
+ margin: 5px 0 3px 5px;
1281
+ padding: 0;
1282
+ list-style: none;
1283
+ overflow: hidden;
1284
+ }
1285
+
1286
+ .minicolors-swatches .minicolors-swatch {
1287
+ position: relative;
1288
+ float: left;
1289
+ cursor: pointer;
1290
+ margin:0 4px 0 0;
1291
+ }
1292
+
1293
+ .minicolors-with-opacity .minicolors-swatches .minicolors-swatch {
1294
+ margin-right: 7px;
1295
+ }
1296
+
1297
+ .minicolors-swatch.selected {
1298
+ border-color: #000;
1299
+ }
1300
+
1301
+ /* Inline controls */
1302
+ .minicolors-inline {
1303
+ display: inline-block;
1304
+ }
1305
+
1306
+ .minicolors-inline .minicolors-input {
1307
+ display: none !important;
1308
+ }
1309
+
1310
+ .minicolors-inline .minicolors-panel {
1311
+ position: relative;
1312
+ top: auto;
1313
+ left: auto;
1314
+ box-shadow: none;
1315
+ z-index: auto;
1316
+ display: inline-block;
1317
+ }
1318
+
1319
+ /* Default theme */
1320
+ .minicolors-theme-default .minicolors-swatch {
1321
+ top: 5px;
1322
+ left: 5px;
1323
+ width: 18px;
1324
+ height: 18px;
1325
+ }
1326
+ .minicolors-theme-default .minicolors-swatches .minicolors-swatch {
1327
+ margin-bottom: 2px;
1328
+ top: 0;
1329
+ left: 0;
1330
+ width: 18px;
1331
+ height: 18px;
1332
+ }
1333
+ .minicolors-theme-default.minicolors-position-right .minicolors-swatch {
1334
+ left: auto;
1335
+ right: 5px;
1336
+ }
1337
+ .minicolors-theme-default.minicolors {
1338
+ width: auto;
1339
+ display: inline-block;
1340
+ }
1341
+ .minicolors-theme-default .minicolors-input {
1342
+ height: 20px;
1343
+ width: auto;
1344
+ display: inline-block;
1345
+ padding-left: 26px;
1346
+ }
1347
+ .minicolors-theme-default.minicolors-position-right .minicolors-input {
1348
+ padding-right: 26px;
1349
+ padding-left: inherit;
1350
+ }
1351
+
1352
+ /* Bootstrap theme */
1353
+ .minicolors-theme-bootstrap .minicolors-swatch {
1354
+ z-index: 2;
1355
+ top: 3px;
1356
+ left: 3px;
1357
+ width: 28px;
1358
+ height: 28px;
1359
+ border-radius: 3px;
1360
+ }
1361
+ .minicolors-theme-bootstrap .minicolors-swatches .minicolors-swatch {
1362
+ margin-bottom: 2px;
1363
+ top: 0;
1364
+ left: 0;
1365
+ width: 20px;
1366
+ height: 20px;
1367
+ }
1368
+ .minicolors-theme-bootstrap .minicolors-swatch-color {
1369
+ border-radius: inherit;
1370
+ }
1371
+ .minicolors-theme-bootstrap.minicolors-position-right > .minicolors-swatch {
1372
+ left: auto;
1373
+ right: 3px;
1374
+ }
1375
+ .minicolors-theme-bootstrap .minicolors-input {
1376
+ float: none;
1377
+ padding-left: 44px;
1378
+ }
1379
+ .minicolors-theme-bootstrap.minicolors-position-right .minicolors-input {
1380
+ padding-right: 44px;
1381
+ padding-left: 12px;
1382
+ }
1383
+ .minicolors-theme-bootstrap .minicolors-input.input-lg + .minicolors-swatch {
1384
+ top: 4px;
1385
+ left: 4px;
1386
+ width: 37px;
1387
+ height: 37px;
1388
+ border-radius: 5px;
1389
+ }
1390
+ .minicolors-theme-bootstrap .minicolors-input.input-sm + .minicolors-swatch {
1391
+ width: 24px;
1392
+ height: 24px;
1393
+ }
1394
+ .minicolors-theme-bootstrap .minicolors-input.input-xs + .minicolors-swatch {
1395
+ width: 18px;
1396
+ height: 18px;
1397
+ }
1398
+ .input-group .minicolors-theme-bootstrap:not(:first-child) .minicolors-input {
1399
+ border-top-left-radius: 0;
1400
+ border-bottom-left-radius: 0;
1401
+ }
1402
+
1403
+ /* Semantic Ui theme */
1404
+ .minicolors-theme-semanticui .minicolors-swatch {
1405
+ top: 0;
1406
+ left: 0;
1407
+ padding: 18px;
1408
+ }
1409
+ .minicolors-theme-semanticui input {
1410
+ text-indent: 30px;
1411
+ }
includes/controls/assets/images/jquery.minicolors.png ADDED
Binary file
includes/controls/assets/js/controls.js CHANGED
@@ -36,4 +36,15 @@
36
  *
37
  */
38
  (function(e){e.fn.jqte=function(t){function l(e,t,n,r,i){var s=f.length+1;return f.push({name:e,cls:s,command:t,key:n,tag:r,emphasis:i})}var n=[{title:"Text Format"},{title:"Font Size"},{title:"Color"},{title:"Bold",hotkey:"B"},{title:"Italic",hotkey:"I"},{title:"Underline",hotkey:"U"},{title:"Ordered List",hotkey:"."},{title:"Unordered List",hotkey:","},{title:"Subscript",hotkey:"down arrow"},{title:"Superscript",hotkey:"up arrow"},{title:"Outdent",hotkey:"left arrow"},{title:"Indent",hotkey:"right arrow"},{title:"Justify Left"},{title:"Justify Center"},{title:"Justify Right"},{title:"Strike Through",hotkey:"K"},{title:"Add Link",hotkey:"L"},{title:"Remove Link"},{title:"Cleaner Style",hotkey:"Delete"},{title:"Horizontal Rule",hotkey:"H"},{title:"Source"}];var r=[["p","Normal"],["h1","Header 1"],["h2","Header 2"],["h3","Header 3"],["h4","Header 4"],["h5","Header 5"],["h6","Header 6"],["pre","Preformatted"]];var i=["10","12","16","18","20","24","28"];var s=["0,0,0","68,68,68","102,102,102","153,153,153","204,204,204","238,238,238","243,243,243","255,255,255",null,"255,0,0","255,153,0","255,255,0","0,255,0","0,255,255","0,0,255","153,0,255","255,0,255",null,"244,204,204","252,229,205","255,242,204","217,234,211","208,224,227","207,226,243","217,210,233","234,209,220","234,153,153","249,203,156","255,229,153","182,215,168","162,196,201","159,197,232","180,167,214","213,166,189","224,102,102","246,178,107","255,217,102","147,196,125","118,165,175","111,168,220","142,124,195","194,123,160","204,0,0","230,145,56","241,194,50","106,168,79","69,129,142","61,133,198","103,78,167","166,77,121","153,0,0","180,95,6","191,144,0","56,118,29","19,79,92","11,83,148","53,28,117","116,27,71","102,0,0","120,63,4","127,96,0","39,78,19","12,52,61","7,55,99","32,18,77","76,17,48"];var o=["Web Address","E-mail Address","Picture URL"];var u=e.extend({status:true,css:"jqte",title:true,titletext:n,button:"OK",format:true,formats:r,fsize:true,fsizes:i,funit:"px",color:true,linktypes:o,b:true,i:true,u:true,ol:true,ul:true,sub:true,sup:true,outdent:true,indent:true,left:true,center:true,right:true,strike:true,link:true,unlink:true,remove:true,rule:true,source:true,placeholder:false,br:true,p:true,change:"",focus:"",blur:""},t);e.fn.jqteVal=function(t){e(this).closest("."+u.css).find("."+u.css+"_editor").html(t)};var a=navigator.userAgent.toLowerCase();if(/msie [1-7]./.test(a))u.title=false;var f=[];l("format","formats","","",false);l("fsize","fSize","","",false);l("color","colors","","",false);l("b","Bold","B",["b","strong"],true);l("i","Italic","I",["i","em"],true);l("u","Underline","U",["u"],true);l("ol","insertorderedlist","¾",["ol"],true);l("ul","insertunorderedlist","¼",["ul"],true);l("sub","subscript","(",["sub"],true);l("sup","superscript","&",["sup"],true);l("outdent","outdent","%",["blockquote"],false);l("indent","indent","'",["blockquote"],true);l("left","justifyLeft","","",false);l("center","justifyCenter","","",false);l("right","justifyRight","","",false);l("strike","strikeThrough","K",["strike"],true);l("link","linkcreator","L",["a"],true);l("unlink","unlink","",["a"],false);l("remove","removeformat",".","",false);l("rule","inserthorizontalrule","H",["hr"],false);l("source","displaysource","","",false);return this.each(function(){function B(){if(window.getSelection)return window.getSelection();else if(document.selection&&document.selection.createRange&&document.selection.type!="None")return document.selection.createRange()}function j(e,t){var n,r=B();if(window.getSelection){if(r.anchorNode&&r.getRangeAt)n=r.getRangeAt(0);if(n){r.removeAllRanges();r.addRange(n)}if(!a.match(/msie/))document.execCommand("StyleWithCSS",false,false);document.execCommand(e,false,t)}else if(document.selection&&document.selection.createRange&&document.selection.type!="None"){n=document.selection.createRange();n.execCommand(e,false,t)}q(false,false)}function F(t,n,r){if(v.not(":focus"))v.focus();if(window.getSelection){var i=B(),s,o,u;if(i.anchorNode&&i.getRangeAt){s=i.getRangeAt(0);o=document.createElement(t);e(o).attr(n,r);u=s.extractContents();o.appendChild(u);s.insertNode(o);i.removeAllRanges();if(n=="style")q(e(o),r);else q(e(o),false)}}else if(document.selection&&document.selection.createRange&&document.selection.type!="None"){var a=document.selection.createRange();var f=a.htmlText;var l="<"+t+" "+n+'="'+r+'">'+f+"</"+t+">";document.selection.createRange().pasteHTML(l)}}function q(e,t){var n=I();n=n?n:e;if(n&&t==false){if(n.parent().is("[style]"))n.attr("style",n.parent().attr("style"));if(n.is("[style]"))n.find("*").attr("style",n.attr("style"))}else if(e&&t&&e.is("[style]")){var r=t.split(";");r=r[0].split(":");if(e.is("[style*="+r[0]+"]"))e.find("*").css(r[0],r[1]);R(e)}}function R(t){if(t){var t=t[0];if(document.body.createTextRange){var n=document.body.createTextRange();n.moveToElementText(t);n.select()}else if(window.getSelection){var r=window.getSelection();var n=document.createRange();if(t!="undefined"&&t!=null){n.selectNodeContents(t);r.removeAllRanges();r.addRange(n);if(e(t).is(":empty")){e(t).append(" ");R(e(t))}}}}}function U(){if(!p.data("sourceOpened")){var t=I();var n="http://";W(true);if(t){var r=t.prop("tagName").toLowerCase();if(r=="a"&&t.is("[href]")){n=t.attr("href");t.attr(S,"")}else F("a",S,"")}else y.val(n).focus();g.click(function(t){if(e(t.target).hasClass(u.css+"_linktypetext")||e(t.target).hasClass(u.css+"_linktypearrow"))X(true)});w.find("a").click(function(){var t=e(this).attr(u.css+"-linktype");w.data("linktype",t);E.find("."+u.css+"_linktypetext").html(w.find("a:eq("+w.data("linktype")+")").text());V(n);X()});V(n);y.focus().val(n).bind("keypress keyup",function(e){if(e.keyCode==13){z(h.find("["+S+"]"));return false}});b.click(function(){z(h.find("["+S+"]"))})}else W(false)}function z(t){y.focus();R(t);t.removeAttr(S);if(w.data("linktype")!="2")j("createlink",y.val());else{j("insertImage",y.val());v.find("img").each(function(){var t=e(this).prev("a");var n=e(this).next("a");if(t.length>0&&t.html()=="")t.remove();else if(n.length>0&&n.html()=="")n.remove()})}W();v.trigger("change")}function W(e){Q("["+S+"]:not([href])");h.find("["+S+"][href]").removeAttr(S);if(e){p.data("linkOpened",true);d.show()}else{p.data("linkOpened",false);d.hide()}X()}function X(e){if(e)w.show();else w.hide()}function V(e){var t=w.data("linktype");if(t=="1"&&(y.val()=="http://"||y.is("[value^=http://]")||!y.is("[value^=mailto]")))y.val("mailto:");else if(t!="1"&&!y.is("[value^=http://]"))y.val("http://");else y.val(e)}function J(t){if(!p.data("sourceOpened")){if(t=="fSize")styleField=P;else if(t=="colors")styleField=H;K(styleField,true);styleField.find("a").unbind("click").click(function(){var n=e(this).attr(u.css+"-styleval");if(t=="fSize"){styleType="font-size";n=n+u.funit}else if(t=="colors"){styleType="color";n="rgb("+n+")"}var r=G(styleType);F("span","style",styleType+":"+n+";"+r);K("",false);e("."+u.css+"_title").remove();v.trigger("change")})}else K(styleField,false);W(false)}function K(e,t){var n="",r=[{d:"fsizeOpened",f:P},{d:"cpallOpened",f:H}];if(e!=""){for(var i=0;i<r.length;i++){if(e==r[i]["f"])n=r[i]}}if(t){p.data(n["d"],true);n["f"].slideDown(100);for(var i=0;i<r.length;i++){if(n["d"]!=r[i]["d"]){p.data(r[i]["d"],false);r[i]["f"].slideUp(100)}}}else{for(var i=0;i<r.length;i++){p.data(r[i]["d"],false);r[i]["f"].slideUp(100)}}}function Q(t){h.find(t).each(function(){e(this).before(e(this).html()).remove()})}function G(e){var t=I();if(t&&t.is("[style]")&&t.css(e)!=""){var n=t.css(e);t.css(e,"");var r=t.attr("style");t.css(e,n);return r}else return""}function Y(){Z(true);D.find("a").click(function(){e("*",this).click(function(e){e.preventDefault();return false});et(e(this).text());var t=e(this).attr(u.css+"-formatval");j("formatBlock","<"+t+">");Z(false)})}function Z(e){var t=e?true:false;t=e&&D.data("status")?true:false;if(t||!e)D.data("status",false).slideUp(200);else D.data("status",true).slideDown(200)}function et(e){var t=D.closest("."+u.css+"_tool").find("."+u.css+"_tool_label").find("."+u.css+"_tool_text");if(e.length>10)e=e.substr(0,7)+"...";t.html(e)}function tt(e){var t,n,r;t=e.replace(/\n/gim,"").replace(/\r/gim,"").replace(/\t/gim,"").replace(/ /gim," ");n=[/\<span(|\s+.*?)><span(|\s+.*?)>(.*?)<\/span><\/span>/gim,/<(\w*[^p])\s*[^\/>]*>\s*<\/\1>/gim,/\<div(|\s+.*?)>(.*?)\<\/div>/gim,/\<strong(|\s+.*?)>(.*?)\<\/strong>/gim,/\<em(|\s+.*?)>(.*?)\<\/em>/gim];r=["<span$2>$3</span>","","<p$1>$2</p>","<b$1>$2</b>","<i$1>$2</i>"];for(A=0;A<5;A++){for(var i=0;i<n.length;i++){t=t.replace(n[i],r[i])}}if(!u.p)t=t.replace(/\<p(|\s+.*?)>(.*?)\<\/p>/ig,"<br/>$2");if(!u.br){n=[/\<br>(.*?)/ig,/\<br\/>(.*?)/ig];r=["<p>$1</p>","<p>$1</p>"];for(var i=0;i<n.length;i++){t=t.replace(n[i],r[i])}}if(!u.p&&!u.br)t=t.replace(/\<p>(.*?)\<\/p>/ig,"<div>$1</div>");return t}function nt(){var e=v.text()==""&&v.html().length<12?"":v.html();l.val(tt(e))}function rt(){v.html(tt(l.val()))}function it(t){var n=false,r=I(),i;if(r){e.each(t,function(t,s){i=r.prop("tagName").toLowerCase();if(i==s)n=true;else{r.parents().each(function(){i=e(this).prop("tagName").toLowerCase();if(i==s)n=true})}});return n}else return false}function st(t){for(var n=0;n<f.length;n++){if(u[f[n].name]&&f[n].emphasis&&f[n].tag!="")it(f[n].tag)?p.find("."+u.css+"_tool_"+f[n].cls).addClass(m):e("."+u.css+"_tool_"+f[n].cls).removeClass(m)}if(u.format&&e.isArray(u.formats)){var r=false;for(var i=0;i<u.formats.length;i++){var s=[];s[0]=u.formats[i][0];if(u.formats[i][0].length>0&&it(s)){et(u.formats[i][1]);r=true;break}}if(!r)et(u.formats[0][1])}K("",false);Z(false)}if(!e(this).data("jqte")||e(this).data("jqte")==null||e(this).data("jqte")=="undefined")e(this).data("jqte",true);else e(this).data("jqte",false);if(!u.status||!e(this).data("jqte")){if(e(this).closest("."+u.css).length>0){var t=e(this).closest("."+u.css).find("."+u.css+"_editor").html();var n="";e(e(this)[0].attributes).each(function(){if(this.nodeName!="style")n=n+" "+this.nodeName+'="'+this.nodeValue+'"'});var r=e(this).is("[data-origin]")&&e(this).attr("data-origin")!=""?e(this).attr("data-origin"):"textarea";var i=">"+t;if(r=="input"||r=="option"){t=t.replace(/"/g,"&#34;").replace(/'/g,"&#39;").replace(/</g,"<").replace(/>/g,">");i='value="'+t+'">'}var o=e(this).clone();e(this).data("jqte",false).closest("."+u.css).before(o).remove();o.replaceWith("<"+r+n+i+"</"+r+">")}return}var l=e(this);var r=e(this).prop("tagName").toLowerCase();e(this).attr("data-origin",r);var c=e(this).is("[value]")||r=="textarea"?e(this).val():e(this).html();c=c.replace(/&#34;/g,'"').replace(/&#39;/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&");e(this).after('<div class="'+u.css+'"></div>');var h=e(this).next("."+u.css);h.html('<div class="'+u.css+"_toolbar"+'" role="toolbar" unselectable></div><div class="'+u.css+'_linkform" style="display:none" role="dialog"></div><div class="'+u.css+"_editor"+'"></div>');var p=h.find("."+u.css+"_toolbar");var d=h.find("."+u.css+"_linkform");var v=h.find("."+u.css+"_editor");var m=u.css+"_tool_depressed";d.append('<div class="'+u.css+'_linktypeselect" unselectable></div><input class="'+u.css+'_linkinput" type="text/css" value=""><div class="'+u.css+'_linkbutton" unselectable>'+u.button+'</div> <div style="height:1px;float:none;clear:both"></div>');var g=d.find("."+u.css+"_linktypeselect");var y=d.find("."+u.css+"_linkinput");var b=d.find("."+u.css+"_linkbutton");g.append('<div class="'+u.css+'_linktypeview" unselectable></div><div class="'+u.css+'_linktypes" role="menu" unselectable></div>');var w=g.find("."+u.css+"_linktypes");var E=g.find("."+u.css+"_linktypeview");var S=u.css+"-setlink";v.after('<div class="'+u.css+"_source "+u.css+'_hiddenField"></div>');var x=h.find("."+u.css+"_source");l.appendTo(x);if(r!="textarea"){var n="";e(l[0].attributes).each(function(){if(this.nodeName!="type"&&this.nodeName!="value")n=n+" "+this.nodeName+'="'+this.nodeValue+'"'});l.replaceWith("<textarea "+n+">"+c+"</textarea>");l=x.find("textarea")}v.attr("contenteditable","true").html(c);for(var T=0;T<f.length;T++){if(u[f[T].name]){var N=f[T].key.length>0?u.titletext[T].hotkey!=null&&u.titletext[T].hotkey!="undefined"&&u.titletext[T].hotkey!=""?" (Ctrl+"+u.titletext[T].hotkey+")":"":"";var C=u.titletext[T].title!=null&&u.titletext[T].title!="undefined"&&u.titletext[T].title!=""?u.titletext[T].title+N:"";p.append('<div class="'+u.css+"_tool "+u.css+"_tool_"+f[T].cls+'" role="button" data-tool="'+T+'" unselectable><a class="'+u.css+'_tool_icon" unselectable></a></div>');p.find("."+u.css+"_tool[data-tool="+T+"]").data({tag:f[T].tag,command:f[T].command,emphasis:f[T].emphasis,title:C});if(f[T].name=="format"&&e.isArray(u.formats)){var k=u.formats[0][1].length>0&&u.formats[0][1]!="undefined"?u.formats[0][1]:"";p.find("."+u.css+"_tool_"+f[T].cls).find("."+u.css+"_tool_icon").replaceWith('<a class="'+u.css+'_tool_label" unselectable><span class="'+u.css+'_tool_text" unselectable>'+k+'</span><span class="'+u.css+'_tool_icon" unselectable></span></a>');p.find("."+u.css+"_tool_"+f[T].cls).append('<div class="'+u.css+'_formats" unselectable></div>');for(var L=0;L<u.formats.length;L++){p.find("."+u.css+"_formats").append("<a "+u.css+'-formatval="'+u.formats[L][0]+'" class="'+u.css+"_format"+" "+u.css+"_format_"+L+'" role="menuitem" unselectable>'+u.formats[L][1]+"</a>")}p.find("."+u.css+"_formats").data("status",false)}else if(f[T].name=="fsize"&&e.isArray(u.fsizes)){p.find("."+u.css+"_tool_"+f[T].cls).append('<div class="'+u.css+'_fontsizes" unselectable></div>');for(var L=0;L<u.fsizes.length;L++){p.find("."+u.css+"_fontsizes").append("<a "+u.css+'-styleval="'+u.fsizes[L]+'" class="'+u.css+"_fontsize"+'" style="font-size:'+u.fsizes[L]+u.funit+'" role="menuitem" unselectable>Abcdefgh...</a>')}}else if(f[T].name=="color"&&e.isArray(s)){p.find("."+u.css+"_tool_"+f[T].cls).append('<div class="'+u.css+'_cpalette" unselectable></div>');for(var A=0;A<s.length;A++){if(s[A]!=null)p.find("."+u.css+"_cpalette").append("<a "+u.css+'-styleval="'+s[A]+'" class="'+u.css+"_color"+'" style="background-color: rgb('+s[A]+')" role="gridcell" unselectable></a>');else p.find("."+u.css+"_cpalette").append('<div class="'+u.css+"_colorSeperator"+'"></div>')}}}}w.data("linktype","0");for(var T=0;T<3;T++){w.append("<a "+u.css+'-linktype="'+T+'" unselectable>'+u.linktypes[T]+"</a>");E.html('<div class="'+u.css+'_linktypearrow" unselectable></div><div class="'+u.css+'_linktypetext">'+w.find("a:eq("+w.data("linktype")+")").text()+"</div>")}var O="";if(/msie/.test(a))O="-ms-";else if(/chrome/.test(a)||/safari/.test(a)||/yandex/.test(a))O="-webkit-";else if(/mozilla/.test(a))O="-moz-";else if(/opera/.test(a))O="-o-";else if(/konqueror/.test(a))O="-khtml-";else O="";if(u.placeholder&&u.placeholder!=""){h.prepend('<div class="'+u.css+'_placeholder" unselectable><div class="'+u.css+'_placeholder_text">'+u.placeholder+"</div></div>");var M=h.find("."+u.css+"_placeholder");M.click(function(){v.focus()})}h.find("[unselectable]").css(O+"user-select","none").addClass("unselectable").attr("unselectable","on").on("selectstart mousedown",false);var _=p.find("."+u.css+"_tool");var D=p.find("."+u.css+"_formats");var P=p.find("."+u.css+"_fontsizes");var H=p.find("."+u.css+"_cpalette");var I=function(){var t,n;if(window.getSelection){n=getSelection();t=n.anchorNode}if(!t&&document.selection&&document.selection.createRange&&document.selection.type!="None"){n=document.selection;var r=n.getRangeAt?n.getRangeAt(0):n.createRange();t=r.commonAncestorContainer?r.commonAncestorContainer:r.parentElement?r.parentElement():r.item(0)}if(t){return t.nodeName=="#text"?e(t.parentNode):e(t)}else return false};_.unbind("click").click(function(t){if(e(this).data("command")=="displaysource"&&!p.data("sourceOpened")){p.find("."+u.css+"_tool").addClass(u.css+"_hiddenField");e(this).removeClass(u.css+"_hiddenField");p.data("sourceOpened",true);l.css("height",v.outerHeight());x.removeClass(u.css+"_hiddenField");v.addClass(u.css+"_hiddenField");l.focus();W(false);K("",false);Z();if(u.placeholder&&u.placeholder!="")M.hide()}else{if(!p.data("sourceOpened")){if(e(this).data("command")=="linkcreator"){if(!p.data("linkOpened"))U();else{W(false);Z(false)}}else if(e(this).data("command")=="formats"){if(e(this).data("command")=="formats"&&!e(t.target).hasClass(u.css+"_format"))Y();K("",false);if(v.not(":focus"))v.focus()}else if(e(this).data("command")=="fSize"||e(this).data("command")=="colors"){if(e(this).data("command")=="fSize"&&!e(t.target).hasClass(u.css+"_fontsize")||e(this).data("command")=="colors"&&!e(t.target).hasClass(u.css+"_color"))J(e(this).data("command"));Z(false);if(v.not(":focus"))v.focus()}else{if(v.not(":focus"))v.focus();j(e(this).data("command"),null);K("",false);Z(false);X();e(this).data("emphasis")==true&&!e(this).hasClass(m)?e(this).addClass(m):e(this).removeClass(m);x.addClass(u.css+"_hiddenField");v.removeClass(u.css+"_hiddenField")}}else{p.data("sourceOpened",false);p.find("."+u.css+"_tool").removeClass(u.css+"_hiddenField");x.addClass(u.css+"_hiddenField");v.removeClass(u.css+"_hiddenField")}if(u.placeholder&&u.placeholder!="")v.html()!=""?M.hide():M.show()}v.trigger("change")}).hover(function(t){if(u.title&&e(this).data("title")!=""&&(e(t.target).hasClass(u.css+"_tool")||e(t.target).hasClass(u.css+"_tool_icon"))){e("."+u.css+"_title").remove();h.append('<div class="'+u.css+'_title"><div class="'+u.css+'_titleArrow"><div class="'+u.css+'_titleArrowIcon"></div></div><div class="'+u.css+'_titleText">'+e(this).data("title")+"</div></div>");var n=e("."+u.css+"_title:first");var r=n.find("."+u.css+"_titleArrowIcon");var i=e(this).position();var s=i.left+e(this).outerWidth()-n.outerWidth()/2-e(this).outerWidth()/2;var o=i.top+e(this).outerHeight()+5;n.delay(400).css({top:o,left:s}).fadeIn(200)}},function(){e("."+u.css+"_title").remove()});var ot=null;v.bind("keypress keyup keydown drop cut copy paste DOMCharacterDataModified DOMSubtreeModified",function(){if(!p.data("sourceOpened"))e(this).trigger("change");X();if(e.isFunction(u.change))u.change();if(u.placeholder&&u.placeholder!="")e(this).text()!=""?M.hide():M.show()}).bind("change",function(){if(!p.data("sourceOpened")){clearTimeout(ot);ot=setTimeout(nt,10)}}).keydown(function(e){if(e.ctrlKey){for(var t=0;t<f.length;t++){if(u[f[t].name]&&e.keyCode==f[t].key.charCodeAt(0)){if(f[t].command!=""&&f[t].command!="linkcreator")j(f[t].command,null);else if(f[t].command=="linkcreator")U();return false}}}}).bind("mouseup keyup",st).focus(function(){if(e.isFunction(u.focus))u.focus();h.addClass(u.css+"_focused");if(/opera/.test(a)){var t=document.createRange();t.selectNodeContents(v[0]);t.collapse(false);var n=window.getSelection();n.removeAllRanges();n.addRange(t)}}).focusout(function(){_.removeClass(m);K("",false);Z(false);X();if(e.isFunction(u.blur))u.blur();h.removeClass(u.css+"_focused");if(e.isArray(u.formats))et(u.formats[0][1])});l.bind("keydown keyup",function(){setTimeout(rt,0);e(this).height(e(this)[0].scrollHeight);if(e(this).val()=="")e(this).height(0)}).focus(function(){h.addClass(u.css+"_focused")}).focusout(function(){h.removeClass(u.css+"_focused")})})}})(jQuery)
39
- /* End jQuery TE */
 
 
 
 
 
 
 
 
 
 
 
36
  *
37
  */
38
  (function(e){e.fn.jqte=function(t){function l(e,t,n,r,i){var s=f.length+1;return f.push({name:e,cls:s,command:t,key:n,tag:r,emphasis:i})}var n=[{title:"Text Format"},{title:"Font Size"},{title:"Color"},{title:"Bold",hotkey:"B"},{title:"Italic",hotkey:"I"},{title:"Underline",hotkey:"U"},{title:"Ordered List",hotkey:"."},{title:"Unordered List",hotkey:","},{title:"Subscript",hotkey:"down arrow"},{title:"Superscript",hotkey:"up arrow"},{title:"Outdent",hotkey:"left arrow"},{title:"Indent",hotkey:"right arrow"},{title:"Justify Left"},{title:"Justify Center"},{title:"Justify Right"},{title:"Strike Through",hotkey:"K"},{title:"Add Link",hotkey:"L"},{title:"Remove Link"},{title:"Cleaner Style",hotkey:"Delete"},{title:"Horizontal Rule",hotkey:"H"},{title:"Source"}];var r=[["p","Normal"],["h1","Header 1"],["h2","Header 2"],["h3","Header 3"],["h4","Header 4"],["h5","Header 5"],["h6","Header 6"],["pre","Preformatted"]];var i=["10","12","16","18","20","24","28"];var s=["0,0,0","68,68,68","102,102,102","153,153,153","204,204,204","238,238,238","243,243,243","255,255,255",null,"255,0,0","255,153,0","255,255,0","0,255,0","0,255,255","0,0,255","153,0,255","255,0,255",null,"244,204,204","252,229,205","255,242,204","217,234,211","208,224,227","207,226,243","217,210,233","234,209,220","234,153,153","249,203,156","255,229,153","182,215,168","162,196,201","159,197,232","180,167,214","213,166,189","224,102,102","246,178,107","255,217,102","147,196,125","118,165,175","111,168,220","142,124,195","194,123,160","204,0,0","230,145,56","241,194,50","106,168,79","69,129,142","61,133,198","103,78,167","166,77,121","153,0,0","180,95,6","191,144,0","56,118,29","19,79,92","11,83,148","53,28,117","116,27,71","102,0,0","120,63,4","127,96,0","39,78,19","12,52,61","7,55,99","32,18,77","76,17,48"];var o=["Web Address","E-mail Address","Picture URL"];var u=e.extend({status:true,css:"jqte",title:true,titletext:n,button:"OK",format:true,formats:r,fsize:true,fsizes:i,funit:"px",color:true,linktypes:o,b:true,i:true,u:true,ol:true,ul:true,sub:true,sup:true,outdent:true,indent:true,left:true,center:true,right:true,strike:true,link:true,unlink:true,remove:true,rule:true,source:true,placeholder:false,br:true,p:true,change:"",focus:"",blur:""},t);e.fn.jqteVal=function(t){e(this).closest("."+u.css).find("."+u.css+"_editor").html(t)};var a=navigator.userAgent.toLowerCase();if(/msie [1-7]./.test(a))u.title=false;var f=[];l("format","formats","","",false);l("fsize","fSize","","",false);l("color","colors","","",false);l("b","Bold","B",["b","strong"],true);l("i","Italic","I",["i","em"],true);l("u","Underline","U",["u"],true);l("ol","insertorderedlist","¾",["ol"],true);l("ul","insertunorderedlist","¼",["ul"],true);l("sub","subscript","(",["sub"],true);l("sup","superscript","&",["sup"],true);l("outdent","outdent","%",["blockquote"],false);l("indent","indent","'",["blockquote"],true);l("left","justifyLeft","","",false);l("center","justifyCenter","","",false);l("right","justifyRight","","",false);l("strike","strikeThrough","K",["strike"],true);l("link","linkcreator","L",["a"],true);l("unlink","unlink","",["a"],false);l("remove","removeformat",".","",false);l("rule","inserthorizontalrule","H",["hr"],false);l("source","displaysource","","",false);return this.each(function(){function B(){if(window.getSelection)return window.getSelection();else if(document.selection&&document.selection.createRange&&document.selection.type!="None")return document.selection.createRange()}function j(e,t){var n,r=B();if(window.getSelection){if(r.anchorNode&&r.getRangeAt)n=r.getRangeAt(0);if(n){r.removeAllRanges();r.addRange(n)}if(!a.match(/msie/))document.execCommand("StyleWithCSS",false,false);document.execCommand(e,false,t)}else if(document.selection&&document.selection.createRange&&document.selection.type!="None"){n=document.selection.createRange();n.execCommand(e,false,t)}q(false,false)}function F(t,n,r){if(v.not(":focus"))v.focus();if(window.getSelection){var i=B(),s,o,u;if(i.anchorNode&&i.getRangeAt){s=i.getRangeAt(0);o=document.createElement(t);e(o).attr(n,r);u=s.extractContents();o.appendChild(u);s.insertNode(o);i.removeAllRanges();if(n=="style")q(e(o),r);else q(e(o),false)}}else if(document.selection&&document.selection.createRange&&document.selection.type!="None"){var a=document.selection.createRange();var f=a.htmlText;var l="<"+t+" "+n+'="'+r+'">'+f+"</"+t+">";document.selection.createRange().pasteHTML(l)}}function q(e,t){var n=I();n=n?n:e;if(n&&t==false){if(n.parent().is("[style]"))n.attr("style",n.parent().attr("style"));if(n.is("[style]"))n.find("*").attr("style",n.attr("style"))}else if(e&&t&&e.is("[style]")){var r=t.split(";");r=r[0].split(":");if(e.is("[style*="+r[0]+"]"))e.find("*").css(r[0],r[1]);R(e)}}function R(t){if(t){var t=t[0];if(document.body.createTextRange){var n=document.body.createTextRange();n.moveToElementText(t);n.select()}else if(window.getSelection){var r=window.getSelection();var n=document.createRange();if(t!="undefined"&&t!=null){n.selectNodeContents(t);r.removeAllRanges();r.addRange(n);if(e(t).is(":empty")){e(t).append(" ");R(e(t))}}}}}function U(){if(!p.data("sourceOpened")){var t=I();var n="http://";W(true);if(t){var r=t.prop("tagName").toLowerCase();if(r=="a"&&t.is("[href]")){n=t.attr("href");t.attr(S,"")}else F("a",S,"")}else y.val(n).focus();g.click(function(t){if(e(t.target).hasClass(u.css+"_linktypetext")||e(t.target).hasClass(u.css+"_linktypearrow"))X(true)});w.find("a").click(function(){var t=e(this).attr(u.css+"-linktype");w.data("linktype",t);E.find("."+u.css+"_linktypetext").html(w.find("a:eq("+w.data("linktype")+")").text());V(n);X()});V(n);y.focus().val(n).bind("keypress keyup",function(e){if(e.keyCode==13){z(h.find("["+S+"]"));return false}});b.click(function(){z(h.find("["+S+"]"))})}else W(false)}function z(t){y.focus();R(t);t.removeAttr(S);if(w.data("linktype")!="2")j("createlink",y.val());else{j("insertImage",y.val());v.find("img").each(function(){var t=e(this).prev("a");var n=e(this).next("a");if(t.length>0&&t.html()=="")t.remove();else if(n.length>0&&n.html()=="")n.remove()})}W();v.trigger("change")}function W(e){Q("["+S+"]:not([href])");h.find("["+S+"][href]").removeAttr(S);if(e){p.data("linkOpened",true);d.show()}else{p.data("linkOpened",false);d.hide()}X()}function X(e){if(e)w.show();else w.hide()}function V(e){var t=w.data("linktype");if(t=="1"&&(y.val()=="http://"||y.is("[value^=http://]")||!y.is("[value^=mailto]")))y.val("mailto:");else if(t!="1"&&!y.is("[value^=http://]"))y.val("http://");else y.val(e)}function J(t){if(!p.data("sourceOpened")){if(t=="fSize")styleField=P;else if(t=="colors")styleField=H;K(styleField,true);styleField.find("a").unbind("click").click(function(){var n=e(this).attr(u.css+"-styleval");if(t=="fSize"){styleType="font-size";n=n+u.funit}else if(t=="colors"){styleType="color";n="rgb("+n+")"}var r=G(styleType);F("span","style",styleType+":"+n+";"+r);K("",false);e("."+u.css+"_title").remove();v.trigger("change")})}else K(styleField,false);W(false)}function K(e,t){var n="",r=[{d:"fsizeOpened",f:P},{d:"cpallOpened",f:H}];if(e!=""){for(var i=0;i<r.length;i++){if(e==r[i]["f"])n=r[i]}}if(t){p.data(n["d"],true);n["f"].slideDown(100);for(var i=0;i<r.length;i++){if(n["d"]!=r[i]["d"]){p.data(r[i]["d"],false);r[i]["f"].slideUp(100)}}}else{for(var i=0;i<r.length;i++){p.data(r[i]["d"],false);r[i]["f"].slideUp(100)}}}function Q(t){h.find(t).each(function(){e(this).before(e(this).html()).remove()})}function G(e){var t=I();if(t&&t.is("[style]")&&t.css(e)!=""){var n=t.css(e);t.css(e,"");var r=t.attr("style");t.css(e,n);return r}else return""}function Y(){Z(true);D.find("a").click(function(){e("*",this).click(function(e){e.preventDefault();return false});et(e(this).text());var t=e(this).attr(u.css+"-formatval");j("formatBlock","<"+t+">");Z(false)})}function Z(e){var t=e?true:false;t=e&&D.data("status")?true:false;if(t||!e)D.data("status",false).slideUp(200);else D.data("status",true).slideDown(200)}function et(e){var t=D.closest("."+u.css+"_tool").find("."+u.css+"_tool_label").find("."+u.css+"_tool_text");if(e.length>10)e=e.substr(0,7)+"...";t.html(e)}function tt(e){var t,n,r;t=e.replace(/\n/gim,"").replace(/\r/gim,"").replace(/\t/gim,"").replace(/ /gim," ");n=[/\<span(|\s+.*?)><span(|\s+.*?)>(.*?)<\/span><\/span>/gim,/<(\w*[^p])\s*[^\/>]*>\s*<\/\1>/gim,/\<div(|\s+.*?)>(.*?)\<\/div>/gim,/\<strong(|\s+.*?)>(.*?)\<\/strong>/gim,/\<em(|\s+.*?)>(.*?)\<\/em>/gim];r=["<span$2>$3</span>","","<p$1>$2</p>","<b$1>$2</b>","<i$1>$2</i>"];for(A=0;A<5;A++){for(var i=0;i<n.length;i++){t=t.replace(n[i],r[i])}}if(!u.p)t=t.replace(/\<p(|\s+.*?)>(.*?)\<\/p>/ig,"<br/>$2");if(!u.br){n=[/\<br>(.*?)/ig,/\<br\/>(.*?)/ig];r=["<p>$1</p>","<p>$1</p>"];for(var i=0;i<n.length;i++){t=t.replace(n[i],r[i])}}if(!u.p&&!u.br)t=t.replace(/\<p>(.*?)\<\/p>/ig,"<div>$1</div>");return t}function nt(){var e=v.text()==""&&v.html().length<12?"":v.html();l.val(tt(e))}function rt(){v.html(tt(l.val()))}function it(t){var n=false,r=I(),i;if(r){e.each(t,function(t,s){i=r.prop("tagName").toLowerCase();if(i==s)n=true;else{r.parents().each(function(){i=e(this).prop("tagName").toLowerCase();if(i==s)n=true})}});return n}else return false}function st(t){for(var n=0;n<f.length;n++){if(u[f[n].name]&&f[n].emphasis&&f[n].tag!="")it(f[n].tag)?p.find("."+u.css+"_tool_"+f[n].cls).addClass(m):e("."+u.css+"_tool_"+f[n].cls).removeClass(m)}if(u.format&&e.isArray(u.formats)){var r=false;for(var i=0;i<u.formats.length;i++){var s=[];s[0]=u.formats[i][0];if(u.formats[i][0].length>0&&it(s)){et(u.formats[i][1]);r=true;break}}if(!r)et(u.formats[0][1])}K("",false);Z(false)}if(!e(this).data("jqte")||e(this).data("jqte")==null||e(this).data("jqte")=="undefined")e(this).data("jqte",true);else e(this).data("jqte",false);if(!u.status||!e(this).data("jqte")){if(e(this).closest("."+u.css).length>0){var t=e(this).closest("."+u.css).find("."+u.css+"_editor").html();var n="";e(e(this)[0].attributes).each(function(){if(this.nodeName!="style")n=n+" "+this.nodeName+'="'+this.nodeValue+'"'});var r=e(this).is("[data-origin]")&&e(this).attr("data-origin")!=""?e(this).attr("data-origin"):"textarea";var i=">"+t;if(r=="input"||r=="option"){t=t.replace(/"/g,"&#34;").replace(/'/g,"&#39;").replace(/</g,"<").replace(/>/g,">");i='value="'+t+'">'}var o=e(this).clone();e(this).data("jqte",false).closest("."+u.css).before(o).remove();o.replaceWith("<"+r+n+i+"</"+r+">")}return}var l=e(this);var r=e(this).prop("tagName").toLowerCase();e(this).attr("data-origin",r);var c=e(this).is("[value]")||r=="textarea"?e(this).val():e(this).html();c=c.replace(/&#34;/g,'"').replace(/&#39;/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&");e(this).after('<div class="'+u.css+'"></div>');var h=e(this).next("."+u.css);h.html('<div class="'+u.css+"_toolbar"+'" role="toolbar" unselectable></div><div class="'+u.css+'_linkform" style="display:none" role="dialog"></div><div class="'+u.css+"_editor"+'"></div>');var p=h.find("."+u.css+"_toolbar");var d=h.find("."+u.css+"_linkform");var v=h.find("."+u.css+"_editor");var m=u.css+"_tool_depressed";d.append('<div class="'+u.css+'_linktypeselect" unselectable></div><input class="'+u.css+'_linkinput" type="text/css" value=""><div class="'+u.css+'_linkbutton" unselectable>'+u.button+'</div> <div style="height:1px;float:none;clear:both"></div>');var g=d.find("."+u.css+"_linktypeselect");var y=d.find("."+u.css+"_linkinput");var b=d.find("."+u.css+"_linkbutton");g.append('<div class="'+u.css+'_linktypeview" unselectable></div><div class="'+u.css+'_linktypes" role="menu" unselectable></div>');var w=g.find("."+u.css+"_linktypes");var E=g.find("."+u.css+"_linktypeview");var S=u.css+"-setlink";v.after('<div class="'+u.css+"_source "+u.css+'_hiddenField"></div>');var x=h.find("."+u.css+"_source");l.appendTo(x);if(r!="textarea"){var n="";e(l[0].attributes).each(function(){if(this.nodeName!="type"&&this.nodeName!="value")n=n+" "+this.nodeName+'="'+this.nodeValue+'"'});l.replaceWith("<textarea "+n+">"+c+"</textarea>");l=x.find("textarea")}v.attr("contenteditable","true").html(c);for(var T=0;T<f.length;T++){if(u[f[T].name]){var N=f[T].key.length>0?u.titletext[T].hotkey!=null&&u.titletext[T].hotkey!="undefined"&&u.titletext[T].hotkey!=""?" (Ctrl+"+u.titletext[T].hotkey+")":"":"";var C=u.titletext[T].title!=null&&u.titletext[T].title!="undefined"&&u.titletext[T].title!=""?u.titletext[T].title+N:"";p.append('<div class="'+u.css+"_tool "+u.css+"_tool_"+f[T].cls+'" role="button" data-tool="'+T+'" unselectable><a class="'+u.css+'_tool_icon" unselectable></a></div>');p.find("."+u.css+"_tool[data-tool="+T+"]").data({tag:f[T].tag,command:f[T].command,emphasis:f[T].emphasis,title:C});if(f[T].name=="format"&&e.isArray(u.formats)){var k=u.formats[0][1].length>0&&u.formats[0][1]!="undefined"?u.formats[0][1]:"";p.find("."+u.css+"_tool_"+f[T].cls).find("."+u.css+"_tool_icon").replaceWith('<a class="'+u.css+'_tool_label" unselectable><span class="'+u.css+'_tool_text" unselectable>'+k+'</span><span class="'+u.css+'_tool_icon" unselectable></span></a>');p.find("."+u.css+"_tool_"+f[T].cls).append('<div class="'+u.css+'_formats" unselectable></div>');for(var L=0;L<u.formats.length;L++){p.find("."+u.css+"_formats").append("<a "+u.css+'-formatval="'+u.formats[L][0]+'" class="'+u.css+"_format"+" "+u.css+"_format_"+L+'" role="menuitem" unselectable>'+u.formats[L][1]+"</a>")}p.find("."+u.css+"_formats").data("status",false)}else if(f[T].name=="fsize"&&e.isArray(u.fsizes)){p.find("."+u.css+"_tool_"+f[T].cls).append('<div class="'+u.css+'_fontsizes" unselectable></div>');for(var L=0;L<u.fsizes.length;L++){p.find("."+u.css+"_fontsizes").append("<a "+u.css+'-styleval="'+u.fsizes[L]+'" class="'+u.css+"_fontsize"+'" style="font-size:'+u.fsizes[L]+u.funit+'" role="menuitem" unselectable>Abcdefgh...</a>')}}else if(f[T].name=="color"&&e.isArray(s)){p.find("."+u.css+"_tool_"+f[T].cls).append('<div class="'+u.css+'_cpalette" unselectable></div>');for(var A=0;A<s.length;A++){if(s[A]!=null)p.find("."+u.css+"_cpalette").append("<a "+u.css+'-styleval="'+s[A]+'" class="'+u.css+"_color"+'" style="background-color: rgb('+s[A]+')" role="gridcell" unselectable></a>');else p.find("."+u.css+"_cpalette").append('<div class="'+u.css+"_colorSeperator"+'"></div>')}}}}w.data("linktype","0");for(var T=0;T<3;T++){w.append("<a "+u.css+'-linktype="'+T+'" unselectable>'+u.linktypes[T]+"</a>");E.html('<div class="'+u.css+'_linktypearrow" unselectable></div><div class="'+u.css+'_linktypetext">'+w.find("a:eq("+w.data("linktype")+")").text()+"</div>")}var O="";if(/msie/.test(a))O="-ms-";else if(/chrome/.test(a)||/safari/.test(a)||/yandex/.test(a))O="-webkit-";else if(/mozilla/.test(a))O="-moz-";else if(/opera/.test(a))O="-o-";else if(/konqueror/.test(a))O="-khtml-";else O="";if(u.placeholder&&u.placeholder!=""){h.prepend('<div class="'+u.css+'_placeholder" unselectable><div class="'+u.css+'_placeholder_text">'+u.placeholder+"</div></div>");var M=h.find("."+u.css+"_placeholder");M.click(function(){v.focus()})}h.find("[unselectable]").css(O+"user-select","none").addClass("unselectable").attr("unselectable","on").on("selectstart mousedown",false);var _=p.find("."+u.css+"_tool");var D=p.find("."+u.css+"_formats");var P=p.find("."+u.css+"_fontsizes");var H=p.find("."+u.css+"_cpalette");var I=function(){var t,n;if(window.getSelection){n=getSelection();t=n.anchorNode}if(!t&&document.selection&&document.selection.createRange&&document.selection.type!="None"){n=document.selection;var r=n.getRangeAt?n.getRangeAt(0):n.createRange();t=r.commonAncestorContainer?r.commonAncestorContainer:r.parentElement?r.parentElement():r.item(0)}if(t){return t.nodeName=="#text"?e(t.parentNode):e(t)}else return false};_.unbind("click").click(function(t){if(e(this).data("command")=="displaysource"&&!p.data("sourceOpened")){p.find("."+u.css+"_tool").addClass(u.css+"_hiddenField");e(this).removeClass(u.css+"_hiddenField");p.data("sourceOpened",true);l.css("height",v.outerHeight());x.removeClass(u.css+"_hiddenField");v.addClass(u.css+"_hiddenField");l.focus();W(false);K("",false);Z();if(u.placeholder&&u.placeholder!="")M.hide()}else{if(!p.data("sourceOpened")){if(e(this).data("command")=="linkcreator"){if(!p.data("linkOpened"))U();else{W(false);Z(false)}}else if(e(this).data("command")=="formats"){if(e(this).data("command")=="formats"&&!e(t.target).hasClass(u.css+"_format"))Y();K("",false);if(v.not(":focus"))v.focus()}else if(e(this).data("command")=="fSize"||e(this).data("command")=="colors"){if(e(this).data("command")=="fSize"&&!e(t.target).hasClass(u.css+"_fontsize")||e(this).data("command")=="colors"&&!e(t.target).hasClass(u.css+"_color"))J(e(this).data("command"));Z(false);if(v.not(":focus"))v.focus()}else{if(v.not(":focus"))v.focus();j(e(this).data("command"),null);K("",false);Z(false);X();e(this).data("emphasis")==true&&!e(this).hasClass(m)?e(this).addClass(m):e(this).removeClass(m);x.addClass(u.css+"_hiddenField");v.removeClass(u.css+"_hiddenField")}}else{p.data("sourceOpened",false);p.find("."+u.css+"_tool").removeClass(u.css+"_hiddenField");x.addClass(u.css+"_hiddenField");v.removeClass(u.css+"_hiddenField")}if(u.placeholder&&u.placeholder!="")v.html()!=""?M.hide():M.show()}v.trigger("change")}).hover(function(t){if(u.title&&e(this).data("title")!=""&&(e(t.target).hasClass(u.css+"_tool")||e(t.target).hasClass(u.css+"_tool_icon"))){e("."+u.css+"_title").remove();h.append('<div class="'+u.css+'_title"><div class="'+u.css+'_titleArrow"><div class="'+u.css+'_titleArrowIcon"></div></div><div class="'+u.css+'_titleText">'+e(this).data("title")+"</div></div>");var n=e("."+u.css+"_title:first");var r=n.find("."+u.css+"_titleArrowIcon");var i=e(this).position();var s=i.left+e(this).outerWidth()-n.outerWidth()/2-e(this).outerWidth()/2;var o=i.top+e(this).outerHeight()+5;n.delay(400).css({top:o,left:s}).fadeIn(200)}},function(){e("."+u.css+"_title").remove()});var ot=null;v.bind("keypress keyup keydown drop cut copy paste DOMCharacterDataModified DOMSubtreeModified",function(){if(!p.data("sourceOpened"))e(this).trigger("change");X();if(e.isFunction(u.change))u.change();if(u.placeholder&&u.placeholder!="")e(this).text()!=""?M.hide():M.show()}).bind("change",function(){if(!p.data("sourceOpened")){clearTimeout(ot);ot=setTimeout(nt,10)}}).keydown(function(e){if(e.ctrlKey){for(var t=0;t<f.length;t++){if(u[f[t].name]&&e.keyCode==f[t].key.charCodeAt(0)){if(f[t].command!=""&&f[t].command!="linkcreator")j(f[t].command,null);else if(f[t].command=="linkcreator")U();return false}}}}).bind("mouseup keyup",st).focus(function(){if(e.isFunction(u.focus))u.focus();h.addClass(u.css+"_focused");if(/opera/.test(a)){var t=document.createRange();t.selectNodeContents(v[0]);t.collapse(false);var n=window.getSelection();n.removeAllRanges();n.addRange(t)}}).focusout(function(){_.removeClass(m);K("",false);Z(false);X();if(e.isFunction(u.blur))u.blur();h.removeClass(u.css+"_focused");if(e.isArray(u.formats))et(u.formats[0][1])});l.bind("keydown keyup",function(){setTimeout(rt,0);e(this).height(e(this)[0].scrollHeight);if(e(this).val()=="")e(this).height(0)}).focus(function(){h.addClass(u.css+"_focused")}).focusout(function(){h.removeClass(u.css+"_focused")})})}})(jQuery)
39
+ /* End jQuery TE */
40
+
41
+ /* Begin MiniColors */
42
+ //
43
+ // jQuery MiniColors: A tiny color picker built on jQuery
44
+ //
45
+ // Developed by Cory LaViska for A Beautiful Site, LLC
46
+ //
47
+ // Licensed under the MIT license: http://opensource.org/licenses/MIT
48
+ //
49
+ !function(i){"function"==typeof define&&define.amd?define(["jquery"],i):"object"==typeof exports?module.exports=i(require("jquery")):i(jQuery)}(function(i){"use strict";function t(t,o){var s,a,n,r,e,l=i('<div class="minicolors" />'),h=i.minicolors.defaults;if(!t.data("minicolors-initialized")){if(o=i.extend(!0,{},h,o),l.addClass("minicolors-theme-"+o.theme).toggleClass("minicolors-with-opacity",o.opacity),void 0!==o.position&&i.each(o.position.split(" "),function(){l.addClass("minicolors-position-"+this)}),s="rgb"===o.format?o.opacity?"25":"20":o.keywords?"11":"7",t.addClass("minicolors-input").data("minicolors-initialized",!1).data("minicolors-settings",o).prop("size",s).wrap(l).after('<div class="minicolors-panel minicolors-slider-'+o.control+'"><div class="minicolors-slider minicolors-sprite"><div class="minicolors-picker"></div></div><div class="minicolors-opacity-slider minicolors-sprite"><div class="minicolors-picker"></div></div><div class="minicolors-grid minicolors-sprite"><div class="minicolors-grid-inner"></div><div class="minicolors-picker"><div></div></div></div></div>'),o.inline||(t.after('<span class="minicolors-swatch minicolors-sprite minicolors-input-swatch"><span class="minicolors-swatch-color"></span></span>'),t.next(".minicolors-input-swatch").on("click",function(i){i.preventDefault(),t.focus()})),r=t.parent().find(".minicolors-panel"),r.on("selectstart",function(){return!1}).end(),o.swatches&&0!==o.swatches.length)for(r.addClass("minicolors-with-swatches"),a=i('<ul class="minicolors-swatches"></ul>').appendTo(r),e=0;e<o.swatches.length;++e)n=o.swatches[e],n=v(n)?g(n,!0):I(u(n,!0)),i('<li class="minicolors-swatch minicolors-sprite"><span class="minicolors-swatch-color"></span></li>').appendTo(a).data("swatch-color",o.swatches[e]).find(".minicolors-swatch-color").css({backgroundColor:C(n),opacity:n.a}),o.swatches[e]=n;o.inline&&t.parent().addClass("minicolors-inline"),c(t,!1),t.data("minicolors-initialized",!0)}}function o(i){var t=i.parent();i.removeData("minicolors-initialized").removeData("minicolors-settings").removeProp("size").removeClass("minicolors-input"),t.before(i).remove()}function s(i){var t=i.parent(),o=t.find(".minicolors-panel"),s=i.data("minicolors-settings");!i.data("minicolors-initialized")||i.prop("disabled")||t.hasClass("minicolors-inline")||t.hasClass("minicolors-focus")||(a(),t.addClass("minicolors-focus"),o.stop(!0,!0).fadeIn(s.showSpeed,function(){s.show&&s.show.call(i.get(0))}))}function a(){i(".minicolors-focus").each(function(){var t=i(this),o=t.find(".minicolors-input"),s=t.find(".minicolors-panel"),a=o.data("minicolors-settings");s.fadeOut(a.hideSpeed,function(){a.hide&&a.hide.call(o.get(0)),t.removeClass("minicolors-focus")})})}function n(i,t,o){var s,a,n,e,c=i.parents(".minicolors").find(".minicolors-input"),l=c.data("minicolors-settings"),h=i.find("[class$=-picker]"),d=i.offset().left,p=i.offset().top,u=Math.round(t.pageX-d),g=Math.round(t.pageY-p),m=o?l.animationSpeed:0;t.originalEvent.changedTouches&&(u=t.originalEvent.changedTouches[0].pageX-d,g=t.originalEvent.changedTouches[0].pageY-p),u<0&&(u=0),g<0&&(g=0),u>i.width()&&(u=i.width()),g>i.height()&&(g=i.height()),i.parent().is(".minicolors-slider-wheel")&&h.parent().is(".minicolors-grid")&&(s=75-u,a=75-g,n=Math.sqrt(s*s+a*a),e=Math.atan2(a,s),e<0&&(e+=2*Math.PI),n>75&&(n=75,u=75-75*Math.cos(e),g=75-75*Math.sin(e)),u=Math.round(u),g=Math.round(g)),i.is(".minicolors-grid")?h.stop(!0).animate({top:g+"px",left:u+"px"},m,l.animationEasing,function(){r(c,i)}):h.stop(!0).animate({top:g+"px"},m,l.animationEasing,function(){r(c,i)})}function r(i,t){function o(i,t){var o,s;return i.length&&t?(o=i.offset().left,s=i.offset().top,{x:o-t.offset().left+i.outerWidth()/2,y:s-t.offset().top+i.outerHeight()/2}):null}var s,a,n,r,c,h,d,p=i.val(),u=i.attr("data-opacity"),g=i.parent(),m=i.data("minicolors-settings"),v=g.find(".minicolors-input-swatch"),b=g.find(".minicolors-grid"),w=g.find(".minicolors-slider"),y=g.find(".minicolors-opacity-slider"),C=b.find("[class$=-picker]"),M=w.find("[class$=-picker]"),x=y.find("[class$=-picker]"),I=o(C,b),S=o(M,w),z=o(x,y);if(t.is(".minicolors-grid, .minicolors-slider, .minicolors-opacity-slider")){switch(m.control){case"wheel":r=b.width()/2-I.x,c=b.height()/2-I.y,h=Math.sqrt(r*r+c*c),d=Math.atan2(c,r),d<0&&(d+=2*Math.PI),h>75&&(h=75,I.x=69-75*Math.cos(d),I.y=69-75*Math.sin(d)),a=f(h/.75,0,100),s=f(180*d/Math.PI,0,360),n=f(100-Math.floor(S.y*(100/w.height())),0,100),p=k({h:s,s:a,b:n}),w.css("backgroundColor",k({h:s,s:a,b:100}));break;case"saturation":s=f(parseInt(I.x*(360/b.width()),10),0,360),a=f(100-Math.floor(S.y*(100/w.height())),0,100),n=f(100-Math.floor(I.y*(100/b.height())),0,100),p=k({h:s,s:a,b:n}),w.css("backgroundColor",k({h:s,s:100,b:n})),g.find(".minicolors-grid-inner").css("opacity",a/100);break;case"brightness":s=f(parseInt(I.x*(360/b.width()),10),0,360),a=f(100-Math.floor(I.y*(100/b.height())),0,100),n=f(100-Math.floor(S.y*(100/w.height())),0,100),p=k({h:s,s:a,b:n}),w.css("backgroundColor",k({h:s,s:a,b:100})),g.find(".minicolors-grid-inner").css("opacity",1-n/100);break;default:s=f(360-parseInt(S.y*(360/w.height()),10),0,360),a=f(Math.floor(I.x*(100/b.width())),0,100),n=f(100-Math.floor(I.y*(100/b.height())),0,100),p=k({h:s,s:a,b:n}),b.css("backgroundColor",k({h:s,s:100,b:100}))}u=m.opacity?parseFloat(1-z.y/y.height()).toFixed(2):1,e(i,p,u)}else v.find("span").css({backgroundColor:p,opacity:u}),l(i,p,u)}function e(i,t,o){var s,a=i.parent(),n=i.data("minicolors-settings"),r=a.find(".minicolors-input-swatch");n.opacity&&i.attr("data-opacity",o),"rgb"===n.format?(s=v(t)?g(t,!0):I(u(t,!0)),o=""===i.attr("data-opacity")?1:f(parseFloat(i.attr("data-opacity")).toFixed(2),0,1),!isNaN(o)&&n.opacity||(o=1),t=i.minicolors("rgbObject").a<=1&&s&&n.opacity?"rgba("+s.r+", "+s.g+", "+s.b+", "+parseFloat(o)+")":"rgb("+s.r+", "+s.g+", "+s.b+")"):(v(t)&&(t=y(t)),t=p(t,n.letterCase)),i.val(t),r.find("span").css({backgroundColor:t,opacity:o}),l(i,t,o)}function c(t,o){var s,a,n,r,e,c,h,d,w,C,x=t.parent(),I=t.data("minicolors-settings"),S=x.find(".minicolors-input-swatch"),z=x.find(".minicolors-grid"),F=x.find(".minicolors-slider"),T=x.find(".minicolors-opacity-slider"),D=z.find("[class$=-picker]"),j=F.find("[class$=-picker]"),q=T.find("[class$=-picker]");switch(v(t.val())?(s=y(t.val()),e=f(parseFloat(b(t.val())).toFixed(2),0,1),e&&t.attr("data-opacity",e)):s=p(u(t.val(),!0),I.letterCase),s||(s=p(m(I.defaultValue,!0),I.letterCase)),a=M(s),r=I.keywords?i.map(I.keywords.split(","),function(t){return i.trim(t.toLowerCase())}):[],c=""!==t.val()&&i.inArray(t.val().toLowerCase(),r)>-1?p(t.val()):v(t.val())?g(t.val()):s,o||t.val(c),I.opacity&&(n=""===t.attr("data-opacity")?1:f(parseFloat(t.attr("data-opacity")).toFixed(2),0,1),isNaN(n)&&(n=1),t.attr("data-opacity",n),S.find("span").css("opacity",n),d=f(T.height()-T.height()*n,0,T.height()),q.css("top",d+"px")),"transparent"===t.val().toLowerCase()&&S.find("span").css("opacity",0),S.find("span").css("backgroundColor",s),I.control){case"wheel":w=f(Math.ceil(.75*a.s),0,z.height()/2),C=a.h*Math.PI/180,h=f(75-Math.cos(C)*w,0,z.width()),d=f(75-Math.sin(C)*w,0,z.height()),D.css({top:d+"px",left:h+"px"}),d=150-a.b/(100/z.height()),""===s&&(d=0),j.css("top",d+"px"),F.css("backgroundColor",k({h:a.h,s:a.s,b:100}));break;case"saturation":h=f(5*a.h/12,0,150),d=f(z.height()-Math.ceil(a.b/(100/z.height())),0,z.height()),D.css({top:d+"px",left:h+"px"}),d=f(F.height()-a.s*(F.height()/100),0,F.height()),j.css("top",d+"px"),F.css("backgroundColor",k({h:a.h,s:100,b:a.b})),x.find(".minicolors-grid-inner").css("opacity",a.s/100);break;case"brightness":h=f(5*a.h/12,0,150),d=f(z.height()-Math.ceil(a.s/(100/z.height())),0,z.height()),D.css({top:d+"px",left:h+"px"}),d=f(F.height()-a.b*(F.height()/100),0,F.height()),j.css("top",d+"px"),F.css("backgroundColor",k({h:a.h,s:a.s,b:100})),x.find(".minicolors-grid-inner").css("opacity",1-a.b/100);break;default:h=f(Math.ceil(a.s/(100/z.width())),0,z.width()),d=f(z.height()-Math.ceil(a.b/(100/z.height())),0,z.height()),D.css({top:d+"px",left:h+"px"}),d=f(F.height()-a.h/(360/F.height()),0,F.height()),j.css("top",d+"px"),z.css("backgroundColor",k({h:a.h,s:100,b:100}))}t.data("minicolors-initialized")&&l(t,c,n)}function l(i,t,o){var s,a,n,r=i.data("minicolors-settings"),e=i.data("minicolors-lastChange");if(!e||e.value!==t||e.opacity!==o){if(i.data("minicolors-lastChange",{value:t,opacity:o}),r.swatches&&0!==r.swatches.length){for(s=v(t)?g(t,!0):I(t),a=-1,n=0;n<r.swatches.length;++n)if(s.r===r.swatches[n].r&&s.g===r.swatches[n].g&&s.b===r.swatches[n].b&&s.a===r.swatches[n].a){a=n;break}i.parent().find(".minicolors-swatches .minicolors-swatch").removeClass("selected"),a!==-1&&i.parent().find(".minicolors-swatches .minicolors-swatch").eq(n).addClass("selected")}r.change&&(r.changeDelay?(clearTimeout(i.data("minicolors-changeTimeout")),i.data("minicolors-changeTimeout",setTimeout(function(){r.change.call(i.get(0),t,o)},r.changeDelay))):r.change.call(i.get(0),t,o)),i.trigger("change").trigger("input")}}function h(t){var o,s=i(t).attr("data-opacity");if(v(i(t).val()))o=g(i(t).val(),!0);else{var a=u(i(t).val(),!0);o=I(a)}return o?(void 0!==s&&i.extend(o,{a:parseFloat(s)}),o):null}function d(t,o){var s,a=i(t).attr("data-opacity");if(v(i(t).val()))s=g(i(t).val(),!0);else{var n=u(i(t).val(),!0);s=I(n)}return s?(void 0===a&&(a=1),o?"rgba("+s.r+", "+s.g+", "+s.b+", "+parseFloat(a)+")":"rgb("+s.r+", "+s.g+", "+s.b+")"):null}function p(i,t){return"uppercase"===t?i.toUpperCase():i.toLowerCase()}function u(i,t){return i=i.replace(/^#/g,""),i.match(/^[A-F0-9]{3,6}/gi)?3!==i.length&&6!==i.length?"":(3===i.length&&t&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]),"#"+i):""}function g(i,t){var o=i.replace(/[^\d,.]/g,""),s=o.split(",");return s[0]=f(parseInt(s[0],10),0,255),s[1]=f(parseInt(s[1],10),0,255),s[2]=f(parseInt(s[2],10),0,255),s[3]&&(s[3]=f(parseFloat(s[3],10),0,1)),t?s[3]?{r:s[0],g:s[1],b:s[2],a:s[3]}:{r:s[0],g:s[1],b:s[2]}:"undefined"!=typeof s[3]&&s[3]<=1?"rgba("+s[0]+", "+s[1]+", "+s[2]+", "+s[3]+")":"rgb("+s[0]+", "+s[1]+", "+s[2]+")"}function m(i,t){return v(i)?g(i):u(i,t)}function f(i,t,o){return i<t&&(i=t),i>o&&(i=o),i}function v(i){var t=i.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);return!(!t||4!==t.length)}function b(i){return i=i.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+(\.\d{1,2})?|\.\d{1,2})[\s+]?/i),i&&6===i.length?i[4]:"1"}function w(i){var t={},o=Math.round(i.h),s=Math.round(255*i.s/100),a=Math.round(255*i.b/100);if(0===s)t.r=t.g=t.b=a;else{var n=a,r=(255-s)*a/255,e=(n-r)*(o%60)/60;360===o&&(o=0),o<60?(t.r=n,t.b=r,t.g=r+e):o<120?(t.g=n,t.b=r,t.r=n-e):o<180?(t.g=n,t.r=r,t.b=r+e):o<240?(t.b=n,t.r=r,t.g=n-e):o<300?(t.b=n,t.g=r,t.r=r+e):o<360?(t.r=n,t.g=r,t.b=n-e):(t.r=0,t.g=0,t.b=0)}return{r:Math.round(t.r),g:Math.round(t.g),b:Math.round(t.b)}}function y(i){return i=i.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i),i&&4===i.length?"#"+("0"+parseInt(i[1],10).toString(16)).slice(-2)+("0"+parseInt(i[2],10).toString(16)).slice(-2)+("0"+parseInt(i[3],10).toString(16)).slice(-2):""}function C(t){var o=[t.r.toString(16),t.g.toString(16),t.b.toString(16)];return i.each(o,function(i,t){1===t.length&&(o[i]="0"+t)}),"#"+o.join("")}function k(i){return C(w(i))}function M(i){var t=x(I(i));return 0===t.s&&(t.h=360),t}function x(i){var t={h:0,s:0,b:0},o=Math.min(i.r,i.g,i.b),s=Math.max(i.r,i.g,i.b),a=s-o;return t.b=s,t.s=0!==s?255*a/s:0,0!==t.s?i.r===s?t.h=(i.g-i.b)/a:i.g===s?t.h=2+(i.b-i.r)/a:t.h=4+(i.r-i.g)/a:t.h=-1,t.h*=60,t.h<0&&(t.h+=360),t.s*=100/255,t.b*=100/255,t}function I(i){return i=parseInt(i.indexOf("#")>-1?i.substring(1):i,16),{r:i>>16,g:(65280&i)>>8,b:255&i}}i.minicolors={defaults:{animationSpeed:50,animationEasing:"swing",change:null,changeDelay:0,control:"hue",defaultValue:"",format:"hex",hide:null,hideSpeed:100,inline:!1,keywords:"",letterCase:"lowercase",opacity:!1,position:"bottom left",show:null,showSpeed:100,theme:"default",swatches:[]}},i.extend(i.fn,{minicolors:function(n,r){switch(n){case"destroy":return i(this).each(function(){o(i(this))}),i(this);case"hide":return a(),i(this);case"opacity":return void 0===r?i(this).attr("data-opacity"):(i(this).each(function(){c(i(this).attr("data-opacity",r))}),i(this));case"rgbObject":return h(i(this),"rgbaObject"===n);case"rgbString":case"rgbaString":return d(i(this),"rgbaString"===n);case"settings":return void 0===r?i(this).data("minicolors-settings"):(i(this).each(function(){var t=i(this).data("minicolors-settings")||{};o(i(this)),i(this).minicolors(i.extend(!0,t,r))}),i(this));case"show":return s(i(this).eq(0)),i(this);case"value":return void 0===r?i(this).val():(i(this).each(function(){"object"==typeof r&&null!==r?(r.opacity&&i(this).attr("data-opacity",f(r.opacity,0,1)),r.color&&i(this).val(r.color)):i(this).val(r),c(i(this))}),i(this));default:return"create"!==n&&(r=n),i(this).each(function(){t(i(this),r)}),i(this)}}}),i([document]).on("mousedown.minicolors touchstart.minicolors",function(t){i(t.target).parents().add(t.target).hasClass("minicolors")||a()}).on("mousedown.minicolors touchstart.minicolors",".minicolors-grid, .minicolors-slider, .minicolors-opacity-slider",function(t){var o=i(this);t.preventDefault(),i(t.delegateTarget).data("minicolors-target",o),n(o,t,!0)}).on("mousemove.minicolors touchmove.minicolors",function(t){var o=i(t.delegateTarget).data("minicolors-target");o&&n(o,t)}).on("mouseup.minicolors touchend.minicolors",function(){i(this).removeData("minicolors-target")}).on("click.minicolors",".minicolors-swatches li",function(t){t.preventDefault();var o=i(this),s=o.parents(".minicolors").find(".minicolors-input"),a=o.data("swatch-color");e(s,a,b(a)),c(s)}).on("mousedown.minicolors touchstart.minicolors",".minicolors-input-swatch",function(t){var o=i(this).parent().find(".minicolors-input");t.preventDefault(),s(o)}).on("focus.minicolors",".minicolors-input",function(){var t=i(this);t.data("minicolors-initialized")&&s(t)}).on("blur.minicolors",".minicolors-input",function(){var t,o,s,a,n,r=i(this),e=r.data("minicolors-settings");r.data("minicolors-initialized")&&(t=e.keywords?i.map(e.keywords.split(","),function(t){return i.trim(t.toLowerCase())}):[],""!==r.val()&&i.inArray(r.val().toLowerCase(),t)>-1?n=r.val():(v(r.val())?s=g(r.val(),!0):(o=u(r.val(),!0),s=o?I(o):null),n=null===s?e.defaultValue:"rgb"===e.format?g(e.opacity?"rgba("+s.r+","+s.g+","+s.b+","+r.attr("data-opacity")+")":"rgb("+s.r+","+s.g+","+s.b+")"):C(s)),a=e.opacity?r.attr("data-opacity"):1,"transparent"===n.toLowerCase()&&(a=0),r.closest(".minicolors").find(".minicolors-input-swatch > span").css("opacity",a),r.val(n),""===r.val()&&r.val(m(e.defaultValue,!0)),r.val(p(r.val(),e.letterCase)))}).on("keydown.minicolors",".minicolors-input",function(t){var o=i(this);if(o.data("minicolors-initialized"))switch(t.keyCode){case 9:a();break;case 13:case 27:a(),o.blur()}}).on("keyup.minicolors",".minicolors-input",function(){var t=i(this);t.data("minicolors-initialized")&&c(t,!0)}).on("paste.minicolors",".minicolors-input",function(){var t=i(this);t.data("minicolors-initialized")&&setTimeout(function(){c(t,!0)},1)})});
50
+ /* End MiniColors */
includes/controls/assets/js/uncompressed/jQuery-TE/jquery-te-1.4.0.js ADDED
@@ -0,0 +1,1347 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ *
3
+ * jQuery TE 1.4.0 , http://jqueryte.com/
4
+ * Copyright (C) 2013, Fatih Koca (fattih@fattih.com), (http://jqueryte.com/about)
5
+
6
+ * jQuery TE is provided under the MIT LICENSE.
7
+ *
8
+ */
9
+
10
+ (function($){
11
+ $.fn.jqte = function(options){
12
+
13
+ // default titles of buttons
14
+ var varsTitle = [
15
+ {title:"Text Format"},
16
+ {title:"Font Size"},
17
+ {title:"Color"},
18
+ {title:"Bold",hotkey:"B"},
19
+ {title:"Italic",hotkey:"I"},
20
+ {title:"Underline",hotkey:"U"},
21
+ {title:"Ordered List",hotkey:"."},
22
+ {title:"Unordered List",hotkey:","},
23
+ {title:"Subscript",hotkey:"down arrow"},
24
+ {title:"Superscript",hotkey:"up arrow"},
25
+ {title:"Outdent",hotkey:"left arrow"},
26
+ {title:"Indent",hotkey:"right arrow"},
27
+ {title:"Justify Left"},
28
+ {title:"Justify Center"},
29
+ {title:"Justify Right"},
30
+ {title:"Strike Through",hotkey:"K"},
31
+ {title:"Add Link",hotkey:"L"},
32
+ {title:"Remove Link"},
33
+ {title:"Cleaner Style",hotkey:"Delete"},
34
+ {title:"Horizontal Rule",hotkey:"H"},
35
+ {title:"Source"}
36
+ ];
37
+
38
+ // default text formats
39
+ var formats = [["p","Normal"],["h1","Header 1"],["h2","Header 2"],["h3","Header 3"],["h4","Header 4"],["h5","Header 5"],["h6","Header 6"],["pre","Preformatted"]];
40
+
41
+ // default font sizes
42
+ var fsizes = ["10","12","16","18","20","24","28"];
43
+
44
+ // default rgb values of colors
45
+ var colors = [
46
+ "0,0,0","68,68,68","102,102,102","153,153,153","204,204,204","238,238,238","243,243,243","255,255,255",
47
+ null,
48
+ "255,0,0","255,153,0","255,255,0","0,255,0","0,255,255","0,0,255","153,0,255","255,0,255",
49
+ null,
50
+ "244,204,204","252,229,205","255,242,204","217,234,211","208,224,227","207,226,243","217,210,233","234,209,220",
51
+ "234,153,153","249,203,156","255,229,153","182,215,168","162,196,201","159,197,232","180,167,214","213,166,189",
52
+ "224,102,102","246,178,107","255,217,102","147,196,125","118,165,175","111,168,220","142,124,195","194,123,160",
53
+ "204,0,0","230,145,56","241,194,50","106,168,79","69,129,142","61,133,198","103,78,167","166,77,121",
54
+ "153,0,0","180,95,6","191,144,0","56,118,29","19,79,92","11,83,148","53,28,117","116,27,71",
55
+ "102,0,0","120,63,4","127,96,0","39,78,19","12,52,61","7,55,99","32,18,77","76,17,48"
56
+ ];
57
+
58
+ // default link-type names
59
+ var linktypes = ["Web Address","E-mail Address","Picture URL"];
60
+
61
+ var vars = $.extend({
62
+ // options
63
+ 'status' : true,
64
+ 'css' : "jqte",
65
+ 'title' : true,
66
+ 'titletext' : varsTitle,
67
+ 'button' : "OK",
68
+ 'format' : true,
69
+ 'formats' : formats,
70
+ 'fsize' : true,
71
+ 'fsizes' : fsizes,
72
+ 'funit' : "px",
73
+ 'color' : true,
74
+ 'linktypes' : linktypes,
75
+ 'b' : true,
76
+ 'i' : true,
77
+ 'u' : true,
78
+ 'ol' : true,
79
+ 'ul' : true,
80
+ 'sub' : true,
81
+ 'sup' : true,
82
+ 'outdent' : true,
83
+ 'indent' : true,
84
+ 'left' : true,
85
+ 'center' : true,
86
+ 'right' : true,
87
+ 'strike' : true,
88
+ 'link' : true,
89
+ 'unlink' : true,
90
+ 'remove' : true,
91
+ 'rule' : true,
92
+ 'source' : true,
93
+ 'placeholder' : false,
94
+ 'br' : true,
95
+ 'p' : true,
96
+
97
+ // events
98
+ 'change' : "",
99
+ 'focus' : "",
100
+ 'blur' : ""
101
+ }, options);
102
+
103
+ // methods
104
+ $.fn.jqteVal = function(value){
105
+ $(this).closest("."+vars.css).find("."+vars.css+"_editor").html(value);
106
+ }
107
+
108
+ // browser information is received
109
+ var thisBrowser = navigator.userAgent.toLowerCase();
110
+
111
+ // if browser is ie and it version is 7 or even older, close title property
112
+ if(/msie [1-7]./.test(thisBrowser))
113
+ vars.title = false;
114
+
115
+ var buttons = [];
116
+
117
+ // insertion function for parameters to toolbar
118
+ function addParams(name,command,key,tag,emphasis)
119
+ {
120
+ var thisCssNo = buttons.length+1;
121
+ return buttons.push({name:name, cls:thisCssNo, command:command, key:key, tag:tag, emphasis:emphasis});
122
+ };
123
+
124
+ // add parameters for toolbar buttons
125
+ addParams('format','formats','','',false); // text format button --> no hotkey
126
+ addParams('fsize','fSize','','',false); // font size button --> no hotkey
127
+ addParams('color','colors','','',false); // text color button --> no hotkey
128
+ addParams('b','Bold','B',["b","strong"],true); // bold --> ctrl + b
129
+ addParams('i','Italic','I',["i","em"],true); // italic --> ctrl + i
130
+ addParams('u','Underline','U',["u"],true); // underline --> ctrl + u
131
+ addParams('ol','insertorderedlist','¾',["ol"],true); // ordered list --> ctrl + .(dot)
132
+ addParams('ul','insertunorderedlist','¼',["ul"],true); // unordered list --> ctrl + ,(comma)
133
+ addParams('sub','subscript','(',["sub"],true); // sub script --> ctrl + down arrow
134
+ addParams('sup','superscript','&',["sup"],true); // super script --> ctrl + up arrow
135
+ addParams('outdent','outdent','%',["blockquote"],false); // outdent --> ctrl + left arrow
136
+ addParams('indent','indent','\'',["blockquote"],true); // indent --> ctrl + right arrow
137
+ addParams('left','justifyLeft','','',false); // justify Left --> no hotkey
138
+ addParams('center','justifyCenter','','',false); // justify center --> no hotkey
139
+ addParams('right','justifyRight','','',false); // justify right --> no hotkey
140
+ addParams('strike','strikeThrough','K',["strike"],true); // strike through --> ctrl + K
141
+ addParams('link','linkcreator','L',["a"],true); // insertion link --> ctrl + L
142
+ addParams('unlink','unlink','',["a"],false); // remove link --> ctrl + N
143
+ addParams('remove','removeformat','.','',false); // remove all styles --> ctrl + delete
144
+ addParams('rule','inserthorizontalrule','H',["hr"],false); // insertion horizontal rule --> ctrl + H
145
+ addParams('source','displaysource','','',false); // feature of displaying source
146
+
147
+ return this.each(function(){
148
+ if(!$(this).data("jqte") || $(this).data("jqte")==null || $(this).data("jqte")=="undefined")
149
+ $(this).data("jqte",true);
150
+ else
151
+ $(this).data("jqte",false);
152
+
153
+ // is the status false of the editor
154
+ if(!vars.status || !$(this).data("jqte"))
155
+ {
156
+ // if wanting the false status later
157
+ if($(this).closest("."+vars.css).length>0)
158
+ {
159
+ var editorValue = $(this).closest("."+vars.css).find("."+vars.css+"_editor").html();
160
+
161
+ // add all attributes of element
162
+ var thisElementAttrs = "";
163
+
164
+ $($(this)[0].attributes).each(function()
165
+ {
166
+ if(this.nodeName!="style")
167
+ thisElementAttrs = thisElementAttrs+" "+this.nodeName+'="'+this.nodeValue+'"';
168
+ });
169
+
170
+ var thisElementTag = $(this).is("[data-origin]") && $(this).attr("data-origin")!="" ? $(this).attr("data-origin") : "textarea";
171
+
172
+ // the contents of this element
173
+ var createValue = '>'+editorValue;
174
+
175
+ // if this element is input or option
176
+ if(thisElementTag=="input" || thisElementTag=="option")
177
+ {
178
+ // encode special html characters
179
+ editorValue = editorValue.replace(/"/g,'&#34;').replace(/'/g,'&#39;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
180
+
181
+ // the value of this element
182
+ createValue = 'value="'+editorValue+'">';
183
+ }
184
+
185
+ var thisClone = $(this).clone();
186
+
187
+ $(this).data("jqte",false).closest("."+vars.css).before(thisClone).remove();
188
+ thisClone.replaceWith('<'+ thisElementTag + thisElementAttrs + createValue + '</'+thisElementTag+'>');
189
+ }
190
+ return;
191
+ }
192
+
193
+ // element will converted to the jqte editor
194
+ var thisElement = $(this);
195
+
196
+ // tag name of the element
197
+ var thisElementTag = $(this).prop('tagName').toLowerCase();
198
+
199
+ // tag name of origin
200
+ $(this).attr("data-origin",thisElementTag);
201
+
202
+ // contents of the element
203
+ var thisElementVal = $(this).is("[value]") || thisElementTag == "textarea" ? $(this).val() : $(this).html();
204
+
205
+ // decode special html characters
206
+ thisElementVal = thisElementVal.replace(/&#34;/g,'"').replace(/&#39;/g,"'").replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
207
+
208
+ // start jqte editor to after the element
209
+ $(this).after('<div class="'+vars.css+'"></div>');
210
+
211
+ // jqte
212
+ var jQTE = $(this).next('.'+vars.css);
213
+
214
+ // insert toolbar in jqte editor
215
+ jQTE.html('<div class="'+vars.css+"_toolbar"+'" role="toolbar" unselectable></div><div class="'+vars.css+'_linkform" style="display:none" role="dialog"></div><div class="'+vars.css+"_editor"+'"></div>');
216
+
217
+ var toolbar = jQTE.find('.'+vars.css+"_toolbar"); // the toolbar variable
218
+ var linkform = jQTE.find('.'+vars.css+"_linkform"); // the link-form-area in the toolbar variable
219
+ var editor = jQTE.find('.'+vars.css+"_editor"); // the text-field of jqte editor
220
+ var emphasize = vars.css+"_tool_depressed"; // highlight style of the toolbar buttons
221
+
222
+ // add to some tools in link form area
223
+ linkform.append('<div class="'+vars.css+'_linktypeselect" unselectable></div><input class="'+vars.css+'_linkinput" type="text/css" value=""><div class="'+vars.css+'_linkbutton" unselectable>'+vars.button+'</div> <div style="height:1px;float:none;clear:both"></div>');
224
+
225
+ var linktypeselect = linkform.find("."+vars.css+"_linktypeselect"); // the tool of link-type-selector
226
+ var linkinput = linkform.find("."+vars.css+"_linkinput"); // the input of insertion link
227
+ var linkbutton = linkform.find("."+vars.css+"_linkbutton"); // the button of insertion link
228
+
229
+ // add to the link-type-selector sub tool parts
230
+ linktypeselect.append('<div class="'+vars.css+'_linktypeview" unselectable></div><div class="'+vars.css+'_linktypes" role="menu" unselectable></div>');
231
+
232
+ var linktypes = linktypeselect.find("."+vars.css+"_linktypes"); // the select box of link types
233
+ var linktypeview = linktypeselect.find("."+vars.css+"_linktypeview"); // the link type preview
234
+ var setdatalink = vars.css+"-setlink"; // the selected text add to mark as "link will be added"
235
+
236
+ // create to the source-area
237
+ editor.after('<div class="'+vars.css+'_source '+vars.css+'_hiddenField"></div>');
238
+
239
+ var sourceField = jQTE.find("."+vars.css+"_source"); // the source-area variable
240
+
241
+ // move the element to the source-area
242
+ thisElement.appendTo(sourceField);
243
+
244
+ // if the element isn't a textarea, convert this to textarea
245
+ if(thisElementTag!="textarea")
246
+ {
247
+ // add all attributes of element to new textarea (type and value except)
248
+ var thisElementAttrs = "";
249
+
250
+ $(thisElement[0].attributes).each(function(){
251
+ if(this.nodeName!="type" && this.nodeName!="value")
252
+ thisElementAttrs = thisElementAttrs+" "+this.nodeName+'="'+this.nodeValue+'"';
253
+ });
254
+
255
+ // convert the element to textarea
256
+ thisElement.replaceWith('<textarea '+thisElementAttrs+'>'+thisElementVal+'</textarea>');
257
+
258
+ // update to variable of thisElement
259
+ thisElement = sourceField.find("textarea");
260
+ }
261
+
262
+ // add feature editable to the text-field ve copy from the element's value to text-field
263
+ editor.attr("contenteditable","true").html(thisElementVal);
264
+
265
+ // insertion the toolbar button
266
+ for(var n = 0; n < buttons.length; n++)
267
+ {
268
+ // if setting of this button is activated (is it true?)
269
+ if(vars[buttons[n].name])
270
+ {
271
+ // if it have a title, add to this button
272
+ var buttonHotkey = buttons[n].key.length>0 ? vars.titletext[n].hotkey!=null && vars.titletext[n].hotkey!="undefined" && vars.titletext[n].hotkey!="" ? ' (Ctrl+'+vars.titletext[n].hotkey+')' : '' : '';
273
+ var buttonTitle = vars.titletext[n].title!=null && vars.titletext[n].title!="undefined" && vars.titletext[n].title!="" ? vars.titletext[n].title+buttonHotkey : '';
274
+
275
+ // add this button to the toolbar
276
+ toolbar.append('<div class="'+vars.css+'_tool '+vars.css+'_tool_'+buttons[n].cls+'" role="button" data-tool="'+n+'" unselectable><a class="'+vars.css+'_tool_icon" unselectable></a></div>');
277
+
278
+ // add the parameters to this button
279
+ toolbar.find('.'+vars.css+'_tool[data-tool='+n+']').data({tag : buttons[n].tag, command : buttons[n].command, emphasis : buttons[n].emphasis, title : buttonTitle});
280
+
281
+ // format-selector field
282
+ if(buttons[n].name=="format" && $.isArray(vars.formats))
283
+ {
284
+ // selected text format
285
+ var toolLabel = vars.formats[0][1].length>0 && vars.formats[0][1]!="undefined" ? vars.formats[0][1] : "";
286
+
287
+ toolbar.find("."+vars.css+'_tool_'+buttons[n].cls).find("."+vars.css+"_tool_icon").replaceWith('<a class="'+vars.css+'_tool_label" unselectable><span class="'+vars.css+'_tool_text" unselectable>'+toolLabel+'</span><span class="'+vars.css+'_tool_icon" unselectable></span></a>');
288
+
289
+ toolbar.find("."+vars.css+'_tool_'+buttons[n].cls)
290
+ .append('<div class="'+vars.css+'_formats" unselectable></div>');
291
+
292
+ // add font-sizes to font-size-selector
293
+ for(var f = 0; f < vars.formats.length; f++)
294
+ {
295
+ toolbar.find("."+vars.css+"_formats").append('<a '+vars.css+'-formatval="'+ vars.formats[f][0] +'" class="'+vars.css+'_format'+' '+vars.css+'_format_'+f+'" role="menuitem" unselectable>'+ vars.formats[f][1] +'</a>');
296
+ }
297
+
298
+ toolbar.find("."+vars.css+"_formats").data("status",false);
299
+ }
300
+
301
+ // font-size-selector field
302
+ else if(buttons[n].name=="fsize" && $.isArray(vars.fsizes))
303
+ {
304
+ toolbar.find("."+vars.css+'_tool_'+buttons[n].cls)
305
+ .append('<div class="'+vars.css+'_fontsizes" unselectable></div>');
306
+
307
+ // add font-sizes to font-size-selector
308
+ for(var f = 0; f < vars.fsizes.length; f++)
309
+ {
310
+ toolbar.find("."+vars.css+"_fontsizes").append('<a '+vars.css+'-styleval="'+ vars.fsizes[f] +'" class="'+vars.css+'_fontsize'+'" style="font-size:'+ vars.fsizes[f] + vars.funit+'" role="menuitem" unselectable>Abcdefgh...</a>');
311
+ }
312
+ }
313
+
314
+ // color-selector field
315
+ else if(buttons[n].name=="color" && $.isArray(colors))
316
+ {
317
+ toolbar.find("."+vars.css+'_tool_'+buttons[n].cls)
318
+ .append('<div class="'+vars.css+'_cpalette" unselectable></div>');
319
+
320
+ // create color palette to color-selector field
321
+ for(var c = 0; c < colors.length; c++)
322
+ {
323
+ if(colors[c]!=null)
324
+ toolbar.find("."+vars.css+"_cpalette").append('<a '+vars.css+'-styleval="'+ colors[c] +'" class="'+vars.css+'_color'+'" style="background-color: rgb('+ colors[c] +')" role="gridcell" unselectable></a>');
325
+ else
326
+ toolbar.find("."+vars.css+"_cpalette").append('<div class="'+vars.css+"_colorSeperator"+'"></div>');
327
+ }
328
+ }
329
+ }
330
+ }
331
+
332
+ // the default value of the link-type
333
+ linktypes.data("linktype","0");
334
+
335
+ // add link types to link-type-selector
336
+ for(var n = 0; n < 3; n++)
337
+ {
338
+ linktypes.append('<a '+vars.css+'-linktype="'+n+'" unselectable>'+vars.linktypes[n]+'</a>');
339
+
340
+ linktypeview.html('<div class="'+vars.css+'_linktypearrow" unselectable></div><div class="'+vars.css+'_linktypetext">'+linktypes.find('a:eq('+linktypes.data("linktype")+')').text()+'</div>');
341
+ }
342
+
343
+ // add the prefix of css according to browser
344
+ var prefixCss = "";
345
+
346
+ if(/msie/.test(thisBrowser)) // ie
347
+ prefixCss = '-ms-';
348
+ else if(/chrome/.test(thisBrowser) || /safari/.test(thisBrowser) || /yandex/.test(thisBrowser)) // webkit group (safari, chrome, yandex)
349
+ prefixCss = '-webkit-';
350
+ else if(/mozilla/.test(thisBrowser)) // firefox
351
+ prefixCss = '-moz-';
352
+ else if(/opera/.test(thisBrowser)) // opera
353
+ prefixCss = '-o-';
354
+ else if(/konqueror/.test(thisBrowser)) // konqueror
355
+ prefixCss = '-khtml-';
356
+ else
357
+ prefixCss = '';
358
+
359
+ // the feature of placeholder
360
+ if(vars.placeholder && vars.placeholder!="")
361
+ {
362
+ jQTE.prepend('<div class="'+vars.css+'_placeholder" unselectable><div class="'+vars.css+'_placeholder_text">'+vars.placeholder+'</div></div>');
363
+
364
+ var placeHolder = jQTE.find("."+vars.css+"_placeholder");
365
+
366
+ placeHolder.click(function(){
367
+ editor.focus();
368
+ });
369
+ }
370
+
371
+ // make unselectable to unselectable attribute ones
372
+ jQTE.find("[unselectable]")
373
+ .css(prefixCss+"user-select","none")
374
+ .addClass("unselectable")
375
+ .attr("unselectable","on")
376
+ .on("selectstart mousedown",false);
377
+
378
+ // each button of the toolbar
379
+ var toolbutton = toolbar.find("."+vars.css+"_tool");
380
+
381
+ // format menu
382
+ var formatbar = toolbar.find("."+vars.css+"_formats");
383
+
384
+ // font-size filed
385
+ var fsizebar = toolbar.find("."+vars.css+"_fontsizes");
386
+
387
+ // color palette
388
+ var cpalette = toolbar.find("."+vars.css+"_cpalette");
389
+
390
+ // get the selected text as plain format
391
+ function selectionGet()
392
+ {
393
+ // for webkit, mozilla, opera
394
+ if (window.getSelection)
395
+ return window.getSelection();
396
+ // for ie
397
+ else if (document.selection && document.selection.createRange && document.selection.type != "None")
398
+ return document.selection.createRange();
399
+ }
400
+
401
+ // the function of changing to the selected text with "execCommand" method
402
+ function selectionSet(addCommand,thirdParam)
403
+ {
404
+ var range,
405
+ sel = selectionGet();
406
+
407
+ // for webkit, mozilla, opera
408
+ if (window.getSelection)
409
+ {
410
+ if (sel.anchorNode && sel.getRangeAt)
411
+ range = sel.getRangeAt(0);
412
+
413
+ if(range)
414
+ {
415
+ sel.removeAllRanges();
416
+ sel.addRange(range);
417
+ }
418
+
419
+ if(!thisBrowser.match(/msie/))
420
+ document.execCommand('StyleWithCSS', false, false);
421
+
422
+ document.execCommand(addCommand, false, thirdParam);
423
+ }
424
+
425
+ // for ie
426
+ else if (document.selection && document.selection.createRange && document.selection.type != "None")
427
+ {
428
+ range = document.selection.createRange();
429
+ range.execCommand(addCommand, false, thirdParam);
430
+ }
431
+
432
+ // change styles to around tags
433
+ affectStyleAround(false,false);
434
+ }
435
+
436
+ // the function of changing to the selected text with tags and tags's attributes
437
+ function replaceSelection(tTag,tAttr,tVal) {
438
+
439
+ // first, prevent to conflict of different jqte editors
440
+ if(editor.not(":focus"))
441
+ editor.focus();
442
+
443
+ // for webkit, mozilla, opera
444
+ if (window.getSelection)
445
+ {
446
+ var selObj = selectionGet(), selRange, newElement, documentFragment;
447
+
448
+ if (selObj.anchorNode && selObj.getRangeAt)
449
+ {
450
+ selRange = selObj.getRangeAt(0);
451
+
452
+ // create to new element
453
+ newElement = document.createElement(tTag);
454
+
455
+ // add the attribute to the new element
456
+ $(newElement).attr(tAttr,tVal);
457
+
458
+ // extract to the selected text
459
+ documentFragment = selRange.extractContents();
460
+
461
+ // add the contents to the new element
462
+ newElement.appendChild(documentFragment);
463
+
464
+ selRange.insertNode(newElement);
465
+ selObj.removeAllRanges();
466
+
467
+ // if the attribute is "style", change styles to around tags
468
+ if(tAttr=="style")
469
+ affectStyleAround($(newElement),tVal);
470
+ // for other attributes
471
+ else
472
+ affectStyleAround($(newElement),false);
473
+ }
474
+ }
475
+ // for ie
476
+ else if (document.selection && document.selection.createRange && document.selection.type != "None")
477
+ {
478
+ var range = document.selection.createRange();
479
+ var selectedText = range.htmlText;
480
+
481
+ var newText = '<'+tTag+' '+tAttr+'="'+tVal+'">'+selectedText+'</'+tTag+'>';
482
+
483
+ document.selection.createRange().pasteHTML(newText);
484
+ }
485
+ }
486
+
487
+ // the function of getting to the parent tag
488
+ var getSelectedNode = function() {
489
+ var node,selection;
490
+ if(window.getSelection) {
491
+ selection = getSelection();
492
+ node = selection.anchorNode;
493
+ }
494
+ if(!node && document.selection && document.selection.createRange && document.selection.type != "None")
495
+ {
496
+ selection = document.selection;
497
+ var range = selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange();
498
+ node = range.commonAncestorContainer ? range.commonAncestorContainer :
499
+ range.parentElement ? range.parentElement() : range.item(0);
500
+ }
501
+ if(node) {
502
+ return (node.nodeName == "#text" ? $(node.parentNode) : $(node));
503
+ }
504
+ else
505
+ return false;
506
+ };
507
+
508
+ // the function of replacement styles to the around tags (parent and child)
509
+ function affectStyleAround(element,style)
510
+ {
511
+ var selectedTag = getSelectedNode(); // the selected node
512
+
513
+ selectedTag = selectedTag ? selectedTag : element;
514
+
515
+ // (for replacement with execCommand) affect to child tags with parent tag's styles
516
+ if(selectedTag && style==false)
517
+ {
518
+ // apply to the selected node with parent tag's styles
519
+ if(selectedTag.parent().is("[style]"))
520
+ selectedTag.attr("style",selectedTag.parent().attr("style"));
521
+
522
+ // apply to child tags with parent tag's styles
523
+ if(selectedTag.is("[style]"))
524
+ selectedTag.find("*").attr("style",selectedTag.attr("style"));
525
+ }
526
+ // (for replacement with html changing method)
527
+ else if(element && style && element.is("[style]"))
528
+ {
529
+ var styleKey = style.split(";"); // split the styles
530
+
531
+ styleKey = styleKey[0].split(":") // get the key of first style feature
532
+
533
+ // apply to child tags with parent tag's styles
534
+ if(element.is("[style*="+styleKey[0]+"]"))
535
+ element.find("*").css(styleKey[0],styleKey[1]);
536
+
537
+ // select to the selected node again
538
+ selectText(element);
539
+ }
540
+ }
541
+
542
+ // the function of making selected to a element
543
+ function selectText(element)
544
+ {
545
+ if(element)
546
+ {
547
+ var element = element[0];
548
+
549
+ if (document.body.createTextRange)
550
+ {
551
+ var range = document.body.createTextRange();
552
+ range.moveToElementText(element);
553
+ range.select();
554
+ }
555
+ else if (window.getSelection)
556
+ {
557
+ var selection = window.getSelection();
558
+ var range = document.createRange();
559
+
560
+ if(element != "undefined" && element != null)
561
+ {
562
+ range.selectNodeContents(element);
563
+
564
+ selection.removeAllRanges();
565
+ selection.addRange(range);
566
+
567
+ if($(element).is(":empty"))
568
+ {
569
+ $(element).append("&nbsp;");
570
+ selectText($(element));
571
+ }
572
+ }
573
+ }
574
+ }
575
+ }
576
+
577
+ // the function of converting text to link
578
+ function selected2link()
579
+ {
580
+ if(!toolbar.data("sourceOpened"))
581
+ {
582
+ var selectedTag = getSelectedNode(); // the selected node
583
+ var thisHrefLink = "http://"; // default the input value of the link-form-field
584
+
585
+ // display the link-form-field
586
+ linkAreaSwitch(true);
587
+
588
+ if(selectedTag)
589
+ {
590
+
591
+ var thisTagName = selectedTag.prop('tagName').toLowerCase();
592
+
593
+ // if tag name of the selected node is "a" and the selected node have "href" attribute
594
+ if(thisTagName == "a" && selectedTag.is('[href]'))
595
+ {
596
+ thisHrefLink = selectedTag.attr('href');
597
+
598
+ selectedTag.attr(setdatalink,"");
599
+ }
600
+ // if it don't have "a" tag name
601
+ else
602
+ replaceSelection("a",setdatalink,"");
603
+
604
+ }
605
+ else
606
+ linkinput.val(thisHrefLink).focus();
607
+
608
+ // the method of displaying-hiding to link-types
609
+ linktypeselect.click(function(e)
610
+ {
611
+ if($(e.target).hasClass(vars.css+"_linktypetext") || $(e.target).hasClass(vars.css+"_linktypearrow"))
612
+ linktypeSwitch(true);
613
+ });
614
+
615
+ // the method of selecting to link-types
616
+ linktypes.find("a").click(function()
617
+ {
618
+ var thisLinkType = $(this).attr(vars.css+"-linktype");
619
+
620
+ linktypes.data("linktype",thisLinkType)
621
+
622
+ linktypeview.find("."+vars.css+"_linktypetext").html(linktypes.find('a:eq('+linktypes.data("linktype")+')').text());
623
+
624
+ linkInputSet(thisHrefLink);
625
+
626
+ linktypeSwitch();
627
+ });
628
+
629
+ linkInputSet(thisHrefLink);
630
+
631
+ // the method of link-input
632
+ linkinput
633
+ // auto focus
634
+ .focus()
635
+ // update to value
636
+ .val(thisHrefLink)
637
+ // the event of key to enter in link-input
638
+ .bind("keypress keyup",function(e)
639
+ {
640
+ if(e.keyCode==13)
641
+ {
642
+ linkRecord(jQTE.find("["+setdatalink+"]"));
643
+ return false;
644
+ }
645
+ });
646
+
647
+ // the event of click link-button
648
+ linkbutton.click(function()
649
+ {
650
+ linkRecord(jQTE.find("["+setdatalink+"]"));
651
+ });
652
+ }
653
+ else
654
+ // hide the link-form-field
655
+ linkAreaSwitch(false);
656
+ }
657
+
658
+ function linkRecord(thisSelection)
659
+ {
660
+ // focus to link-input
661
+ linkinput.focus();
662
+
663
+ // select to the selected node
664
+ selectText(thisSelection);
665
+
666
+ // remove pre-link attribute (mark as "link will be added") of the selected node
667
+ thisSelection.removeAttr(setdatalink);
668
+
669
+ // if not selected to link-type of picture
670
+ if(linktypes.data("linktype")!="2")
671
+ selectionSet("createlink",linkinput.val()); // insert link url of link-input to the selected node
672
+ // if selected to link-type of picture
673
+ else
674
+ {
675
+ selectionSet("insertImage",linkinput.val()); // insert image url of link-input to the selected node
676
+
677
+ // the method of all pictures in the editor
678
+ editor.find("img").each(function(){
679
+ var emptyPrevLinks = $(this).prev("a");
680
+ var emptyNextLinks = $(this).next("a");
681
+
682
+ // if "a" tags of the front and rear of the picture is empty, remove
683
+ if(emptyPrevLinks.length>0 && emptyPrevLinks.html()=="")
684
+ emptyPrevLinks.remove();
685
+ else if(emptyNextLinks.length>0 && emptyNextLinks.html()=="")
686
+ emptyNextLinks.remove();
687
+ });
688
+ }
689
+
690
+ // hide the link-form-field
691
+ linkAreaSwitch();
692
+
693
+ // export contents of the text to the sources
694
+ editor.trigger("change");
695
+ }
696
+
697
+ // the function of switching link-form-field
698
+ function linkAreaSwitch(status)
699
+ {
700
+ // remove all pre-link attribute (mark as "link will be added")
701
+ clearSetElement("["+setdatalink+"]:not([href])");
702
+ jQTE.find("["+setdatalink+"][href]").removeAttr(setdatalink);
703
+
704
+ if(status)
705
+ {
706
+ toolbar.data("linkOpened",true);
707
+ linkform.show();
708
+ }
709
+ else
710
+ {
711
+ toolbar.data("linkOpened",false);
712
+ linkform.hide();
713
+ }
714
+
715
+ linktypeSwitch();
716
+ }
717
+
718
+ // the function of switching link-type-selector
719
+ function linktypeSwitch(status)
720
+ {
721
+ if(status)
722
+ linktypes.show();
723
+ else
724
+ linktypes.hide();
725
+ }
726
+
727
+ // the function of updating the link-input according to the link-type
728
+ function linkInputSet(thisHrefLink)
729
+ {
730
+ var currentType = linktypes.data("linktype");
731
+
732
+ // if selected type of e-mail
733
+ if(currentType=="1" && (linkinput.val()=="http://" || linkinput.is("[value^=http://]") || !linkinput.is("[value^=mailto]")))
734
+ linkinput.val("mailto:");
735
+ else if(currentType!="1" && !linkinput.is("[value^=http://]"))
736
+ linkinput.val("http://");
737
+ else
738
+ linkinput.val(thisHrefLink);
739
+ }
740
+
741
+ // the function of adding style to selected text
742
+ function selected2style(styleCommand)
743
+ {
744
+ if(!toolbar.data("sourceOpened"))
745
+ {
746
+
747
+ // if selected to changing the font-size value
748
+ if(styleCommand=="fSize")
749
+ styleField = fsizebar;
750
+
751
+ // if selected to changing the text-color value
752
+ else if(styleCommand=="colors")
753
+ styleField = cpalette;
754
+
755
+ // display the style-field
756
+ styleFieldSwitch(styleField,true);
757
+
758
+ // the event of click to style button
759
+ styleField.find("a").unbind("click").click(function()
760
+ {
761
+ var styleValue = $(this).attr(vars.css + "-styleval"); // the property of style value to be added
762
+
763
+ // if selected to changing the font-size value
764
+ if(styleCommand=="fSize")
765
+ {
766
+ styleType = "font-size";
767
+ styleValue = styleValue + vars.funit; // combine the value with size unit
768
+ }
769
+ // if selected to changing the text-color value
770
+ else if(styleCommand=="colors")
771
+ {
772
+ styleType = "color";
773
+ styleValue = "rgb("+styleValue + ")"; // combine color value with rgb
774
+ }
775
+
776
+ var prevStyles = refuseStyle(styleType); // affect styles to child tags (and extract to the new style attributes)
777
+
778
+ // change to selected text
779
+ replaceSelection("span","style",styleType+":"+styleValue+";"+prevStyles);
780
+
781
+ // hide all style-fields
782
+ styleFieldSwitch("",false);
783
+
784
+ // remove title bubbles
785
+ $('.'+vars.css+'_title').remove();
786
+
787
+ // export contents of the text to the sources
788
+ editor.trigger("change");
789
+ });
790
+
791
+ }
792
+ else
793
+ // hide the style-field
794
+ styleFieldSwitch(styleField,false);
795
+
796
+ // hide the link-form-field
797
+ linkAreaSwitch(false);
798
+ }
799
+
800
+ // the function of switching the style-field
801
+ function styleFieldSwitch(styleField,status)
802
+ {
803
+ var mainData="", // the style data of the actual wanted
804
+ allData = [{"d":"fsizeOpened","f":fsizebar},{"d":"cpallOpened","f":cpalette}]; // all style datas
805
+
806
+ // if the style data of the actual wanted isn't empty
807
+ if(styleField!="")
808
+ {
809
+ // return to all datas and find the main data
810
+ for(var si=0; si < allData.length; si++)
811
+ {
812
+ if(styleField==allData[si]["f"])
813
+ mainData = allData[si];
814
+ }
815
+ }
816
+ // display the style-field
817
+ if(status)
818
+ {
819
+ toolbar.data(mainData["d"],true); // stil seçme alanının açıldığını belirten parametre yaz
820
+ mainData["f"].slideDown(100); // stil seçme alanını aç
821
+
822
+ // return to all datas and close the fields of external datas
823
+ for(var si=0; si < allData.length; si++)
824
+ {
825
+ if(mainData["d"]!=allData[si]["d"])
826
+ {
827
+ toolbar.data(allData[si]["d"],false);
828
+ allData[si]["f"].slideUp(100);
829
+ }
830
+ }
831
+ }
832
+ // hide all style-fields
833
+ else
834
+ {
835
+ // return to all datas and close all style fields
836
+ for(var si=0; si < allData.length; si++)
837
+ {
838
+ toolbar.data(allData[si]["d"],false);
839
+ allData[si]["f"].slideUp(100);
840
+ }
841
+ }
842
+ }
843
+
844
+ // the function of removing all pre-link attribute (mark as "link will be added")
845
+ function clearSetElement(elem)
846
+ {
847
+ jQTE.find(elem).each(function(){
848
+ $(this).before($(this).html()).remove();
849
+ });
850
+ }
851
+
852
+ // the function of refusing some styles
853
+ function refuseStyle(refStyle)
854
+ {
855
+ var selectedTag = getSelectedNode(); // the selected node
856
+
857
+ // if the selected node have attribute of "style" and it have unwanted style
858
+ if(selectedTag && selectedTag.is("[style]") && selectedTag.css(refStyle)!="")
859
+ {
860
+ var refValue = selectedTag.css(refStyle); // first get key of unwanted style
861
+
862
+ selectedTag.css(refStyle,""); // clear unwanted style
863
+
864
+ var cleanStyle = selectedTag.attr("style"); // cleaned style
865
+
866
+ selectedTag.css(refStyle,refValue); // add unwanted style to the selected node again
867
+
868
+ return cleanStyle; // print cleaned style
869
+ }
870
+ else
871
+ return "";
872
+ }
873
+
874
+ // the function of adding style to selected text
875
+ function selected2format()
876
+ {
877
+ formatFieldSwitch(true);
878
+
879
+ formatbar.find("a").click(function()
880
+ {
881
+ $("*",this).click(function(e)
882
+ {
883
+ e.preventDefault();
884
+ return false;
885
+ });
886
+
887
+ formatLabelView($(this).text());
888
+
889
+ var formatValue = $(this).attr(vars.css + "-formatval"); // the type of format value
890
+
891
+ // convert to selected format
892
+ selectionSet("formatBlock",'<'+formatValue+'>');
893
+
894
+ formatFieldSwitch(false);
895
+ });
896
+ }
897
+
898
+ // the function of switching the style-field
899
+ function formatFieldSwitch(status)
900
+ {
901
+ var thisStatus = status ? true : false;
902
+
903
+ thisStatus = status && formatbar.data("status") ? true : false;
904
+
905
+ if(thisStatus || !status)
906
+ formatbar.data("status",false).slideUp(200);
907
+ else
908
+ formatbar.data("status",true).slideDown(200);
909
+ }
910
+
911
+ // change format label
912
+ function formatLabelView(str)
913
+ {
914
+ var formatLabel = formatbar.closest("."+vars.css+"_tool").find("."+vars.css+"_tool_label").find("."+vars.css+"_tool_text");
915
+
916
+ if(str.length > 10)
917
+ str = str.substr(0,7) + "...";
918
+
919
+ // change format label of button
920
+ formatLabel.html(str);
921
+ }
922
+
923
+ // the function of insertion a specific form to texts
924
+ function extractToText(strings)
925
+ {
926
+ var $htmlContent, $htmlPattern, $htmlReplace;
927
+
928
+ // first remove to unnecessary gaps
929
+ $htmlContent = strings.replace(/\n/gim,'').replace(/\r/gim,'').replace(/\t/gim,'').replace(/&nbsp;/gim,' ');
930
+
931
+ $htmlPattern = [
932
+ /\<span(|\s+.*?)><span(|\s+.*?)>(.*?)<\/span><\/span>/gim, // trim nested spans
933
+ /<(\w*[^p])\s*[^\/>]*>\s*<\/\1>/gim, // remove empty or white-spaces tags (ignore paragraphs (<p>) and breaks (<br>))
934
+ /\<div(|\s+.*?)>(.*?)\<\/div>/gim, // convert div to p
935
+ /\<strong(|\s+.*?)>(.*?)\<\/strong>/gim, // convert strong to b
936
+ /\<em(|\s+.*?)>(.*?)\<\/em>/gim // convert em to i
937
+ ];
938
+
939
+ $htmlReplace = [
940
+ '<span$2>$3</span>',
941
+ '',
942
+ '<p$1>$2</p>',
943
+ '<b$1>$2</b>',
944
+ '<i$1>$2</i>'
945
+ ];
946
+
947
+ // repeat the cleaning process 5 times
948
+ for(c=0; c<5; c++)
949
+ {
950
+ // create loop as the number of pattern
951
+ for(var i = 0; i < $htmlPattern.length; i++)
952
+ {
953
+ $htmlContent = $htmlContent.replace($htmlPattern[i], $htmlReplace[i]);
954
+ }
955
+ }
956
+
957
+ // if paragraph is false (<p>), convert <p> to <br>
958
+ if(!vars.p)
959
+ $htmlContent = $htmlContent.replace(/\<p(|\s+.*?)>(.*?)\<\/p>/ig, '<br/>$2');
960
+
961
+ // if break is false (<br>), convert <br> to <p>
962
+ if(!vars.br)
963
+ {
964
+ $htmlPattern = [
965
+ /\<br>(.*?)/ig,
966
+ /\<br\/>(.*?)/ig
967
+ ];
968
+
969
+ $htmlReplace = [
970
+ '<p>$1</p>',
971
+ '<p>$1</p>'
972
+ ];
973
+
974
+ // create loop as the number of pattern (for breaks)
975
+ for (var i = 0; i < $htmlPattern.length; i++) {
976
+ $htmlContent = $htmlContent.replace($htmlPattern[i], $htmlReplace[i]);
977
+ }
978
+ }
979
+
980
+ // if paragraph and break is false (<p> && <br>), convert <p> to <div>
981
+ if(!vars.p && !vars.br)
982
+ $htmlContent = $htmlContent.replace(/\<p>(.*?)\<\/p>/ig, '<div>$1</div>');
983
+
984
+ return $htmlContent;
985
+ }
986
+
987
+ // the function of exporting contents of the text field to the source field (to be the standard in all browsers)
988
+ function postToSource()
989
+ {
990
+ // clear unnecessary tags when editor view empty
991
+ var sourceStrings = editor.text()=="" && editor.html().length<12 ? "" : editor.html();
992
+
993
+ thisElement.val(extractToText(sourceStrings));
994
+ }
995
+
996
+ // the function of exporting contents of the source field to the text field (to be the standard in all browsers)
997
+ function postToEditor()
998
+ {
999
+ editor.html(extractToText(thisElement.val()));
1000
+ }
1001
+
1002
+ // the function of getting parent (or super parent) tag name of the selected node
1003
+ function detectElement(tags){
1004
+
1005
+ var resultdetect=false, $node = getSelectedNode(), parentsTag;
1006
+
1007
+ if($node)
1008
+ {
1009
+ $.each(tags, function(i, val){
1010
+ parentsTag = $node.prop('tagName').toLowerCase();
1011
+
1012
+ if (parentsTag == val)
1013
+ resultdetect = true;
1014
+ else
1015
+ {
1016
+ $node.parents().each(function(){
1017
+ parentsTag = $(this).prop('tagName').toLowerCase();
1018
+ if (parentsTag == val)
1019
+ resultdetect = true;
1020
+ });
1021
+ }
1022
+ });
1023
+
1024
+ return resultdetect;
1025
+ }
1026
+ else
1027
+ return false;
1028
+ };
1029
+
1030
+ // the function of highlighting the toolbar buttons according to the cursor position in jqte editor
1031
+ function buttonEmphasize(e)
1032
+ {
1033
+ for(var n = 0; n < buttons.length; n++)
1034
+ {
1035
+ if(vars[buttons[n].name] && buttons[n].emphasis && buttons[n].tag!='')
1036
+ detectElement(buttons[n].tag) ? toolbar.find('.'+vars.css+'_tool_'+buttons[n].cls).addClass(emphasize) : $('.'+vars.css+'_tool_'+buttons[n].cls).removeClass(emphasize);
1037
+ }
1038
+ // showing text format
1039
+ if(vars.format && $.isArray(vars.formats))
1040
+ {
1041
+ var isFoundFormat = false;
1042
+
1043
+ for(var f = 0; f < vars.formats.length; f++)
1044
+ {
1045
+ var thisFormat = [];
1046
+ thisFormat[0] = vars.formats[f][0];
1047
+
1048
+ if(vars.formats[f][0].length>0 && detectElement(thisFormat))
1049
+ {
1050
+ formatLabelView(vars.formats[f][1]);
1051
+
1052
+ isFoundFormat = true;
1053
+ break;
1054
+ }
1055
+ }
1056
+
1057
+ if(!isFoundFormat)
1058
+ formatLabelView(vars.formats[0][1]);
1059
+ }
1060
+
1061
+ // hide all style-fields
1062
+ styleFieldSwitch("",false);
1063
+ formatFieldSwitch(false);
1064
+ }
1065
+
1066
+ // the event of click to the toolbar buttons
1067
+ toolbutton
1068
+ .unbind("click")
1069
+ .click(function(e){
1070
+ // if source button is clicked
1071
+ if($(this).data('command')=='displaysource' && !toolbar.data("sourceOpened"))
1072
+ {
1073
+ // hide all the toolbar buttons (except the source button)
1074
+ toolbar.find("."+vars.css+"_tool").addClass(vars.css+"_hiddenField");
1075
+ $(this).removeClass(vars.css+"_hiddenField");
1076
+
1077
+ // update to data of source displaying
1078
+ toolbar.data("sourceOpened",true);
1079
+
1080
+ // equalize height of the text field with height of the source field
1081
+ thisElement.css("height",editor.outerHeight());
1082
+
1083
+ sourceField.removeClass(vars.css+"_hiddenField");
1084
+ editor.addClass(vars.css+"_hiddenField");
1085
+ thisElement.focus();
1086
+
1087
+ // hide the link-form-field
1088
+ linkAreaSwitch(false);
1089
+
1090
+ // hide all style-fields
1091
+ styleFieldSwitch("",false);
1092
+
1093
+ // hide format field
1094
+ formatFieldSwitch();
1095
+
1096
+ // hide placeholder
1097
+ if(vars.placeholder && vars.placeholder!="")
1098
+ placeHolder.hide();
1099
+ }
1100
+ // if other buttons is clicked
1101
+ else
1102
+ {
1103
+ // if source field is closed
1104
+ if(!toolbar.data("sourceOpened"))
1105
+ {
1106
+ // if insert-link-button is clicked
1107
+ if($(this).data('command')=='linkcreator')
1108
+ {
1109
+ if(!toolbar.data("linkOpened"))
1110
+ selected2link();
1111
+ else
1112
+ {
1113
+ // hide the link-form-field
1114
+ linkAreaSwitch(false);
1115
+
1116
+ // hide format field
1117
+ formatFieldSwitch(false);
1118
+ }
1119
+ }
1120
+
1121
+ // if the format button is clicked
1122
+ else if($(this).data('command')=='formats')
1123
+ {
1124
+ if($(this).data('command')=='formats' && !$(e.target).hasClass(vars.css+"_format"))
1125
+ selected2format();
1126
+
1127
+ // hide all style-fields
1128
+ styleFieldSwitch("",false);
1129
+
1130
+ if(editor.not(":focus"))
1131
+ editor.focus();
1132
+ }
1133
+
1134
+ // if the style buttons are clicked
1135
+ else if($(this).data('command')=='fSize' || $(this).data('command')=='colors')
1136
+ {
1137
+ if(
1138
+ ($(this).data('command')=='fSize' && !$(e.target).hasClass(vars.css+"_fontsize")) || // the font-size button
1139
+ ($(this).data('command')=='colors' && !$(e.target).hasClass(vars.css+"_color")) // the color button
1140
+ )
1141
+ selected2style($(this).data('command'));
1142
+
1143
+ // hide format field
1144
+ formatFieldSwitch(false);
1145
+
1146
+ if(editor.not(":focus"))
1147
+ editor.focus();
1148
+ }
1149
+
1150
+ // if other buttons is clicked
1151
+ else
1152
+ {
1153
+ // first, prevent to conflict of different jqte editors
1154
+ if(editor.not(":focus"))
1155
+ editor.focus();
1156
+
1157
+ // apply command of clicked button to the selected text
1158
+ selectionSet($(this).data('command'),null);
1159
+
1160
+ // hide all menu-fields
1161
+ styleFieldSwitch("",false);
1162
+ formatFieldSwitch(false);
1163
+ linktypeSwitch();
1164
+
1165
+ // to highlight the toolbar buttons according to the cursor position in jqte editor
1166
+ $(this).data('emphasis')==true && !$(this).hasClass(emphasize) ? $(this).addClass(emphasize) : $(this).removeClass(emphasize);
1167
+
1168
+ sourceField.addClass(vars.css+"_hiddenField");
1169
+ editor.removeClass(vars.css+"_hiddenField");
1170
+ }
1171
+
1172
+ }
1173
+ // hide the source field and display the text field
1174
+ else
1175
+ {
1176
+ // update to data of source hiding
1177
+ toolbar.data("sourceOpened",false);
1178
+
1179
+ // display all the toolbar buttons
1180
+ toolbar.find("."+vars.css+"_tool").removeClass(vars.css+"_hiddenField");
1181
+
1182
+ sourceField.addClass(vars.css+"_hiddenField");
1183
+ editor.removeClass(vars.css+"_hiddenField");
1184
+ }
1185
+
1186
+ if(vars.placeholder && vars.placeholder!="")
1187
+ editor.html()!="" ? placeHolder.hide() : placeHolder.show();
1188
+ }
1189
+
1190
+ // export contents of the text to the sources
1191
+ editor.trigger("change");
1192
+ })
1193
+ // the event of showing to the title bubble when mouse over of the toolbar buttons
1194
+ .hover(function(e){
1195
+ if(vars.title && $(this).data("title")!="" && ( $(e.target).hasClass(vars.css+"_tool") || $(e.target).hasClass(vars.css+"_tool_icon") ))
1196
+ {
1197
+ $('.'+vars.css+'_title').remove();
1198
+
1199
+ // create the title bubble
1200
+ jQTE.append('<div class="'+vars.css+'_title"><div class="'+vars.css+'_titleArrow"><div class="'+vars.css+'_titleArrowIcon"></div></div><div class="'+vars.css+'_titleText">'+$(this).data("title")+'</div></div>');
1201
+
1202
+ var thisTitle = $('.'+vars.css+'_title:first');
1203
+ var thisArrow = thisTitle.find('.'+vars.css+'_titleArrowIcon');
1204
+ var thisPosition = $(this).position();
1205
+ var thisAlignX = thisPosition.left + $(this).outerWidth() - (thisTitle.outerWidth()/2) - ($(this).outerWidth()/2);
1206
+ var thisAlignY = (thisPosition.top + $(this).outerHeight() + 5);
1207
+
1208
+ // show the title bubble and set to its position
1209
+ thisTitle.delay(400).css({'top':thisAlignY, 'left':thisAlignX}).fadeIn(200);
1210
+ }
1211
+ },function(){
1212
+ $('.'+vars.css+'_title').remove();
1213
+ });
1214
+
1215
+ // prevent multiple calling postToSource()
1216
+ var editorChangeTimer = null;
1217
+
1218
+ // the methods of the text fields
1219
+ editor
1220
+
1221
+ // trigger change method of the text field when the text field modified
1222
+ .bind("keypress keyup keydown drop cut copy paste DOMCharacterDataModified DOMSubtreeModified",function()
1223
+ {
1224
+ // export contents of the text to the sources
1225
+ if(!toolbar.data("sourceOpened"))
1226
+ $(this).trigger("change");
1227
+
1228
+ // hide the link-type-field
1229
+ linktypeSwitch();
1230
+
1231
+ // if the change method is added run the change method
1232
+ if($.isFunction(vars.change))
1233
+ vars.change();
1234
+
1235
+ // the feature of placeholder
1236
+ if(vars.placeholder && vars.placeholder!="")
1237
+ $(this).text()!="" ? placeHolder.hide() : placeHolder.show();
1238
+ })
1239
+ .bind("change",function()
1240
+ {
1241
+ if(!toolbar.data("sourceOpened"))
1242
+ {
1243
+ clearTimeout(editorChangeTimer);
1244
+ editorChangeTimer = setTimeout(postToSource,10);
1245
+ }
1246
+ })
1247
+
1248
+ // run to keyboard shortcuts
1249
+ .keydown(function(e)
1250
+ {
1251
+ // if ctrl key is clicked
1252
+ if(e.ctrlKey)
1253
+ {
1254
+ // check all toolbar buttons
1255
+ for(var n = 0; n < buttons.length; n++)
1256
+ {
1257
+ // if this settings of this button is activated (is it true)
1258
+ // if the keyed button with ctrl is same of hotkey of this button
1259
+ if(vars[buttons[n].name] && e.keyCode == buttons[n].key.charCodeAt(0))
1260
+ {
1261
+ if(buttons[n].command!='' && buttons[n].command!='linkcreator')
1262
+ selectionSet(buttons[n].command,null);
1263
+
1264
+ else if(buttons[n].command=='linkcreator')
1265
+ selected2link();
1266
+
1267
+ return false;
1268
+ }
1269
+ }
1270
+ }
1271
+ })
1272
+
1273
+ // method of triggering to the highlight button
1274
+ .bind("mouseup keyup",buttonEmphasize)
1275
+
1276
+ // the event of focus to the text field
1277
+ .focus(function()
1278
+ {
1279
+ // if the focus method is added run the focus method
1280
+ if($.isFunction(vars.focus))
1281
+ vars.focus();
1282
+
1283
+ // add onfocus class
1284
+ jQTE.addClass(vars.css+"_focused");
1285
+
1286
+ // prevent focus problem on opera
1287
+ if(/opera/.test(thisBrowser))
1288
+ {
1289
+ var range = document.createRange();
1290
+ range.selectNodeContents(editor[0]);
1291
+ range.collapse(false);
1292
+ var selection = window.getSelection();
1293
+ selection.removeAllRanges();
1294
+ selection.addRange(range);
1295
+ }
1296
+ })
1297
+
1298
+ // the event of focus out from the text field
1299
+ .focusout(function()
1300
+ {
1301
+ // remove to highlights of all toolbar buttons
1302
+ toolbutton.removeClass(emphasize);
1303
+
1304
+ // hide all menu-fields
1305
+ styleFieldSwitch("",false);
1306
+ formatFieldSwitch(false);
1307
+ linktypeSwitch();
1308
+
1309
+ // if the blur method is added run the blur method
1310
+ if($.isFunction(vars.blur))
1311
+ vars.blur();
1312
+
1313
+ // remove onfocus class
1314
+ jQTE.removeClass(vars.css+"_focused");
1315
+
1316
+ // show default text format
1317
+ if($.isArray(vars.formats))
1318
+ formatLabelView(vars.formats[0][1]);
1319
+ });
1320
+
1321
+ // the event of key in the source field
1322
+ thisElement
1323
+ .bind("keydown keyup",function()
1324
+ {
1325
+ // export contents of the source to the text field
1326
+ setTimeout(postToEditor,0);
1327
+
1328
+ // auto extension for the source field
1329
+ $(this).height($(this)[0].scrollHeight);
1330
+
1331
+ // if the source field is empty, shorten to the source field
1332
+ if($(this).val()=="")
1333
+ $(this).height(0);
1334
+ })
1335
+ .focus(function()
1336
+ {
1337
+ // add onfocus class
1338
+ jQTE.addClass(vars.css+"_focused");
1339
+ })
1340
+ .focusout(function()
1341
+ {
1342
+ // remove onfocus class
1343
+ jQTE.removeClass(vars.css+"_focused");
1344
+ });
1345
+ });
1346
+ };
1347
+ })(jQuery);
includes/controls/assets/js/uncompressed/jQuery-TE/license/AUTHOR.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ AUTHOR
2
+
3
+ jQuery TE 1.4.0 , http://jqueryte.com/
4
+ Copyright (C) 2013, Fatih Koca (fattih@fattih.com), (http://jqueryte.com/about)
5
+
6
+ jQuery TE is provided under the MIT LICENSE.
includes/controls/assets/js/uncompressed/jQuery-TE/license/MIT-LICENSE.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ Copyright (C) 2013 jQueryTE, Fatih Koca (fattih@fattih.com), http://jqueryte.com/license.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (jQueryTE), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED"AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
includes/controls/assets/js/uncompressed/jQuery-chosen/LICENSE.md ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #### Chosen
2
+ - by Patrick Filler for [Harvest](http://getharvest.com)
3
+ - Copyright (c) 2011-2016 by Harvest
4
+
5
+ Available for use under the [MIT License](http://en.wikipedia.org/wiki/MIT_License)
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in
15
+ all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ THE SOFTWARE.
includes/controls/assets/js/uncompressed/jQuery-chosen/chosen.jquery.js ADDED
@@ -0,0 +1,1349 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ Chosen, a Select Box Enhancer for jQuery and Prototype
3
+ by Patrick Filler for Harvest, http://getharvest.com
4
+
5
+ Version 1.8.2
6
+ Full source at https://github.com/harvesthq/chosen
7
+ Copyright (c) 2011-2017 Harvest http://getharvest.com
8
+
9
+ MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
10
+ This file is generated by `grunt build`, do not edit it by hand.
11
+ */
12
+
13
+ (function() {
14
+ var $, AbstractChosen, Chosen, SelectParser,
15
+ bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
16
+ extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
17
+ hasProp = {}.hasOwnProperty;
18
+
19
+ SelectParser = (function() {
20
+ function SelectParser() {
21
+ this.options_index = 0;
22
+ this.parsed = [];
23
+ }
24
+
25
+ SelectParser.prototype.add_node = function(child) {
26
+ if (child.nodeName.toUpperCase() === "OPTGROUP") {
27
+ return this.add_group(child);
28
+ } else {
29
+ return this.add_option(child);
30
+ }
31
+ };
32
+
33
+ SelectParser.prototype.add_group = function(group) {
34
+ var group_position, i, len, option, ref, results1;
35
+ group_position = this.parsed.length;
36
+ this.parsed.push({
37
+ array_index: group_position,
38
+ group: true,
39
+ label: group.label,
40
+ title: group.title ? group.title : void 0,
41
+ children: 0,
42
+ disabled: group.disabled,
43
+ classes: group.className
44
+ });
45
+ ref = group.childNodes;
46
+ results1 = [];
47
+ for (i = 0, len = ref.length; i < len; i++) {
48
+ option = ref[i];
49
+ results1.push(this.add_option(option, group_position, group.disabled));
50
+ }
51
+ return results1;
52
+ };
53
+
54
+ SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
55
+ if (option.nodeName.toUpperCase() === "OPTION") {
56
+ if (option.text !== "") {
57
+ if (group_position != null) {
58
+ this.parsed[group_position].children += 1;
59
+ }
60
+ this.parsed.push({
61
+ array_index: this.parsed.length,
62
+ options_index: this.options_index,
63
+ value: option.value,
64
+ text: option.text,
65
+ html: option.innerHTML,
66
+ title: option.title ? option.title : void 0,
67
+ selected: option.selected,
68
+ disabled: group_disabled === true ? group_disabled : option.disabled,
69
+ group_array_index: group_position,
70
+ group_label: group_position != null ? this.parsed[group_position].label : null,
71
+ classes: option.className,
72
+ style: option.style.cssText
73
+ });
74
+ } else {
75
+ this.parsed.push({
76
+ array_index: this.parsed.length,
77
+ options_index: this.options_index,
78
+ empty: true
79
+ });
80
+ }
81
+ return this.options_index += 1;
82
+ }
83
+ };
84
+
85
+ return SelectParser;
86
+
87
+ })();
88
+
89
+ SelectParser.select_to_array = function(select) {
90
+ var child, i, len, parser, ref;
91
+ parser = new SelectParser();
92
+ ref = select.childNodes;
93
+ for (i = 0, len = ref.length; i < len; i++) {
94
+ child = ref[i];
95
+ parser.add_node(child);
96
+ }
97
+ return parser.parsed;
98
+ };
99
+
100
+ AbstractChosen = (function() {
101
+ function AbstractChosen(form_field, options1) {
102
+ this.form_field = form_field;
103
+ this.options = options1 != null ? options1 : {};
104
+ this.label_click_handler = bind(this.label_click_handler, this);
105
+ if (!AbstractChosen.browser_is_supported()) {
106
+ return;
107
+ }
108
+ this.is_multiple = this.form_field.multiple;
109
+ this.set_default_text();
110
+ this.set_default_values();
111
+ this.setup();
112
+ this.set_up_html();
113
+ this.register_observers();
114
+ this.on_ready();
115
+ }
116
+
117
+ AbstractChosen.prototype.set_default_values = function() {
118
+ this.click_test_action = (function(_this) {
119
+ return function(evt) {
120
+ return _this.test_active_click(evt);
121
+ };
122
+ })(this);
123
+ this.activate_action = (function(_this) {
124
+ return function(evt) {
125
+ return _this.activate_field(evt);
126
+ };
127
+ })(this);
128
+ this.active_field = false;
129
+ this.mouse_on_container = false;
130
+ this.results_showing = false;
131
+ this.result_highlighted = null;
132
+ this.is_rtl = this.options.rtl || /\bchosen-rtl\b/.test(this.form_field.className);
133
+ this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
134
+ this.disable_search_threshold = this.options.disable_search_threshold || 0;
135
+ this.disable_search = this.options.disable_search || false;
136
+ this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
137
+ this.group_search = this.options.group_search != null ? this.options.group_search : true;
138
+ this.search_contains = this.options.search_contains || false;
139
+ this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true;
140
+ this.max_selected_options = this.options.max_selected_options || Infinity;
141
+ this.inherit_select_classes = this.options.inherit_select_classes || false;
142
+ this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true;
143
+ this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true;
144
+ this.include_group_label_in_selected = this.options.include_group_label_in_selected || false;
145
+ this.max_shown_results = this.options.max_shown_results || Number.POSITIVE_INFINITY;
146
+ this.case_sensitive_search = this.options.case_sensitive_search || false;
147
+ return this.hide_results_on_select = this.options.hide_results_on_select != null ? this.options.hide_results_on_select : true;
148
+ };
149
+
150
+ AbstractChosen.prototype.set_default_text = function() {
151
+ if (this.form_field.getAttribute("data-placeholder")) {
152
+ this.default_text = this.form_field.getAttribute("data-placeholder");
153
+ } else if (this.is_multiple) {
154
+ this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
155
+ } else {
156
+ this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
157
+ }
158
+ this.default_text = this.escape_html(this.default_text);
159
+ return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
160
+ };
161
+
162
+ AbstractChosen.prototype.choice_label = function(item) {
163
+ if (this.include_group_label_in_selected && (item.group_label != null)) {
164
+ return "<b class='group-name'>" + item.group_label + "</b>" + item.html;
165
+ } else {
166
+ return item.html;
167
+ }
168
+ };
169
+
170
+ AbstractChosen.prototype.mouse_enter = function() {
171
+ return this.mouse_on_container = true;
172
+ };
173
+
174
+ AbstractChosen.prototype.mouse_leave = function() {
175
+ return this.mouse_on_container = false;
176
+ };
177
+
178
+ AbstractChosen.prototype.input_focus = function(evt) {
179
+ if (this.is_multiple) {
180
+ if (!this.active_field) {
181
+ return setTimeout(((function(_this) {
182
+ return function() {
183
+ return _this.container_mousedown();
184
+ };
185
+ })(this)), 50);
186
+ }
187
+ } else {
188
+ if (!this.active_field) {
189
+ return this.activate_field();
190
+ }
191
+ }
192
+ };
193
+
194
+ AbstractChosen.prototype.input_blur = function(evt) {
195
+ if (!this.mouse_on_container) {
196
+ this.active_field = false;
197
+ return setTimeout(((function(_this) {
198
+ return function() {
199
+ return _this.blur_test();
200
+ };
201
+ })(this)), 100);
202
+ }
203
+ };
204
+
205
+ AbstractChosen.prototype.label_click_handler = function(evt) {
206
+ if (this.is_multiple) {
207
+ return this.container_mousedown(evt);
208
+ } else {
209
+ return this.activate_field();
210
+ }
211
+ };
212
+
213
+ AbstractChosen.prototype.results_option_build = function(options) {
214
+ var content, data, data_content, i, len, ref, shown_results;
215
+ content = '';
216
+ shown_results = 0;
217
+ ref = this.results_data;
218
+ for (i = 0, len = ref.length; i < len; i++) {
219
+ data = ref[i];
220
+ data_content = '';
221
+ if (data.group) {
222
+ data_content = this.result_add_group(data);
223
+ } else {
224
+ data_content = this.result_add_option(data);
225
+ }
226
+ if (data_content !== '') {
227
+ shown_results++;
228
+ content += data_content;
229
+ }
230
+ if (options != null ? options.first : void 0) {
231
+ if (data.selected && this.is_multiple) {
232
+ this.choice_build(data);
233
+ } else if (data.selected && !this.is_multiple) {
234
+ this.single_set_selected_text(this.choice_label(data));
235
+ }
236
+ }
237
+ if (shown_results >= this.max_shown_results) {
238
+ break;
239
+ }
240
+ }
241
+ return content;
242
+ };
243
+
244
+ AbstractChosen.prototype.result_add_option = function(option) {
245
+ var classes, option_el;
246
+ if (!option.search_match) {
247
+ return '';
248
+ }
249
+ if (!this.include_option_in_results(option)) {
250
+ return '';
251
+ }
252
+ classes = [];
253
+ if (!option.disabled && !(option.selected && this.is_multiple)) {
254
+ classes.push("active-result");
255
+ }
256
+ if (option.disabled && !(option.selected && this.is_multiple)) {
257
+ classes.push("disabled-result");
258
+ }
259
+ if (option.selected) {
260
+ classes.push("result-selected");
261
+ }
262
+ if (option.group_array_index != null) {
263
+ classes.push("group-option");
264
+ }
265
+ if (option.classes !== "") {
266
+ classes.push(option.classes);
267
+ }
268
+ option_el = document.createElement("li");
269
+ option_el.className = classes.join(" ");
270
+ option_el.style.cssText = option.style;
271
+ option_el.setAttribute("data-option-array-index", option.array_index);
272
+ option_el.innerHTML = option.highlighted_html || option.html;
273
+ if (option.title) {
274
+ option_el.title = option.title;
275
+ }
276
+ return this.outerHTML(option_el);
277
+ };
278
+
279
+ AbstractChosen.prototype.result_add_group = function(group) {
280
+ var classes, group_el;
281
+ if (!(group.search_match || group.group_match)) {
282
+ return '';
283
+ }
284
+ if (!(group.active_options > 0)) {
285
+ return '';
286
+ }
287
+ classes = [];
288
+ classes.push("group-result");
289
+ if (group.classes) {
290
+ classes.push(group.classes);
291
+ }
292
+ group_el = document.createElement("li");
293
+ group_el.className = classes.join(" ");
294
+ group_el.innerHTML = group.highlighted_html || this.escape_html(group.label);
295
+ if (group.title) {
296
+ group_el.title = group.title;
297
+ }
298
+ return this.outerHTML(group_el);
299
+ };
300
+
301
+ AbstractChosen.prototype.results_update_field = function() {
302
+ this.set_default_text();
303
+ if (!this.is_multiple) {
304
+ this.results_reset_cleanup();
305
+ }
306
+ this.result_clear_highlight();
307
+ this.results_build();
308
+ if (this.results_showing) {
309
+ return this.winnow_results();
310
+ }
311
+ };
312
+
313
+ AbstractChosen.prototype.reset_single_select_options = function() {
314
+ var i, len, ref, result, results1;
315
+ ref = this.results_data;
316
+ results1 = [];
317
+ for (i = 0, len = ref.length; i < len; i++) {
318
+ result = ref[i];
319
+ if (result.selected) {
320
+ results1.push(result.selected = false);
321
+ } else {
322
+ results1.push(void 0);
323
+ }
324
+ }
325
+ return results1;
326
+ };
327
+
328
+ AbstractChosen.prototype.results_toggle = function() {
329
+ if (this.results_showing) {
330
+ return this.results_hide();
331
+ } else {
332
+ return this.results_show();
333
+ }
334
+ };
335
+
336
+ AbstractChosen.prototype.results_search = function(evt) {
337
+ if (this.results_showing) {
338
+ return this.winnow_results();
339
+ } else {
340
+ return this.results_show();
341
+ }
342
+ };
343
+
344
+ AbstractChosen.prototype.winnow_results = function() {
345
+ var escapedQuery, fix, i, len, option, prefix, query, ref, regex, results, results_group, search_match, startpos, suffix, text;
346
+ this.no_results_clear();
347
+ results = 0;
348
+ query = this.get_search_text();
349
+ escapedQuery = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
350
+ regex = this.get_search_regex(escapedQuery);
351
+ ref = this.results_data;
352
+ for (i = 0, len = ref.length; i < len; i++) {
353
+ option = ref[i];
354
+ option.search_match = false;
355
+ results_group = null;
356
+ search_match = null;
357
+ option.highlighted_html = '';
358
+ if (this.include_option_in_results(option)) {
359
+ if (option.group) {
360
+ option.group_match = false;
361
+ option.active_options = 0;
362
+ }
363
+ if ((option.group_array_index != null) && this.results_data[option.group_array_index]) {
364
+ results_group = this.results_data[option.group_array_index];
365
+ if (results_group.active_options === 0 && results_group.search_match) {
366
+ results += 1;
367
+ }
368
+ results_group.active_options += 1;
369
+ }
370
+ text = option.group ? option.label : option.text;
371
+ if (!(option.group && !this.group_search)) {
372
+ search_match = this.search_string_match(text, regex);
373
+ option.search_match = search_match != null;
374
+ if (option.search_match && !option.group) {
375
+ results += 1;
376
+ }
377
+ if (option.search_match) {
378
+ if (query.length) {
379
+ startpos = search_match.index;
380
+ prefix = text.slice(0, startpos);
381
+ fix = text.slice(startpos, startpos + query.length);
382
+ suffix = text.slice(startpos + query.length);
383
+ option.highlighted_html = (this.escape_html(prefix)) + "<em>" + (this.escape_html(fix)) + "</em>" + (this.escape_html(suffix));
384
+ }
385
+ if (results_group != null) {
386
+ results_group.group_match = true;
387
+ }
388
+ } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) {
389
+ option.search_match = true;
390
+ }
391
+ }
392
+ }
393
+ }
394
+ this.result_clear_highlight();
395
+ if (results < 1 && query.length) {
396
+ this.update_results_content("");
397
+ return this.no_results(query);
398
+ } else {
399
+ this.update_results_content(this.results_option_build());
400
+ return this.winnow_results_set_highlight();
401
+ }
402
+ };
403
+
404
+ AbstractChosen.prototype.get_search_regex = function(escaped_search_string) {
405
+ var regex_flag, regex_string;
406
+ regex_string = this.search_contains ? escaped_search_string : "(^|\\s|\\b)" + escaped_search_string + "[^\\s]*";
407
+ if (!(this.enable_split_word_search || this.search_contains)) {
408
+ regex_string = "^" + regex_string;
409
+ }
410
+ regex_flag = this.case_sensitive_search ? "" : "i";
411
+ return new RegExp(regex_string, regex_flag);
412
+ };
413
+
414
+ AbstractChosen.prototype.search_string_match = function(search_string, regex) {
415
+ var match;
416
+ match = regex.exec(search_string);
417
+ if (!this.search_contains && (match != null ? match[1] : void 0)) {
418
+ match.index += 1;
419
+ }
420
+ return match;
421
+ };
422
+
423
+ AbstractChosen.prototype.choices_count = function() {
424
+ var i, len, option, ref;
425
+ if (this.selected_option_count != null) {
426
+ return this.selected_option_count;
427
+ }
428
+ this.selected_option_count = 0;
429
+ ref = this.form_field.options;
430
+ for (i = 0, len = ref.length; i < len; i++) {
431
+ option = ref[i];
432
+ if (option.selected) {
433
+ this.selected_option_count += 1;
434
+ }
435
+ }
436
+ return this.selected_option_count;
437
+ };
438
+
439
+ AbstractChosen.prototype.choices_click = function(evt) {
440
+ evt.preventDefault();
441
+ this.activate_field();
442
+ if (!(this.results_showing || this.is_disabled)) {
443
+ return this.results_show();
444
+ }
445
+ };
446
+
447
+ AbstractChosen.prototype.keydown_checker = function(evt) {
448
+ var ref, stroke;
449
+ stroke = (ref = evt.which) != null ? ref : evt.keyCode;
450
+ this.search_field_scale();
451
+ if (stroke !== 8 && this.pending_backstroke) {
452
+ this.clear_backstroke();
453
+ }
454
+ switch (stroke) {
455
+ case 8:
456
+ this.backstroke_length = this.get_search_field_value().length;
457
+ break;
458
+ case 9:
459
+ if (this.results_showing && !this.is_multiple) {
460
+ this.result_select(evt);
461
+ }
462
+ this.mouse_on_container = false;
463
+ break;
464
+ case 13:
465
+ if (this.results_showing) {
466
+ evt.preventDefault();
467
+ }
468
+ break;
469
+ case 27:
470
+ if (this.results_showing) {
471
+ evt.preventDefault();
472
+ }
473
+ break;
474
+ case 32:
475
+ if (this.disable_search) {
476
+ evt.preventDefault();
477
+ }
478
+ break;
479
+ case 38:
480
+ evt.preventDefault();
481
+ this.keyup_arrow();
482
+ break;
483
+ case 40:
484
+ evt.preventDefault();
485
+ this.keydown_arrow();
486
+ break;
487
+ }
488
+ };
489
+
490
+ AbstractChosen.prototype.keyup_checker = function(evt) {
491
+ var ref, stroke;
492
+ stroke = (ref = evt.which) != null ? ref : evt.keyCode;
493
+ this.search_field_scale();
494
+ switch (stroke) {
495
+ case 8:
496
+ if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) {
497
+ this.keydown_backstroke();
498
+ } else if (!this.pending_backstroke) {
499
+ this.result_clear_highlight();
500
+ this.results_search();
501
+ }
502
+ break;
503
+ case 13:
504
+ evt.preventDefault();
505
+ if (this.results_showing) {
506
+ this.result_select(evt);
507
+ }
508
+ break;
509
+ case 27:
510
+ if (this.results_showing) {
511
+ this.results_hide();
512
+ }
513
+ break;
514
+ case 9:
515
+ case 16:
516
+ case 17:
517
+ case 18:
518
+ case 38:
519
+ case 40:
520
+ case 91:
521
+ break;
522
+ default:
523
+ this.results_search();
524
+ break;
525
+ }
526
+ };
527
+
528
+ AbstractChosen.prototype.clipboard_event_checker = function(evt) {
529
+ if (this.is_disabled) {
530
+ return;
531
+ }
532
+ return setTimeout(((function(_this) {
533
+ return function() {
534
+ return _this.results_search();
535
+ };
536
+ })(this)), 50);
537
+ };
538
+
539
+ AbstractChosen.prototype.container_width = function() {
540
+ if (this.options.width != null) {
541
+ return this.options.width;
542
+ } else {
543
+ return this.form_field.offsetWidth + "px";
544
+ }
545
+ };
546
+
547
+ AbstractChosen.prototype.include_option_in_results = function(option) {
548
+ if (this.is_multiple && (!this.display_selected_options && option.selected)) {
549
+ return false;
550
+ }
551
+ if (!this.display_disabled_options && option.disabled) {
552
+ return false;
553
+ }
554
+ if (option.empty) {
555
+ return false;
556
+ }
557
+ return true;
558
+ };
559
+
560
+ AbstractChosen.prototype.search_results_touchstart = function(evt) {
561
+ this.touch_started = true;
562
+ return this.search_results_mouseover(evt);
563
+ };
564
+
565
+ AbstractChosen.prototype.search_results_touchmove = function(evt) {
566
+ this.touch_started = false;
567
+ return this.search_results_mouseout(evt);
568
+ };
569
+
570
+ AbstractChosen.prototype.search_results_touchend = function(evt) {
571
+ if (this.touch_started) {
572
+ return this.search_results_mouseup(evt);
573
+ }
574
+ };
575
+
576
+ AbstractChosen.prototype.outerHTML = function(element) {
577
+ var tmp;
578
+ if (element.outerHTML) {
579
+ return element.outerHTML;
580
+ }
581
+ tmp = document.createElement("div");
582
+ tmp.appendChild(element);
583
+ return tmp.innerHTML;
584
+ };
585
+
586
+ AbstractChosen.prototype.get_single_html = function() {
587
+ return "<a class=\"chosen-single chosen-default\">\n <span>" + this.default_text + "</span>\n <div><b></b></div>\n</a>\n<div class=\"chosen-drop\">\n <div class=\"chosen-search\">\n <input class=\"chosen-search-input\" type=\"text\" autocomplete=\"off\" />\n </div>\n <ul class=\"chosen-results\"></ul>\n</div>";
588
+ };
589
+
590
+ AbstractChosen.prototype.get_multi_html = function() {
591
+ return "<ul class=\"chosen-choices\">\n <li class=\"search-field\">\n <input class=\"chosen-search-input\" type=\"text\" autocomplete=\"off\" value=\"" + this.default_text + "\" />\n </li>\n</ul>\n<div class=\"chosen-drop\">\n <ul class=\"chosen-results\"></ul>\n</div>";
592
+ };
593
+
594
+ AbstractChosen.prototype.get_no_results_html = function(terms) {
595
+ return "<li class=\"no-results\">\n " + this.results_none_found + " <span>" + (this.escape_html(terms)) + "</span>\n</li>";
596
+ };
597
+
598
+ AbstractChosen.browser_is_supported = function() {
599
+ if ("Microsoft Internet Explorer" === window.navigator.appName) {
600
+ return document.documentMode >= 8;
601
+ }
602
+ if (/iP(od|hone)/i.test(window.navigator.userAgent) || /IEMobile/i.test(window.navigator.userAgent) || /Windows Phone/i.test(window.navigator.userAgent) || /BlackBerry/i.test(window.navigator.userAgent) || /BB10/i.test(window.navigator.userAgent) || /Android.*Mobile/i.test(window.navigator.userAgent)) {
603
+ return false;
604
+ }
605
+ return true;
606
+ };
607
+
608
+ AbstractChosen.default_multiple_text = "Select Some Options";
609
+
610
+ AbstractChosen.default_single_text = "Select an Option";
611
+
612
+ AbstractChosen.default_no_result_text = "No results match";
613
+
614
+ return AbstractChosen;
615
+
616
+ })();
617
+
618
+ $ = jQuery;
619
+
620
+ $.fn.extend({
621
+ chosen: function(options) {
622
+ if (!AbstractChosen.browser_is_supported()) {
623
+ return this;
624
+ }
625
+ return this.each(function(input_field) {
626
+ var $this, chosen;
627
+ $this = $(this);
628
+ chosen = $this.data('chosen');
629
+ if (options === 'destroy') {
630
+ if (chosen instanceof Chosen) {
631
+ chosen.destroy();
632
+ }
633
+ return;
634
+ }
635
+ if (!(chosen instanceof Chosen)) {
636
+ $this.data('chosen', new Chosen(this, options));
637
+ }
638
+ });
639
+ }
640
+ });
641
+
642
+ Chosen = (function(superClass) {
643
+ extend(Chosen, superClass);
644
+
645
+ function Chosen() {
646
+ return Chosen.__super__.constructor.apply(this, arguments);
647
+ }
648
+
649
+ Chosen.prototype.setup = function() {
650
+ this.form_field_jq = $(this.form_field);
651
+ return this.current_selectedIndex = this.form_field.selectedIndex;
652
+ };
653
+
654
+ Chosen.prototype.set_up_html = function() {
655
+ var container_classes, container_props;
656
+ container_classes = ["chosen-container"];
657
+ container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single"));
658
+ if (this.inherit_select_classes && this.form_field.className) {
659
+ container_classes.push(this.form_field.className);
660
+ }
661
+ if (this.is_rtl) {
662
+ container_classes.push("chosen-rtl");
663
+ }
664
+ container_props = {
665
+ 'class': container_classes.join(' '),
666
+ 'title': this.form_field.title
667
+ };
668
+ if (this.form_field.id.length) {
669
+ container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen";
670
+ }
671
+ this.container = $("<div />", container_props);
672
+ this.container.width(this.container_width());
673
+ if (this.is_multiple) {
674
+ this.container.html(this.get_multi_html());
675
+ } else {
676
+ this.container.html(this.get_single_html());
677
+ }
678
+ this.form_field_jq.hide().after(this.container);
679
+ this.dropdown = this.container.find('div.chosen-drop').first();
680
+ this.search_field = this.container.find('input').first();
681
+ this.search_results = this.container.find('ul.chosen-results').first();
682
+ this.search_field_scale();
683
+ this.search_no_results = this.container.find('li.no-results').first();
684
+ if (this.is_multiple) {
685
+ this.search_choices = this.container.find('ul.chosen-choices').first();
686
+ this.search_container = this.container.find('li.search-field').first();
687
+ } else {
688
+ this.search_container = this.container.find('div.chosen-search').first();
689
+ this.selected_item = this.container.find('.chosen-single').first();
690
+ }
691
+ this.results_build();
692
+ this.set_tab_index();
693
+ return this.set_label_behavior();
694
+ };
695
+
696
+ Chosen.prototype.on_ready = function() {
697
+ return this.form_field_jq.trigger("chosen:ready", {
698
+ chosen: this
699
+ });
700
+ };
701
+
702
+ Chosen.prototype.register_observers = function() {
703
+ this.container.on('touchstart.chosen', (function(_this) {
704
+ return function(evt) {
705
+ _this.container_mousedown(evt);
706
+ };
707
+ })(this));
708
+ this.container.on('touchend.chosen', (function(_this) {
709
+ return function(evt) {
710
+ _this.container_mouseup(evt);
711
+ };
712
+ })(this));
713
+ this.container.on('mousedown.chosen', (function(_this) {
714
+ return function(evt) {
715
+ _this.container_mousedown(evt);
716
+ };
717
+ })(this));
718
+ this.container.on('mouseup.chosen', (function(_this) {
719
+ return function(evt) {
720
+ _this.container_mouseup(evt);
721
+ };
722
+ })(this));
723
+ this.container.on('mouseenter.chosen', (function(_this) {
724
+ return function(evt) {
725
+ _this.mouse_enter(evt);
726
+ };
727
+ })(this));
728
+ this.container.on('mouseleave.chosen', (function(_this) {
729
+ return function(evt) {
730
+ _this.mouse_leave(evt);
731
+ };
732
+ })(this));
733
+ this.search_results.on('mouseup.chosen', (function(_this) {
734
+ return function(evt) {
735
+ _this.search_results_mouseup(evt);
736
+ };
737
+ })(this));
738
+ this.search_results.on('mouseover.chosen', (function(_this) {
739
+ return function(evt) {
740
+ _this.search_results_mouseover(evt);
741
+ };
742
+ })(this));
743
+ this.search_results.on('mouseout.chosen', (function(_this) {
744
+ return function(evt) {
745
+ _this.search_results_mouseout(evt);
746
+ };
747
+ })(this));
748
+ this.search_results.on('mousewheel.chosen DOMMouseScroll.chosen', (function(_this) {
749
+ return function(evt) {
750
+ _this.search_results_mousewheel(evt);
751
+ };
752
+ })(this));
753
+ this.search_results.on('touchstart.chosen', (function(_this) {
754
+ return function(evt) {
755
+ _this.search_results_touchstart(evt);
756
+ };
757
+ })(this));
758
+ this.search_results.on('touchmove.chosen', (function(_this) {
759
+ return function(evt) {
760
+ _this.search_results_touchmove(evt);
761
+ };
762
+ })(this));
763
+ this.search_results.on('touchend.chosen', (function(_this) {
764
+ return function(evt) {
765
+ _this.search_results_touchend(evt);
766
+ };
767
+ })(this));
768
+ this.form_field_jq.on("chosen:updated.chosen", (function(_this) {
769
+ return function(evt) {
770
+ _this.results_update_field(evt);
771
+ };
772
+ })(this));
773
+ this.form_field_jq.on("chosen:activate.chosen", (function(_this) {
774
+ return function(evt) {
775
+ _this.activate_field(evt);
776
+ };
777
+ })(this));
778
+ this.form_field_jq.on("chosen:open.chosen", (function(_this) {
779
+ return function(evt) {
780
+ _this.container_mousedown(evt);
781
+ };
782
+ })(this));
783
+ this.form_field_jq.on("chosen:close.chosen", (function(_this) {
784
+ return function(evt) {
785
+ _this.close_field(evt);
786
+ };
787
+ })(this));
788
+ this.search_field.on('blur.chosen', (function(_this) {
789
+ return function(evt) {
790
+ _this.input_blur(evt);
791
+ };
792
+ })(this));
793
+ this.search_field.on('keyup.chosen', (function(_this) {
794
+ return function(evt) {
795
+ _this.keyup_checker(evt);
796
+ };
797
+ })(this));
798
+ this.search_field.on('keydown.chosen', (function(_this) {
799
+ return function(evt) {
800
+ _this.keydown_checker(evt);
801
+ };
802
+ })(this));
803
+ this.search_field.on('focus.chosen', (function(_this) {
804
+ return function(evt) {
805
+ _this.input_focus(evt);
806
+ };
807
+ })(this));
808
+ this.search_field.on('cut.chosen', (function(_this) {
809
+ return function(evt) {
810
+ _this.clipboard_event_checker(evt);
811
+ };
812
+ })(this));
813
+ this.search_field.on('paste.chosen', (function(_this) {
814
+ return function(evt) {
815
+ _this.clipboard_event_checker(evt);
816
+ };
817
+ })(this));
818
+ if (this.is_multiple) {
819
+ return this.search_choices.on('click.chosen', (function(_this) {
820
+ return function(evt) {
821
+ _this.choices_click(evt);
822
+ };
823
+ })(this));
824
+ } else {
825
+ return this.container.on('click.chosen', function(evt) {
826
+ evt.preventDefault();
827
+ });
828
+ }
829
+ };
830
+
831
+ Chosen.prototype.destroy = function() {
832
+ $(this.container[0].ownerDocument).off('click.chosen', this.click_test_action);
833
+ if (this.form_field_label.length > 0) {
834
+ this.form_field_label.off('click.chosen');
835
+ }
836
+ if (this.search_field[0].tabIndex) {
837
+ this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex;
838
+ }
839
+ this.container.remove();
840
+ this.form_field_jq.removeData('chosen');
841
+ return this.form_field_jq.show();
842
+ };
843
+
844
+ Chosen.prototype.search_field_disabled = function() {
845
+ this.is_disabled = this.form_field.disabled || this.form_field_jq.parents('fieldset').is(':disabled');
846
+ this.container.toggleClass('chosen-disabled', this.is_disabled);
847
+ this.search_field[0].disabled = this.is_disabled;
848
+ if (!this.is_multiple) {
849
+ this.selected_item.off('focus.chosen', this.activate_field);
850
+ }
851
+ if (this.is_disabled) {
852
+ return this.close_field();
853
+ } else if (!this.is_multiple) {
854
+ return this.selected_item.on('focus.chosen', this.activate_field);
855
+ }
856
+ };
857
+
858
+ Chosen.prototype.container_mousedown = function(evt) {
859
+ var ref;
860
+ if (this.is_disabled) {
861
+ return;
862
+ }
863
+ if (evt && ((ref = evt.type) === 'mousedown' || ref === 'touchstart') && !this.results_showing) {
864
+ evt.preventDefault();
865
+ }
866
+ if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
867
+ if (!this.active_field) {
868
+ if (this.is_multiple) {
869
+ this.search_field.val("");
870
+ }
871
+ $(this.container[0].ownerDocument).on('click.chosen', this.click_test_action);
872
+ this.results_show();
873
+ } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) {
874
+ evt.preventDefault();
875
+ this.results_toggle();
876
+ }
877
+ return this.activate_field();
878
+ }
879
+ };
880
+
881
+ Chosen.prototype.container_mouseup = function(evt) {
882
+ if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
883
+ return this.results_reset(evt);
884
+ }
885
+ };
886
+
887
+ Chosen.prototype.search_results_mousewheel = function(evt) {
888
+ var delta;
889
+ if (evt.originalEvent) {
890
+ delta = evt.originalEvent.deltaY || -evt.originalEvent.wheelDelta || evt.originalEvent.detail;
891
+ }
892
+ if (delta != null) {
893
+ evt.preventDefault();
894
+ if (evt.type === 'DOMMouseScroll') {
895
+ delta = delta * 40;
896
+ }
897
+ return this.search_results.scrollTop(delta + this.search_results.scrollTop());
898
+ }
899
+ };
900
+
901
+ Chosen.prototype.blur_test = function(evt) {
902
+ if (!this.active_field && this.container.hasClass("chosen-container-active")) {
903
+ return this.close_field();
904
+ }
905
+ };
906
+
907
+ Chosen.prototype.close_field = function() {
908
+ $(this.container[0].ownerDocument).off("click.chosen", this.click_test_action);
909
+ this.active_field = false;
910
+ this.results_hide();
911
+ this.container.removeClass("chosen-container-active");
912
+ this.clear_backstroke();
913
+ this.show_search_field_default();
914
+ this.search_field_scale();
915
+ return this.search_field.blur();
916
+ };
917
+
918
+ Chosen.prototype.activate_field = function() {
919
+ if (this.is_disabled) {
920
+ return;
921
+ }
922
+ this.container.addClass("chosen-container-active");
923
+ this.active_field = true;
924
+ this.search_field.val(this.search_field.val());
925
+ return this.search_field.focus();
926
+ };
927
+
928
+ Chosen.prototype.test_active_click = function(evt) {
929
+ var active_container;
930
+ active_container = $(evt.target).closest('.chosen-container');
931
+ if (active_container.length && this.container[0] === active_container[0]) {
932
+ return this.active_field = true;
933
+ } else {
934
+ return this.close_field();
935
+ }
936
+ };
937
+
938
+ Chosen.prototype.results_build = function() {
939
+ this.parsing = true;
940
+ this.selected_option_count = null;
941
+ this.results_data = SelectParser.select_to_array(this.form_field);
942
+ if (this.is_multiple) {
943
+ this.search_choices.find("li.search-choice").remove();
944
+ } else if (!this.is_multiple) {
945
+ this.single_set_selected_text();
946
+ if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
947
+ this.search_field[0].readOnly = true;
948
+ this.container.addClass("chosen-container-single-nosearch");
949
+ } else {
950
+ this.search_field[0].readOnly = false;
951
+ this.container.removeClass("chosen-container-single-nosearch");
952
+ }
953
+ }
954
+ this.update_results_content(this.results_option_build({
955
+ first: true
956
+ }));
957
+ this.search_field_disabled();
958
+ this.show_search_field_default();
959
+ this.search_field_scale();
960
+ return this.parsing = false;
961
+ };
962
+
963
+ Chosen.prototype.result_do_highlight = function(el) {
964
+ var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
965
+ if (el.length) {
966
+ this.result_clear_highlight();
967
+ this.result_highlight = el;
968
+ this.result_highlight.addClass("highlighted");
969
+ maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
970
+ visible_top = this.search_results.scrollTop();
971
+ visible_bottom = maxHeight + visible_top;
972
+ high_top = this.result_highlight.position().top + this.search_results.scrollTop();
973
+ high_bottom = high_top + this.result_highlight.outerHeight();
974
+ if (high_bottom >= visible_bottom) {
975
+ return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
976
+ } else if (high_top < visible_top) {
977
+ return this.search_results.scrollTop(high_top);
978
+ }
979
+ }
980
+ };
981
+
982
+ Chosen.prototype.result_clear_highlight = function() {
983
+ if (this.result_highlight) {
984
+ this.result_highlight.removeClass("highlighted");
985
+ }
986
+ return this.result_highlight = null;
987
+ };
988
+
989
+ Chosen.prototype.results_show = function() {
990
+ if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
991
+ this.form_field_jq.trigger("chosen:maxselected", {
992
+ chosen: this
993
+ });
994
+ return false;
995
+ }
996
+ this.container.addClass("chosen-with-drop");
997
+ this.results_showing = true;
998
+ this.search_field.focus();
999
+ this.search_field.val(this.get_search_field_value());
1000
+ this.winnow_results();
1001
+ return this.form_field_jq.trigger("chosen:showing_dropdown", {
1002
+ chosen: this
1003
+ });
1004
+ };
1005
+
1006
+ Chosen.prototype.update_results_content = function(content) {
1007
+ return this.search_results.html(content);
1008
+ };
1009
+
1010
+ Chosen.prototype.results_hide = function() {
1011
+ if (this.results_showing) {
1012
+ this.result_clear_highlight();
1013
+ this.container.removeClass("chosen-with-drop");
1014
+ this.form_field_jq.trigger("chosen:hiding_dropdown", {
1015
+ chosen: this
1016
+ });
1017
+ }
1018
+ return this.results_showing = false;
1019
+ };
1020
+
1021
+ Chosen.prototype.set_tab_index = function(el) {
1022
+ var ti;
1023
+ if (this.form_field.tabIndex) {
1024
+ ti = this.form_field.tabIndex;
1025
+ this.form_field.tabIndex = -1;
1026
+ return this.search_field[0].tabIndex = ti;
1027
+ }
1028
+ };
1029
+
1030
+ Chosen.prototype.set_label_behavior = function() {
1031
+ this.form_field_label = this.form_field_jq.parents("label");
1032
+ if (!this.form_field_label.length && this.form_field.id.length) {
1033
+ this.form_field_label = $("label[for='" + this.form_field.id + "']");
1034
+ }
1035
+ if (this.form_field_label.length > 0) {
1036
+ return this.form_field_label.on('click.chosen', this.label_click_handler);
1037
+ }
1038
+ };
1039
+
1040
+ Chosen.prototype.show_search_field_default = function() {
1041
+ if (this.is_multiple && this.choices_count() < 1 && !this.active_field) {
1042
+ this.search_field.val(this.default_text);
1043
+ return this.search_field.addClass("default");
1044
+ } else {
1045
+ this.search_field.val("");
1046
+ return this.search_field.removeClass("default");
1047
+ }
1048
+ };
1049
+
1050
+ Chosen.prototype.search_results_mouseup = function(evt) {
1051
+ var target;
1052
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
1053
+ if (target.length) {
1054
+ this.result_highlight = target;
1055
+ this.result_select(evt);
1056
+ return this.search_field.focus();
1057
+ }
1058
+ };
1059
+
1060
+ Chosen.prototype.search_results_mouseover = function(evt) {
1061
+ var target;
1062
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
1063
+ if (target) {
1064
+ return this.result_do_highlight(target);
1065
+ }
1066
+ };
1067
+
1068
+ Chosen.prototype.search_results_mouseout = function(evt) {
1069
+ if ($(evt.target).hasClass("active-result") || $(evt.target).parents('.active-result').first()) {
1070
+ return this.result_clear_highlight();
1071
+ }
1072
+ };
1073
+
1074
+ Chosen.prototype.choice_build = function(item) {
1075
+ var choice, close_link;
1076
+ choice = $('<li />', {
1077
+ "class": "search-choice"
1078
+ }).html("<span>" + (this.choice_label(item)) + "</span>");
1079
+ if (item.disabled) {
1080
+ choice.addClass('search-choice-disabled');
1081
+ } else {
1082
+ close_link = $('<a />', {
1083
+ "class": 'search-choice-close',
1084
+ 'data-option-array-index': item.array_index
1085
+ });
1086
+ close_link.on('click.chosen', (function(_this) {
1087
+ return function(evt) {
1088
+ return _this.choice_destroy_link_click(evt);
1089
+ };
1090
+ })(this));
1091
+ choice.append(close_link);
1092
+ }
1093
+ return this.search_container.before(choice);
1094
+ };
1095
+
1096
+ Chosen.prototype.choice_destroy_link_click = function(evt) {
1097
+ evt.preventDefault();
1098
+ evt.stopPropagation();
1099
+ if (!this.is_disabled) {
1100
+ return this.choice_destroy($(evt.target));
1101
+ }
1102
+ };
1103
+
1104
+ Chosen.prototype.choice_destroy = function(link) {
1105
+ if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) {
1106
+ if (this.active_field) {
1107
+ this.search_field.focus();
1108
+ } else {
1109
+ this.show_search_field_default();
1110
+ }
1111
+ if (this.is_multiple && this.choices_count() > 0 && this.get_search_field_value().length < 1) {
1112
+ this.results_hide();
1113
+ }
1114
+ link.parents('li').first().remove();
1115
+ return this.search_field_scale();
1116
+ }
1117
+ };
1118
+
1119
+ Chosen.prototype.results_reset = function() {
1120
+ this.reset_single_select_options();
1121
+ this.form_field.options[0].selected = true;
1122
+ this.single_set_selected_text();
1123
+ this.show_search_field_default();
1124
+ this.results_reset_cleanup();
1125
+ this.trigger_form_field_change();
1126
+ if (this.active_field) {
1127
+ return this.results_hide();
1128
+ }
1129
+ };
1130
+
1131
+ Chosen.prototype.results_reset_cleanup = function() {
1132
+ this.current_selectedIndex = this.form_field.selectedIndex;
1133
+ return this.selected_item.find("abbr").remove();
1134
+ };
1135
+
1136
+ Chosen.prototype.result_select = function(evt) {
1137
+ var high, item;
1138
+ if (this.result_highlight) {
1139
+ high = this.result_highlight;
1140
+ this.result_clear_highlight();
1141
+ if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
1142
+ this.form_field_jq.trigger("chosen:maxselected", {
1143
+ chosen: this
1144
+ });
1145
+ return false;
1146
+ }
1147
+ if (this.is_multiple) {
1148
+ high.removeClass("active-result");
1149
+ } else {
1150
+ this.reset_single_select_options();
1151
+ }
1152
+ high.addClass("result-selected");
1153
+ item = this.results_data[high[0].getAttribute("data-option-array-index")];
1154
+ item.selected = true;
1155
+ this.form_field.options[item.options_index].selected = true;
1156
+ this.selected_option_count = null;
1157
+ this.search_field.val("");
1158
+ if (this.is_multiple) {
1159
+ this.choice_build(item);
1160
+ } else {
1161
+ this.single_set_selected_text(this.choice_label(item));
1162
+ }
1163
+ if (this.is_multiple && (!this.hide_results_on_select || (evt.metaKey || evt.ctrlKey))) {
1164
+ this.winnow_results();
1165
+ } else {
1166
+ this.results_hide();
1167
+ this.show_search_field_default();
1168
+ }
1169
+ if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
1170
+ this.trigger_form_field_change({
1171
+ selected: this.form_field.options[item.options_index].value
1172
+ });
1173
+ }
1174
+ this.current_selectedIndex = this.form_field.selectedIndex;
1175
+ evt.preventDefault();
1176
+ return this.search_field_scale();
1177
+ }
1178
+ };
1179
+
1180
+ Chosen.prototype.single_set_selected_text = function(text) {
1181
+ if (text == null) {
1182
+ text = this.default_text;
1183
+ }
1184
+ if (text === this.default_text) {
1185
+ this.selected_item.addClass("chosen-default");
1186
+ } else {
1187
+ this.single_deselect_control_build();
1188
+ this.selected_item.removeClass("chosen-default");
1189
+ }
1190
+ return this.selected_item.find("span").html(text);
1191
+ };
1192
+
1193
+ Chosen.prototype.result_deselect = function(pos) {
1194
+ var result_data;
1195
+ result_data = this.results_data[pos];
1196
+ if (!this.form_field.options[result_data.options_index].disabled) {
1197
+ result_data.selected = false;
1198
+ this.form_field.options[result_data.options_index].selected = false;
1199
+ this.selected_option_count = null;
1200
+ this.result_clear_highlight();
1201
+ if (this.results_showing) {
1202
+ this.winnow_results();
1203
+ }
1204
+ this.trigger_form_field_change({
1205
+ deselected: this.form_field.options[result_data.options_index].value
1206
+ });
1207
+ this.search_field_scale();
1208
+ return true;
1209
+ } else {
1210
+ return false;
1211
+ }
1212
+ };
1213
+
1214
+ Chosen.prototype.single_deselect_control_build = function() {
1215
+ if (!this.allow_single_deselect) {
1216
+ return;
1217
+ }
1218
+ if (!this.selected_item.find("abbr").length) {
1219
+ this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
1220
+ }
1221
+ return this.selected_item.addClass("chosen-single-with-deselect");
1222
+ };
1223
+
1224
+ Chosen.prototype.get_search_field_value = function() {
1225
+ return this.search_field.val();
1226
+ };
1227
+
1228
+ Chosen.prototype.get_search_text = function() {
1229
+ return $.trim(this.get_search_field_value());
1230
+ };
1231
+
1232
+ Chosen.prototype.escape_html = function(text) {
1233
+ return $('<div/>').text(text).html();
1234
+ };
1235
+
1236
+ Chosen.prototype.winnow_results_set_highlight = function() {
1237
+ var do_high, selected_results;
1238
+ selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
1239
+ do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
1240
+ if (do_high != null) {
1241
+ return this.result_do_highlight(do_high);
1242
+ }
1243
+ };
1244
+
1245
+ Chosen.prototype.no_results = function(terms) {
1246
+ var no_results_html;
1247
+ no_results_html = this.get_no_results_html(terms);
1248
+ this.search_results.append(no_results_html);
1249
+ return this.form_field_jq.trigger("chosen:no_results", {
1250
+ chosen: this
1251
+ });
1252
+ };
1253
+
1254
+ Chosen.prototype.no_results_clear = function() {
1255
+ return this.search_results.find(".no-results").remove();
1256
+ };
1257
+
1258
+ Chosen.prototype.keydown_arrow = function() {
1259
+ var next_sib;
1260
+ if (this.results_showing && this.result_highlight) {
1261
+ next_sib = this.result_highlight.nextAll("li.active-result").first();
1262
+ if (next_sib) {
1263
+ return this.result_do_highlight(next_sib);
1264
+ }
1265
+ } else {
1266
+ return this.results_show();
1267
+ }
1268
+ };
1269
+
1270
+ Chosen.prototype.keyup_arrow = function() {
1271
+ var prev_sibs;
1272
+ if (!this.results_showing && !this.is_multiple) {
1273
+ return this.results_show();
1274
+ } else if (this.result_highlight) {
1275
+ prev_sibs = this.result_highlight.prevAll("li.active-result");
1276
+ if (prev_sibs.length) {
1277
+ return this.result_do_highlight(prev_sibs.first());
1278
+ } else {
1279
+ if (this.choices_count() > 0) {
1280
+ this.results_hide();
1281
+ }
1282
+ return this.result_clear_highlight();
1283
+ }
1284
+ }
1285
+ };
1286
+
1287
+ Chosen.prototype.keydown_backstroke = function() {
1288
+ var next_available_destroy;
1289
+ if (this.pending_backstroke) {
1290
+ this.choice_destroy(this.pending_backstroke.find("a").first());
1291
+ return this.clear_backstroke();
1292
+ } else {
1293
+ next_available_destroy = this.search_container.siblings("li.search-choice").last();
1294
+ if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
1295
+ this.pending_backstroke = next_available_destroy;
1296
+ if (this.single_backstroke_delete) {
1297
+ return this.keydown_backstroke();
1298
+ } else {
1299
+ return this.pending_backstroke.addClass("search-choice-focus");
1300
+ }
1301
+ }
1302
+ }
1303
+ };
1304
+
1305
+ Chosen.prototype.clear_backstroke = function() {
1306
+ if (this.pending_backstroke) {
1307
+ this.pending_backstroke.removeClass("search-choice-focus");
1308
+ }
1309
+ return this.pending_backstroke = null;
1310
+ };
1311
+
1312
+ Chosen.prototype.search_field_scale = function() {
1313
+ var div, i, len, style, style_block, styles, width;
1314
+ if (!this.is_multiple) {
1315
+ return;
1316
+ }
1317
+ style_block = {
1318
+ position: 'absolute',
1319
+ left: '-1000px',
1320
+ top: '-1000px',
1321
+ display: 'none',
1322
+ whiteSpace: 'pre'
1323
+ };
1324
+ styles = ['fontSize', 'fontStyle', 'fontWeight', 'fontFamily', 'lineHeight', 'textTransform', 'letterSpacing'];
1325
+ for (i = 0, len = styles.length; i < len; i++) {
1326
+ style = styles[i];
1327
+ style_block[style] = this.search_field.css(style);
1328
+ }
1329
+ div = $('<div />').css(style_block);
1330
+ div.text(this.get_search_field_value());
1331
+ $('body').append(div);
1332
+ width = div.width() + 25;
1333
+ div.remove();
1334
+ if (this.container.is(':visible')) {
1335
+ width = Math.min(this.container.outerWidth() - 10, width);
1336
+ }
1337
+ return this.search_field.width(width);
1338
+ };
1339
+
1340
+ Chosen.prototype.trigger_form_field_change = function(extra) {
1341
+ this.form_field_jq.trigger("input", extra);
1342
+ return this.form_field_jq.trigger("change", extra);
1343
+ };
1344
+
1345
+ return Chosen;
1346
+
1347
+ })(AbstractChosen);
1348
+
1349
+ }).call(this);
includes/controls/assets/js/uncompressed/jQuery-minicolors/LICENSE.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ Copyright 2017 A Beautiful Site, LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
includes/controls/assets/js/uncompressed/jQuery-minicolors/jquery.minicolors.js ADDED
@@ -0,0 +1,1108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // jQuery MiniColors: A tiny color picker built on jQuery
3
+ //
4
+ // Developed by Cory LaViska for A Beautiful Site, LLC
5
+ //
6
+ // Licensed under the MIT license: http://opensource.org/licenses/MIT
7
+ //
8
+ (function (factory) {
9
+ if(typeof define === 'function' && define.amd) {
10
+ // AMD. Register as an anonymous module.
11
+ define(['jquery'], factory);
12
+ } else if(typeof exports === 'object') {
13
+ // Node/CommonJS
14
+ module.exports = factory(require('jquery'));
15
+ } else {
16
+ // Browser globals
17
+ factory(jQuery);
18
+ }
19
+ }(function ($) {
20
+ 'use strict';
21
+
22
+ // Defaults
23
+ $.minicolors = {
24
+ defaults: {
25
+ animationSpeed: 50,
26
+ animationEasing: 'swing',
27
+ change: null,
28
+ changeDelay: 0,
29
+ control: 'hue',
30
+ defaultValue: '',
31
+ format: 'hex',
32
+ hide: null,
33
+ hideSpeed: 100,
34
+ inline: false,
35
+ keywords: '',
36
+ letterCase: 'lowercase',
37
+ opacity: false,
38
+ position: 'bottom left',
39
+ show: null,
40
+ showSpeed: 100,
41
+ theme: 'default',
42
+ swatches: []
43
+ }
44
+ };
45
+
46
+ // Public methods
47
+ $.extend($.fn, {
48
+ minicolors: function(method, data) {
49
+
50
+ switch(method) {
51
+ // Destroy the control
52
+ case 'destroy':
53
+ $(this).each(function() {
54
+ destroy($(this));
55
+ });
56
+ return $(this);
57
+
58
+ // Hide the color picker
59
+ case 'hide':
60
+ hide();
61
+ return $(this);
62
+
63
+ // Get/set opacity
64
+ case 'opacity':
65
+ // Getter
66
+ if(data === undefined) {
67
+ // Getter
68
+ return $(this).attr('data-opacity');
69
+ } else {
70
+ // Setter
71
+ $(this).each(function() {
72
+ updateFromInput($(this).attr('data-opacity', data));
73
+ });
74
+ }
75
+ return $(this);
76
+
77
+ // Get an RGB(A) object based on the current color/opacity
78
+ case 'rgbObject':
79
+ return rgbObject($(this), method === 'rgbaObject');
80
+
81
+ // Get an RGB(A) string based on the current color/opacity
82
+ case 'rgbString':
83
+ case 'rgbaString':
84
+ return rgbString($(this), method === 'rgbaString');
85
+
86
+ // Get/set settings on the fly
87
+ case 'settings':
88
+ if(data === undefined) {
89
+ return $(this).data('minicolors-settings');
90
+ } else {
91
+ // Setter
92
+ $(this).each(function() {
93
+ var settings = $(this).data('minicolors-settings') || {};
94
+ destroy($(this));
95
+ $(this).minicolors($.extend(true, settings, data));
96
+ });
97
+ }
98
+ return $(this);
99
+
100
+ // Show the color picker
101
+ case 'show':
102
+ show($(this).eq(0));
103
+ return $(this);
104
+
105
+ // Get/set the hex color value
106
+ case 'value':
107
+ if(data === undefined) {
108
+ // Getter
109
+ return $(this).val();
110
+ } else {
111
+ // Setter
112
+ $(this).each(function() {
113
+ if(typeof(data) === 'object' && data !== null) {
114
+ if(data.opacity) {
115
+ $(this).attr('data-opacity', keepWithin(data.opacity, 0, 1));
116
+ }
117
+ if(data.color) {
118
+ $(this).val(data.color);
119
+ }
120
+ } else {
121
+ $(this).val(data);
122
+ }
123
+ updateFromInput($(this));
124
+ });
125
+ }
126
+ return $(this);
127
+
128
+ // Initializes the control
129
+ default:
130
+ if(method !== 'create') data = method;
131
+ $(this).each(function() {
132
+ init($(this), data);
133
+ });
134
+ return $(this);
135
+
136
+ }
137
+
138
+ }
139
+ });
140
+
141
+ // Initialize input elements
142
+ function init(input, settings) {
143
+ var minicolors = $('<div class="minicolors" />');
144
+ var defaults = $.minicolors.defaults;
145
+ var size;
146
+ var swatches;
147
+ var swatch;
148
+ var panel;
149
+ var i;
150
+
151
+ // Do nothing if already initialized
152
+ if(input.data('minicolors-initialized')) return;
153
+
154
+ // Handle settings
155
+ settings = $.extend(true, {}, defaults, settings);
156
+
157
+ // The wrapper
158
+ minicolors
159
+ .addClass('minicolors-theme-' + settings.theme)
160
+ .toggleClass('minicolors-with-opacity', settings.opacity);
161
+
162
+ // Custom positioning
163
+ if(settings.position !== undefined) {
164
+ $.each(settings.position.split(' '), function() {
165
+ minicolors.addClass('minicolors-position-' + this);
166
+ });
167
+ }
168
+
169
+ // Input size
170
+ if(settings.format === 'rgb') {
171
+ size = settings.opacity ? '25' : '20';
172
+ } else {
173
+ size = settings.keywords ? '11' : '7';
174
+ }
175
+
176
+ // The input
177
+ input
178
+ .addClass('minicolors-input')
179
+ .data('minicolors-initialized', false)
180
+ .data('minicolors-settings', settings)
181
+ .prop('size', size)
182
+ .wrap(minicolors)
183
+ .after(
184
+ '<div class="minicolors-panel minicolors-slider-' + settings.control + '">' +
185
+ '<div class="minicolors-slider minicolors-sprite">' +
186
+ '<div class="minicolors-picker"></div>' +
187
+ '</div>' +
188
+ '<div class="minicolors-opacity-slider minicolors-sprite">' +
189
+ '<div class="minicolors-picker"></div>' +
190
+ '</div>' +
191
+ '<div class="minicolors-grid minicolors-sprite">' +
192
+ '<div class="minicolors-grid-inner"></div>' +
193
+ '<div class="minicolors-picker"><div></div></div>' +
194
+ '</div>' +
195
+ '</div>'
196
+ );
197
+
198
+ // The swatch
199
+ if(!settings.inline) {
200
+ input.after('<span class="minicolors-swatch minicolors-sprite minicolors-input-swatch"><span class="minicolors-swatch-color"></span></span>');
201
+ input.next('.minicolors-input-swatch').on('click', function(event) {
202
+ event.preventDefault();
203
+ input.focus();
204
+ });
205
+ }
206
+
207
+ // Prevent text selection in IE
208
+ panel = input.parent().find('.minicolors-panel');
209
+ panel.on('selectstart', function() { return false; }).end();
210
+
211
+ // Swatches
212
+ if(settings.swatches && settings.swatches.length !== 0) {
213
+ panel.addClass('minicolors-with-swatches');
214
+ swatches = $('<ul class="minicolors-swatches"></ul>')
215
+ .appendTo(panel);
216
+ for(i = 0; i < settings.swatches.length; ++i) {
217
+ swatch = settings.swatches[i];
218
+ swatch = isRgb(swatch) ? parseRgb(swatch, true) : hex2rgb(parseHex(swatch, true));
219
+ $('<li class="minicolors-swatch minicolors-sprite"><span class="minicolors-swatch-color"></span></li>')
220
+ .appendTo(swatches)
221
+ .data('swatch-color', settings.swatches[i])
222
+ .find('.minicolors-swatch-color')
223
+ .css({
224
+ backgroundColor: rgb2hex(swatch),
225
+ opacity: swatch.a
226
+ });
227
+ settings.swatches[i] = swatch;
228
+ }
229
+ }
230
+
231
+ // Inline controls
232
+ if(settings.inline) input.parent().addClass('minicolors-inline');
233
+
234
+ updateFromInput(input, false);
235
+
236
+ input.data('minicolors-initialized', true);
237
+ }
238
+
239
+ // Returns the input back to its original state
240
+ function destroy(input) {
241
+ var minicolors = input.parent();
242
+
243
+ // Revert the input element
244
+ input
245
+ .removeData('minicolors-initialized')
246
+ .removeData('minicolors-settings')
247
+ .removeProp('size')
248
+ .removeClass('minicolors-input');
249
+
250
+ // Remove the wrap and destroy whatever remains
251
+ minicolors.before(input).remove();
252
+ }
253
+
254
+ // Shows the specified dropdown panel
255
+ function show(input) {
256
+ var minicolors = input.parent();
257
+ var panel = minicolors.find('.minicolors-panel');
258
+ var settings = input.data('minicolors-settings');
259
+
260
+ // Do nothing if uninitialized, disabled, inline, or already open
261
+ if(
262
+ !input.data('minicolors-initialized') ||
263
+ input.prop('disabled') ||
264
+ minicolors.hasClass('minicolors-inline') ||
265
+ minicolors.hasClass('minicolors-focus')
266
+ ) return;
267
+
268
+ hide();
269
+
270
+ minicolors.addClass('minicolors-focus');
271
+ panel
272
+ .stop(true, true)
273
+ .fadeIn(settings.showSpeed, function() {
274
+ if(settings.show) settings.show.call(input.get(0));
275
+ });
276
+ }
277
+
278
+ // Hides all dropdown panels
279
+ function hide() {
280
+ $('.minicolors-focus').each(function() {
281
+ var minicolors = $(this);
282
+ var input = minicolors.find('.minicolors-input');
283
+ var panel = minicolors.find('.minicolors-panel');
284
+ var settings = input.data('minicolors-settings');
285
+
286
+ panel.fadeOut(settings.hideSpeed, function() {
287
+ if(settings.hide) settings.hide.call(input.get(0));
288
+ minicolors.removeClass('minicolors-focus');
289
+ });
290
+
291
+ });
292
+ }
293
+
294
+ // Moves the selected picker
295
+ function move(target, event, animate) {
296
+ var input = target.parents('.minicolors').find('.minicolors-input');
297
+ var settings = input.data('minicolors-settings');
298
+ var picker = target.find('[class$=-picker]');
299
+ var offsetX = target.offset().left;
300
+ var offsetY = target.offset().top;
301
+ var x = Math.round(event.pageX - offsetX);
302
+ var y = Math.round(event.pageY - offsetY);
303
+ var duration = animate ? settings.animationSpeed : 0;
304
+ var wx, wy, r, phi;
305
+
306
+ // Touch support
307
+ if(event.originalEvent.changedTouches) {
308
+ x = event.originalEvent.changedTouches[0].pageX - offsetX;
309
+ y = event.originalEvent.changedTouches[0].pageY - offsetY;
310
+ }
311
+
312
+ // Constrain picker to its container
313
+ if(x < 0) x = 0;
314
+ if(y < 0) y = 0;
315
+ if(x > target.width()) x = target.width();
316
+ if(y > target.height()) y = target.height();
317
+
318
+ // Constrain color wheel values to the wheel
319
+ if(target.parent().is('.minicolors-slider-wheel') && picker.parent().is('.minicolors-grid')) {
320
+ wx = 75 - x;
321
+ wy = 75 - y;
322
+ r = Math.sqrt(wx * wx + wy * wy);
323
+ phi = Math.atan2(wy, wx);
324
+ if(phi < 0) phi += Math.PI * 2;
325
+ if(r > 75) {
326
+ r = 75;
327
+ x = 75 - (75 * Math.cos(phi));
328
+ y = 75 - (75 * Math.sin(phi));
329
+ }
330
+ x = Math.round(x);
331
+ y = Math.round(y);
332
+ }
333
+
334
+ // Move the picker
335
+ if(target.is('.minicolors-grid')) {
336
+ picker
337
+ .stop(true)
338
+ .animate({
339
+ top: y + 'px',
340
+ left: x + 'px'
341
+ }, duration, settings.animationEasing, function() {
342
+ updateFromControl(input, target);
343
+ });
344
+ } else {
345
+ picker
346
+ .stop(true)
347
+ .animate({
348
+ top: y + 'px'
349
+ }, duration, settings.animationEasing, function() {
350
+ updateFromControl(input, target);
351
+ });
352
+ }
353
+ }
354
+
355
+ // Sets the input based on the color picker values
356
+ function updateFromControl(input, target) {
357
+
358
+ function getCoords(picker, container) {
359
+ var left, top;
360
+ if(!picker.length || !container) return null;
361
+ left = picker.offset().left;
362
+ top = picker.offset().top;
363
+
364
+ return {
365
+ x: left - container.offset().left + (picker.outerWidth() / 2),
366
+ y: top - container.offset().top + (picker.outerHeight() / 2)
367
+ };
368
+ }
369
+
370
+ var hue, saturation, brightness, x, y, r, phi;
371
+ var hex = input.val();
372
+ var opacity = input.attr('data-opacity');
373
+
374
+ // Helpful references
375
+ var minicolors = input.parent();
376
+ var settings = input.data('minicolors-settings');
377
+ var swatch = minicolors.find('.minicolors-input-swatch');
378
+
379
+ // Panel objects
380
+ var grid = minicolors.find('.minicolors-grid');
381
+ var slider = minicolors.find('.minicolors-slider');
382
+ var opacitySlider = minicolors.find('.minicolors-opacity-slider');
383
+
384
+ // Picker objects
385
+ var gridPicker = grid.find('[class$=-picker]');
386
+ var sliderPicker = slider.find('[class$=-picker]');
387
+ var opacityPicker = opacitySlider.find('[class$=-picker]');
388
+
389
+ // Picker positions
390
+ var gridPos = getCoords(gridPicker, grid);
391
+ var sliderPos = getCoords(sliderPicker, slider);
392
+ var opacityPos = getCoords(opacityPicker, opacitySlider);
393
+
394
+ // Handle colors
395
+ if(target.is('.minicolors-grid, .minicolors-slider, .minicolors-opacity-slider')) {
396
+
397
+ // Determine HSB values
398
+ switch(settings.control) {
399
+ case 'wheel':
400
+ // Calculate hue, saturation, and brightness
401
+ x = (grid.width() / 2) - gridPos.x;
402
+ y = (grid.height() / 2) - gridPos.y;
403
+ r = Math.sqrt(x * x + y * y);
404
+ phi = Math.atan2(y, x);
405
+ if(phi < 0) phi += Math.PI * 2;
406
+ if(r > 75) {
407
+ r = 75;
408
+ gridPos.x = 69 - (75 * Math.cos(phi));
409
+ gridPos.y = 69 - (75 * Math.sin(phi));
410
+ }
411
+ saturation = keepWithin(r / 0.75, 0, 100);
412
+ hue = keepWithin(phi * 180 / Math.PI, 0, 360);
413
+ brightness = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100);
414
+ hex = hsb2hex({
415
+ h: hue,
416
+ s: saturation,
417
+ b: brightness
418
+ });
419
+
420
+ // Update UI
421
+ slider.css('backgroundColor', hsb2hex({ h: hue, s: saturation, b: 100 }));
422
+ break;
423
+
424
+ case 'saturation':
425
+ // Calculate hue, saturation, and brightness
426
+ hue = keepWithin(parseInt(gridPos.x * (360 / grid.width()), 10), 0, 360);
427
+ saturation = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100);
428
+ brightness = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100);
429
+ hex = hsb2hex({
430
+ h: hue,
431
+ s: saturation,
432
+ b: brightness
433
+ });
434
+
435
+ // Update UI
436
+ slider.css('backgroundColor', hsb2hex({ h: hue, s: 100, b: brightness }));
437
+ minicolors.find('.minicolors-grid-inner').css('opacity', saturation / 100);
438
+ break;
439
+
440
+ case 'brightness':
441
+ // Calculate hue, saturation, and brightness
442
+ hue = keepWithin(parseInt(gridPos.x * (360 / grid.width()), 10), 0, 360);
443
+ saturation = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100);
444
+ brightness = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100);
445
+ hex = hsb2hex({
446
+ h: hue,
447
+ s: saturation,
448
+ b: brightness
449
+ });
450
+
451
+ // Update UI
452
+ slider.css('backgroundColor', hsb2hex({ h: hue, s: saturation, b: 100 }));
453
+ minicolors.find('.minicolors-grid-inner').css('opacity', 1 - (brightness / 100));
454
+ break;
455
+
456
+ default:
457
+ // Calculate hue, saturation, and brightness
458
+ hue = keepWithin(360 - parseInt(sliderPos.y * (360 / slider.height()), 10), 0, 360);
459
+ saturation = keepWithin(Math.floor(gridPos.x * (100 / grid.width())), 0, 100);
460
+ brightness = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100);
461
+ hex = hsb2hex({
462
+ h: hue,
463
+ s: saturation,
464
+ b: brightness
465
+ });
466
+
467
+ // Update UI
468
+ grid.css('backgroundColor', hsb2hex({ h: hue, s: 100, b: 100 }));
469
+ break;
470
+ }
471
+
472
+ // Handle opacity
473
+ if(settings.opacity) {
474
+ opacity = parseFloat(1 - (opacityPos.y / opacitySlider.height())).toFixed(2);
475
+ } else {
476
+ opacity = 1;
477
+ }
478
+
479
+ updateInput(input, hex, opacity);
480
+ }
481
+ else {
482
+ // Set swatch color
483
+ swatch.find('span').css({
484
+ backgroundColor: hex,
485
+ opacity: opacity
486
+ });
487
+
488
+ // Handle change event
489
+ doChange(input, hex, opacity);
490
+ }
491
+ }
492
+
493
+ // Sets the value of the input and does the appropriate conversions
494
+ // to respect settings, also updates the swatch
495
+ function updateInput(input, value, opacity) {
496
+ var rgb;
497
+
498
+ // Helpful references
499
+ var minicolors = input.parent();
500
+ var settings = input.data('minicolors-settings');
501
+ var swatch = minicolors.find('.minicolors-input-swatch');
502
+
503
+ if(settings.opacity) input.attr('data-opacity', opacity);
504
+
505
+ // Set color string
506
+ if(settings.format === 'rgb') {
507
+ // Returns RGB(A) string
508
+
509
+ // Checks for input format and does the conversion
510
+ if(isRgb(value)) {
511
+ rgb = parseRgb(value, true);
512
+ }
513
+ else {
514
+ rgb = hex2rgb(parseHex(value, true));
515
+ }
516
+
517
+ opacity = input.attr('data-opacity') === '' ? 1 : keepWithin(parseFloat(input.attr('data-opacity')).toFixed(2), 0, 1);
518
+ if(isNaN(opacity) || !settings.opacity) opacity = 1;
519
+
520
+ if(input.minicolors('rgbObject').a <= 1 && rgb && settings.opacity) {
521
+ // Set RGBA string if alpha
522
+ value = 'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + parseFloat(opacity) + ')';
523
+ } else {
524
+ // Set RGB string (alpha = 1)
525
+ value = 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')';
526
+ }
527
+ } else {
528
+ // Returns hex color
529
+
530
+ // Checks for input format and does the conversion
531
+ if(isRgb(value)) {
532
+ value = rgbString2hex(value);
533
+ }
534
+
535
+ value = convertCase(value, settings.letterCase);
536
+ }
537
+
538
+ // Update value from picker
539
+ input.val(value);
540
+
541
+ // Set swatch color
542
+ swatch.find('span').css({
543
+ backgroundColor: value,
544
+ opacity: opacity
545
+ });
546
+
547
+ // Handle change event
548
+ doChange(input, value, opacity);
549
+ }
550
+
551
+ // Sets the color picker values from the input
552
+ function updateFromInput(input, preserveInputValue) {
553
+ var hex, hsb, opacity, keywords, alpha, value, x, y, r, phi;
554
+
555
+ // Helpful references
556
+ var minicolors = input.parent();
557
+ var settings = input.data('minicolors-settings');
558
+ var swatch = minicolors.find('.minicolors-input-swatch');
559
+
560
+ // Panel objects
561
+ var grid = minicolors.find('.minicolors-grid');
562
+ var slider = minicolors.find('.minicolors-slider');
563
+ var opacitySlider = minicolors.find('.minicolors-opacity-slider');
564
+
565
+ // Picker objects
566
+ var gridPicker = grid.find('[class$=-picker]');
567
+ var sliderPicker = slider.find('[class$=-picker]');
568
+ var opacityPicker = opacitySlider.find('[class$=-picker]');
569
+
570
+ // Determine hex/HSB values
571
+ if(isRgb(input.val())) {
572
+ // If input value is a rgb(a) string, convert it to hex color and update opacity
573
+ hex = rgbString2hex(input.val());
574
+ alpha = keepWithin(parseFloat(getAlpha(input.val())).toFixed(2), 0, 1);
575
+ if(alpha) {
576
+ input.attr('data-opacity', alpha);
577
+ }
578
+ } else {
579
+ hex = convertCase(parseHex(input.val(), true), settings.letterCase);
580
+ }
581
+
582
+ if(!hex){
583
+ hex = convertCase(parseInput(settings.defaultValue, true), settings.letterCase);
584
+ }
585
+ hsb = hex2hsb(hex);
586
+
587
+ // Get array of lowercase keywords
588
+ keywords = !settings.keywords ? [] : $.map(settings.keywords.split(','), function(a) {
589
+ return $.trim(a.toLowerCase());
590
+ });
591
+
592
+ // Set color string
593
+ if(input.val() !== '' && $.inArray(input.val().toLowerCase(), keywords) > -1) {
594
+ value = convertCase(input.val());
595
+ } else {
596
+ value = isRgb(input.val()) ? parseRgb(input.val()) : hex;
597
+ }
598
+
599
+ // Update input value
600
+ if(!preserveInputValue) input.val(value);
601
+
602
+ // Determine opacity value
603
+ if(settings.opacity) {
604
+ // Get from data-opacity attribute and keep within 0-1 range
605
+ opacity = input.attr('data-opacity') === '' ? 1 : keepWithin(parseFloat(input.attr('data-opacity')).toFixed(2), 0, 1);
606
+ if(isNaN(opacity)) opacity = 1;
607
+ input.attr('data-opacity', opacity);
608
+ swatch.find('span').css('opacity', opacity);
609
+
610
+ // Set opacity picker position
611
+ y = keepWithin(opacitySlider.height() - (opacitySlider.height() * opacity), 0, opacitySlider.height());
612
+ opacityPicker.css('top', y + 'px');
613
+ }
614
+
615
+ // Set opacity to zero if input value is transparent
616
+ if(input.val().toLowerCase() === 'transparent') {
617
+ swatch.find('span').css('opacity', 0);
618
+ }
619
+
620
+ // Update swatch
621
+ swatch.find('span').css('backgroundColor', hex);
622
+
623
+ // Determine picker locations
624
+ switch(settings.control) {
625
+ case 'wheel':
626
+ // Set grid position
627
+ r = keepWithin(Math.ceil(hsb.s * 0.75), 0, grid.height() / 2);
628
+ phi = hsb.h * Math.PI / 180;
629
+ x = keepWithin(75 - Math.cos(phi) * r, 0, grid.width());
630
+ y = keepWithin(75 - Math.sin(phi) * r, 0, grid.height());
631
+ gridPicker.css({
632
+ top: y + 'px',
633
+ left: x + 'px'
634
+ });
635
+
636
+ // Set slider position
637
+ y = 150 - (hsb.b / (100 / grid.height()));
638
+ if(hex === '') y = 0;
639
+ sliderPicker.css('top', y + 'px');
640
+
641
+ // Update panel color
642
+ slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: hsb.s, b: 100 }));
643
+ break;
644
+
645
+ case 'saturation':
646
+ // Set grid position
647
+ x = keepWithin((5 * hsb.h) / 12, 0, 150);
648
+ y = keepWithin(grid.height() - Math.ceil(hsb.b / (100 / grid.height())), 0, grid.height());
649
+ gridPicker.css({
650
+ top: y + 'px',
651
+ left: x + 'px'
652
+ });
653
+
654
+ // Set slider position
655
+ y = keepWithin(slider.height() - (hsb.s * (slider.height() / 100)), 0, slider.height());
656
+ sliderPicker.css('top', y + 'px');
657
+
658
+ // Update UI
659
+ slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: 100, b: hsb.b }));
660
+ minicolors.find('.minicolors-grid-inner').css('opacity', hsb.s / 100);
661
+ break;
662
+
663
+ case 'brightness':
664
+ // Set grid position
665
+ x = keepWithin((5 * hsb.h) / 12, 0, 150);
666
+ y = keepWithin(grid.height() - Math.ceil(hsb.s / (100 / grid.height())), 0, grid.height());
667
+ gridPicker.css({
668
+ top: y + 'px',
669
+ left: x + 'px'
670
+ });
671
+
672
+ // Set slider position
673
+ y = keepWithin(slider.height() - (hsb.b * (slider.height() / 100)), 0, slider.height());
674
+ sliderPicker.css('top', y + 'px');
675
+
676
+ // Update UI
677
+ slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: hsb.s, b: 100 }));
678
+ minicolors.find('.minicolors-grid-inner').css('opacity', 1 - (hsb.b / 100));
679
+ break;
680
+
681
+ default:
682
+ // Set grid position
683
+ x = keepWithin(Math.ceil(hsb.s / (100 / grid.width())), 0, grid.width());
684
+ y = keepWithin(grid.height() - Math.ceil(hsb.b / (100 / grid.height())), 0, grid.height());
685
+ gridPicker.css({
686
+ top: y + 'px',
687
+ left: x + 'px'
688
+ });
689
+
690
+ // Set slider position
691
+ y = keepWithin(slider.height() - (hsb.h / (360 / slider.height())), 0, slider.height());
692
+ sliderPicker.css('top', y + 'px');
693
+
694
+ // Update panel color
695
+ grid.css('backgroundColor', hsb2hex({ h: hsb.h, s: 100, b: 100 }));
696
+ break;
697
+ }
698
+
699
+ // Fire change event, but only if minicolors is fully initialized
700
+ if(input.data('minicolors-initialized')) {
701
+ doChange(input, value, opacity);
702
+ }
703
+ }
704
+
705
+ // Runs the change and changeDelay callbacks
706
+ function doChange(input, value, opacity) {
707
+ var settings = input.data('minicolors-settings');
708
+ var lastChange = input.data('minicolors-lastChange');
709
+ var obj, sel, i;
710
+
711
+ // Only run if it actually changed
712
+ if(!lastChange || lastChange.value !== value || lastChange.opacity !== opacity) {
713
+
714
+ // Remember last-changed value
715
+ input.data('minicolors-lastChange', {
716
+ value: value,
717
+ opacity: opacity
718
+ });
719
+
720
+ // Check and select applicable swatch
721
+ if(settings.swatches && settings.swatches.length !== 0) {
722
+ if(!isRgb(value)) {
723
+ obj = hex2rgb(value);
724
+ }
725
+ else {
726
+ obj = parseRgb(value, true);
727
+ }
728
+ sel = -1;
729
+ for(i = 0; i < settings.swatches.length; ++i) {
730
+ if(obj.r === settings.swatches[i].r && obj.g === settings.swatches[i].g && obj.b === settings.swatches[i].b && obj.a === settings.swatches[i].a) {
731
+ sel = i;
732
+ break;
733
+ }
734
+ }
735
+
736
+ input.parent().find('.minicolors-swatches .minicolors-swatch').removeClass('selected');
737
+ if(sel !== -1) {
738
+ input.parent().find('.minicolors-swatches .minicolors-swatch').eq(i).addClass('selected');
739
+ }
740
+ }
741
+
742
+ // Fire change event
743
+ if(settings.change) {
744
+ if(settings.changeDelay) {
745
+ // Call after a delay
746
+ clearTimeout(input.data('minicolors-changeTimeout'));
747
+ input.data('minicolors-changeTimeout', setTimeout(function() {
748
+ settings.change.call(input.get(0), value, opacity);
749
+ }, settings.changeDelay));
750
+ } else {
751
+ // Call immediately
752
+ settings.change.call(input.get(0), value, opacity);
753
+ }
754
+ }
755
+ input.trigger('change').trigger('input');
756
+ }
757
+ }
758
+
759
+ // Generates an RGB(A) object based on the input's value
760
+ function rgbObject(input) {
761
+ var rgb,
762
+ opacity = $(input).attr('data-opacity');
763
+ if( isRgb($(input).val()) ) {
764
+ rgb = parseRgb($(input).val(), true);
765
+ } else {
766
+ var hex = parseHex($(input).val(), true);
767
+ rgb = hex2rgb(hex);
768
+ }
769
+ if( !rgb ) return null;
770
+ if( opacity !== undefined ) $.extend(rgb, { a: parseFloat(opacity) });
771
+ return rgb;
772
+ }
773
+
774
+ // Generates an RGB(A) string based on the input's value
775
+ function rgbString(input, alpha) {
776
+ var rgb,
777
+ opacity = $(input).attr('data-opacity');
778
+ if( isRgb($(input).val()) ) {
779
+ rgb = parseRgb($(input).val(), true);
780
+ } else {
781
+ var hex = parseHex($(input).val(), true);
782
+ rgb = hex2rgb(hex);
783
+ }
784
+ if( !rgb ) return null;
785
+ if( opacity === undefined ) opacity = 1;
786
+ if( alpha ) {
787
+ return 'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + parseFloat(opacity) + ')';
788
+ } else {
789
+ return 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')';
790
+ }
791
+ }
792
+
793
+ // Converts to the letter case specified in settings
794
+ function convertCase(string, letterCase) {
795
+ return letterCase === 'uppercase' ? string.toUpperCase() : string.toLowerCase();
796
+ }
797
+
798
+ // Parses a string and returns a valid hex string when possible
799
+ function parseHex(string, expand) {
800
+ string = string.replace(/^#/g, '');
801
+ if(!string.match(/^[A-F0-9]{3,6}/ig)) return '';
802
+ if(string.length !== 3 && string.length !== 6) return '';
803
+ if(string.length === 3 && expand) {
804
+ string = string[0] + string[0] + string[1] + string[1] + string[2] + string[2];
805
+ }
806
+ return '#' + string;
807
+ }
808
+
809
+ // Parses a string and returns a valid RGB(A) string when possible
810
+ function parseRgb(string, obj) {
811
+ var values = string.replace(/[^\d,.]/g, '');
812
+ var rgba = values.split(',');
813
+
814
+ rgba[0] = keepWithin(parseInt(rgba[0], 10), 0, 255);
815
+ rgba[1] = keepWithin(parseInt(rgba[1], 10), 0, 255);
816
+ rgba[2] = keepWithin(parseInt(rgba[2], 10), 0, 255);
817
+ if(rgba[3]) {
818
+ rgba[3] = keepWithin(parseFloat(rgba[3], 10), 0, 1);
819
+ }
820
+
821
+ // Return RGBA object
822
+ if( obj ) {
823
+ if (rgba[3]) {
824
+ return {
825
+ r: rgba[0],
826
+ g: rgba[1],
827
+ b: rgba[2],
828
+ a: rgba[3]
829
+ };
830
+ } else {
831
+ return {
832
+ r: rgba[0],
833
+ g: rgba[1],
834
+ b: rgba[2]
835
+ };
836
+ }
837
+ }
838
+
839
+ // Return RGBA string
840
+ if(typeof(rgba[3]) !== 'undefined' && rgba[3] <= 1) {
841
+ return 'rgba(' + rgba[0] + ', ' + rgba[1] + ', ' + rgba[2] + ', ' + rgba[3] + ')';
842
+ } else {
843
+ return 'rgb(' + rgba[0] + ', ' + rgba[1] + ', ' + rgba[2] + ')';
844
+ }
845
+
846
+ }
847
+
848
+ // Parses a string and returns a valid color string when possible
849
+ function parseInput(string, expand) {
850
+ if(isRgb(string)) {
851
+ // Returns a valid rgb(a) string
852
+ return parseRgb(string);
853
+ } else {
854
+ return parseHex(string, expand);
855
+ }
856
+ }
857
+
858
+ // Keeps value within min and max
859
+ function keepWithin(value, min, max) {
860
+ if(value < min) value = min;
861
+ if(value > max) value = max;
862
+ return value;
863
+ }
864
+
865
+ // Checks if a string is a valid RGB(A) string
866
+ function isRgb(string) {
867
+ var rgb = string.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
868
+ return (rgb && rgb.length === 4) ? true : false;
869
+ }
870
+
871
+ // Function to get alpha from a RGB(A) string
872
+ function getAlpha(rgba) {
873
+ rgba = rgba.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+(\.\d{1,2})?|\.\d{1,2})[\s+]?/i);
874
+ return (rgba && rgba.length === 6) ? rgba[4] : '1';
875
+ }
876
+
877
+ // Converts an HSB object to an RGB object
878
+ function hsb2rgb(hsb) {
879
+ var rgb = {};
880
+ var h = Math.round(hsb.h);
881
+ var s = Math.round(hsb.s * 255 / 100);
882
+ var v = Math.round(hsb.b * 255 / 100);
883
+ if(s === 0) {
884
+ rgb.r = rgb.g = rgb.b = v;
885
+ } else {
886
+ var t1 = v;
887
+ var t2 = (255 - s) * v / 255;
888
+ var t3 = (t1 - t2) * (h % 60) / 60;
889
+ if(h === 360) h = 0;
890
+ if(h < 60) { rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3; }
891
+ else if(h < 120) {rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3; }
892
+ else if(h < 180) {rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3; }
893
+ else if(h < 240) {rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3; }
894
+ else if(h < 300) {rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3; }
895
+ else if(h < 360) {rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3; }
896
+ else { rgb.r = 0; rgb.g = 0; rgb.b = 0; }
897
+ }
898
+ return {
899
+ r: Math.round(rgb.r),
900
+ g: Math.round(rgb.g),
901
+ b: Math.round(rgb.b)
902
+ };
903
+ }
904
+
905
+ // Converts an RGB string to a hex string
906
+ function rgbString2hex(rgb){
907
+ rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
908
+ return (rgb && rgb.length === 4) ? '#' +
909
+ ('0' + parseInt(rgb[1],10).toString(16)).slice(-2) +
910
+ ('0' + parseInt(rgb[2],10).toString(16)).slice(-2) +
911
+ ('0' + parseInt(rgb[3],10).toString(16)).slice(-2) : '';
912
+ }
913
+
914
+ // Converts an RGB object to a hex string
915
+ function rgb2hex(rgb) {
916
+ var hex = [
917
+ rgb.r.toString(16),
918
+ rgb.g.toString(16),
919
+ rgb.b.toString(16)
920
+ ];
921
+ $.each(hex, function(nr, val) {
922
+ if(val.length === 1) hex[nr] = '0' + val;
923
+ });
924
+ return '#' + hex.join('');
925
+ }
926
+
927
+ // Converts an HSB object to a hex string
928
+ function hsb2hex(hsb) {
929
+ return rgb2hex(hsb2rgb(hsb));
930
+ }
931
+
932
+ // Converts a hex string to an HSB object
933
+ function hex2hsb(hex) {
934
+ var hsb = rgb2hsb(hex2rgb(hex));
935
+ if(hsb.s === 0) hsb.h = 360;
936
+ return hsb;
937
+ }
938
+
939
+ // Converts an RGB object to an HSB object
940
+ function rgb2hsb(rgb) {
941
+ var hsb = { h: 0, s: 0, b: 0 };
942
+ var min = Math.min(rgb.r, rgb.g, rgb.b);
943
+ var max = Math.max(rgb.r, rgb.g, rgb.b);
944
+ var delta = max - min;
945
+ hsb.b = max;
946
+ hsb.s = max !== 0 ? 255 * delta / max : 0;
947
+ if(hsb.s !== 0) {
948
+ if(rgb.r === max) {
949
+ hsb.h = (rgb.g - rgb.b) / delta;
950
+ } else if(rgb.g === max) {
951
+ hsb.h = 2 + (rgb.b - rgb.r) / delta;
952
+ } else {
953
+ hsb.h = 4 + (rgb.r - rgb.g) / delta;
954
+ }
955
+ } else {
956
+ hsb.h = -1;
957
+ }
958
+ hsb.h *= 60;
959
+ if(hsb.h < 0) {
960
+ hsb.h += 360;
961
+ }
962
+ hsb.s *= 100/255;
963
+ hsb.b *= 100/255;
964
+ return hsb;
965
+ }
966
+
967
+ // Converts a hex string to an RGB object
968
+ function hex2rgb(hex) {
969
+ hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
970
+ return {
971
+ r: hex >> 16,
972
+ g: (hex & 0x00FF00) >> 8,
973
+ b: (hex & 0x0000FF)
974
+ };
975
+ }
976
+
977
+ // Handle events
978
+ $([document])
979
+ // Hide on clicks outside of the control
980
+ .on('mousedown.minicolors touchstart.minicolors', function(event) {
981
+ if(!$(event.target).parents().add(event.target).hasClass('minicolors')) {
982
+ hide();
983
+ }
984
+ })
985
+ // Start moving
986
+ .on('mousedown.minicolors touchstart.minicolors', '.minicolors-grid, .minicolors-slider, .minicolors-opacity-slider', function(event) {
987
+ var target = $(this);
988
+ event.preventDefault();
989
+ $(event.delegateTarget).data('minicolors-target', target);
990
+ move(target, event, true);
991
+ })
992
+ // Move pickers
993
+ .on('mousemove.minicolors touchmove.minicolors', function(event) {
994
+ var target = $(event.delegateTarget).data('minicolors-target');
995
+ if(target) move(target, event);
996
+ })
997
+ // Stop moving
998
+ .on('mouseup.minicolors touchend.minicolors', function() {
999
+ $(this).removeData('minicolors-target');
1000
+ })
1001
+ // Selected a swatch
1002
+ .on('click.minicolors', '.minicolors-swatches li', function(event) {
1003
+ event.preventDefault();
1004
+ var target = $(this), input = target.parents('.minicolors').find('.minicolors-input'), color = target.data('swatch-color');
1005
+ updateInput(input, color, getAlpha(color));
1006
+ updateFromInput(input);
1007
+ })
1008
+ // Show panel when swatch is clicked
1009
+ .on('mousedown.minicolors touchstart.minicolors', '.minicolors-input-swatch', function(event) {
1010
+ var input = $(this).parent().find('.minicolors-input');
1011
+ event.preventDefault();
1012
+ show(input);
1013
+ })
1014
+ // Show on focus
1015
+ .on('focus.minicolors', '.minicolors-input', function() {
1016
+ var input = $(this);
1017
+ if(!input.data('minicolors-initialized')) return;
1018
+ show(input);
1019
+ })
1020
+ // Update value on blur
1021
+ .on('blur.minicolors', '.minicolors-input', function() {
1022
+ var input = $(this);
1023
+ var settings = input.data('minicolors-settings');
1024
+ var keywords;
1025
+ var hex;
1026
+ var rgba;
1027
+ var swatchOpacity;
1028
+ var value;
1029
+
1030
+ if(!input.data('minicolors-initialized')) return;
1031
+
1032
+ // Get array of lowercase keywords
1033
+ keywords = !settings.keywords ? [] : $.map(settings.keywords.split(','), function(a) {
1034
+ return $.trim(a.toLowerCase());
1035
+ });
1036
+
1037
+ // Set color string
1038
+ if(input.val() !== '' && $.inArray(input.val().toLowerCase(), keywords) > -1) {
1039
+ value = input.val();
1040
+ } else {
1041
+ // Get RGBA values for easy conversion
1042
+ if(isRgb(input.val())) {
1043
+ rgba = parseRgb(input.val(), true);
1044
+ } else {
1045
+ hex = parseHex(input.val(), true);
1046
+ rgba = hex ? hex2rgb(hex) : null;
1047
+ }
1048
+
1049
+ // Convert to format
1050
+ if(rgba === null) {
1051
+ value = settings.defaultValue;
1052
+ } else if(settings.format === 'rgb') {
1053
+ value = settings.opacity ?
1054
+ parseRgb('rgba(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ',' + input.attr('data-opacity') + ')') :
1055
+ parseRgb('rgb(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ')');
1056
+ } else {
1057
+ value = rgb2hex(rgba);
1058
+ }
1059
+ }
1060
+
1061
+ // Update swatch opacity
1062
+ swatchOpacity = settings.opacity ? input.attr('data-opacity') : 1;
1063
+ if(value.toLowerCase() === 'transparent') swatchOpacity = 0;
1064
+ input
1065
+ .closest('.minicolors')
1066
+ .find('.minicolors-input-swatch > span')
1067
+ .css('opacity', swatchOpacity);
1068
+
1069
+ // Set input value
1070
+ input.val(value);
1071
+
1072
+ // Is it blank?
1073
+ if(input.val() === '') input.val(parseInput(settings.defaultValue, true));
1074
+
1075
+ // Adjust case
1076
+ input.val(convertCase(input.val(), settings.letterCase));
1077
+
1078
+ })
1079
+ // Handle keypresses
1080
+ .on('keydown.minicolors', '.minicolors-input', function(event) {
1081
+ var input = $(this);
1082
+ if(!input.data('minicolors-initialized')) return;
1083
+ switch(event.keyCode) {
1084
+ case 9: // tab
1085
+ hide();
1086
+ break;
1087
+ case 13: // enter
1088
+ case 27: // esc
1089
+ hide();
1090
+ input.blur();
1091
+ break;
1092
+ }
1093
+ })
1094
+ // Update on keyup
1095
+ .on('keyup.minicolors', '.minicolors-input', function() {
1096
+ var input = $(this);
1097
+ if(!input.data('minicolors-initialized')) return;
1098
+ updateFromInput(input, true);
1099
+ })
1100
+ // Update on paste
1101
+ .on('paste.minicolors', '.minicolors-input', function() {
1102
+ var input = $(this);
1103
+ if(!input.data('minicolors-initialized')) return;
1104
+ setTimeout(function() {
1105
+ updateFromInput(input, true);
1106
+ }, 1);
1107
+ });
1108
+ }));
includes/controls/controls.php CHANGED
@@ -255,6 +255,13 @@ class smartlogixControls {
255
  if($args['helpText'] != '') { $HTML .= '<small>'.$args['helpText'].'</small>'; }
256
  if($args['useParagraph']) { $HTML .= '</p>'; }
257
  break;
 
 
 
 
 
 
 
258
  case 'textarea':
259
  if($args['useParagraph']) { $HTML .= '<p>'; }
260
  if($args['label'] != '') { $HTML .= '<label '.(($args['name'] != '')?'for="'.$args['name'].'"':'').'>'.$args['label'].'</label><br />'; }
@@ -290,7 +297,13 @@ class smartlogixControls {
290
  $HTML .= '<select '.(($args['id'] != '')?'id="'.$args['id'].'"':'').' '.(($args['name'] != '')?'name="'.$args['name'].'"':'').' '.(($args['value'] != '')?'value="'.$args['value'].'"':'').' '.(($args['className'] != '')?'class="'.$args['className'].'"':'').' '.(($args['style'] != '')?'style="'.$args['style'].'"':'').' '.(($args['required'])?'required':'').'>';
291
  if(is_array($args['options'])) {
292
  foreach($args['options'] as $option) {
293
- $HTML .= '<option '.(($option['value'] != '')?'value="'.$option['value'].'"':'').' '.selected((($args['value'] != '')?$args['value']:''), (($option['value'] != '')?$option['value']:''), false).'>'.(($option['text'] != '')?$option['text']:'').'</option>';
 
 
 
 
 
 
294
  }
295
  }
296
  $HTML .= '</select>';
@@ -341,6 +354,14 @@ class smartlogixControls {
341
  if($args['useParagraph']) { $HTML .= '</p>'; }
342
  $JS .= 'jQuery("#'.(($args['id'] != '')?$args['id']:'').'").ipCheckbox();';
343
  break;
 
 
 
 
 
 
 
 
344
  case 'textarea-wysiwyg':
345
  if($args['useParagraph']) { $HTML .= '<p>'; }
346
  if($args['label'] != '') { $HTML .= '<label '.(($args['name'] != '')?'for="'.$args['name'].'"':'').'>'.$args['label'].'</label><br />'; }
@@ -356,7 +377,7 @@ class smartlogixControls {
356
  } else {
357
  $HTML .= '<input type="checkbox" '.(($args['id'] != '')?'id="'.$args['id'].'"':'').' '.(($args['name'] != '')?'name="'.$args['name'].'"':'').' value="true" '.(($args['className'] != '')?'class="'.$args['className'].'"':'').' '.(($args['style'] != '')?'style="'.$args['style'].'"':'').' '.(($args['required'])?'required':'').' />';
358
  }
359
- if($args['label'] != '') { $HTML .= '&nbsp;<label for="'.(($args['id'] != '')?$args['id']:'').'">'.$args['label'].'</label>'; }
360
  if($args['helpText'] != '') { $HTML .= '<small>'.$args['helpText'].'</small>'; }
361
  if($args['useParagraph']) { $HTML .= '</p>'; }
362
  $JS .= 'jQuery("#'.(($args['id'] != '')?$args['id']:'').'").button({ create: function(event, ui) { jQuery(this).button("option", "label", (jQuery(this).is(":checked")?"'.(($args['checkedLabel'] != '')?$args['checkedLabel']:'').'":"'.(($args['uncheckedLabel'] != '')?$args['uncheckedLabel']:'').'")) }}).change(function () { jQuery(this).button("option", "label", (jQuery(this).is(":checked")?"'.(($args['checkedLabel'] != '')?$args['checkedLabel']:'').'":"'.(($args['uncheckedLabel'] != '')?$args['uncheckedLabel']:'').'")); });';
255
  if($args['helpText'] != '') { $HTML .= '<small>'.$args['helpText'].'</small>'; }
256
  if($args['useParagraph']) { $HTML .= '</p>'; }
257
  break;
258
+ case 'password':
259
+ if($args['useParagraph']) { $HTML .= '<p>'; }
260
+ if($args['label'] != '') { $HTML .= '<label '.(($args['name'] != '')?'for="'.$args['name'].'"':'').'>'.$args['label'].'</label><br />'; }
261
+ $HTML .= '<input type="password" '.(($args['id'] != '')?'id="'.$args['id'].'"':'').' '.(($args['name'] != '')?'name="'.$args['name'].'"':'').' '.(($args['value'] != '')?'value="'.$args['value'].'"':'').' '.(($args['className'] != '')?'class="'.$args['className'].'"':'').' '.(($args['style'] != '')?'style="'.$args['style'].'"':'').' '.(($args['required'])?'required':'').' />';
262
+ if($args['helpText'] != '') { $HTML .= '<small>'.$args['helpText'].'</small>'; }
263
+ if($args['useParagraph']) { $HTML .= '</p>'; }
264
+ break;
265
  case 'textarea':
266
  if($args['useParagraph']) { $HTML .= '<p>'; }
267
  if($args['label'] != '') { $HTML .= '<label '.(($args['name'] != '')?'for="'.$args['name'].'"':'').'>'.$args['label'].'</label><br />'; }
297
  $HTML .= '<select '.(($args['id'] != '')?'id="'.$args['id'].'"':'').' '.(($args['name'] != '')?'name="'.$args['name'].'"':'').' '.(($args['value'] != '')?'value="'.$args['value'].'"':'').' '.(($args['className'] != '')?'class="'.$args['className'].'"':'').' '.(($args['style'] != '')?'style="'.$args['style'].'"':'').' '.(($args['required'])?'required':'').'>';
298
  if(is_array($args['options'])) {
299
  foreach($args['options'] as $option) {
300
+ $metadata = '';
301
+ if(isset($option['metadata']) && is_array($option['metadata'])) {
302
+ foreach($option['metadata'] as $key => $value) {
303
+ $metadata .= 'data-'.$key.'="'.$value.'"';
304
+ }
305
+ }
306
+ $HTML .= '<option '.$metadata.''.(($option['value'] != '')?'value="'.$option['value'].'"':'').' '.selected((($args['value'] != '')?$args['value']:''), (($option['value'] != '')?$option['value']:''), false).'>'.(($option['text'] != '')?$option['text']:'').'</option>';
307
  }
308
  }
309
  $HTML .= '</select>';
354
  if($args['useParagraph']) { $HTML .= '</p>'; }
355
  $JS .= 'jQuery("#'.(($args['id'] != '')?$args['id']:'').'").ipCheckbox();';
356
  break;
357
+ case 'minicolors':
358
+ if($args['useParagraph']) { $HTML .= '<p>'; }
359
+ if($args['label'] != '') { $HTML .= '<label '.(($args['name'] != '')?'for="'.$args['name'].'"':'').'>'.$args['label'].'</label><br />'; }
360
+ $HTML .= '<input type="text" '.(($args['id'] != '')?'id="'.$args['id'].'"':'').' '.(($args['name'] != '')?'name="'.$args['name'].'"':'').' '.(($args['value'] != '')?'value="'.$args['value'].'"':'').' '.(($args['className'] != '')?'class="'.$args['className'].'"':'').' '.(($args['style'] != '')?'style="'.$args['style'].'"':'').' '.(($args['required'])?'required':'').' />';
361
+ if($args['helpText'] != '') { $HTML .= '<small>'.$args['helpText'].'</small>'; }
362
+ if($args['useParagraph']) { $HTML .= '</p>'; }
363
+ $JS .= 'jQuery("#'.(($args['id'] != '')?$args['id']:'').'").minicolors();';
364
+ break;
365
  case 'textarea-wysiwyg':
366
  if($args['useParagraph']) { $HTML .= '<p>'; }
367
  if($args['label'] != '') { $HTML .= '<label '.(($args['name'] != '')?'for="'.$args['name'].'"':'').'>'.$args['label'].'</label><br />'; }
377
  } else {
378
  $HTML .= '<input type="checkbox" '.(($args['id'] != '')?'id="'.$args['id'].'"':'').' '.(($args['name'] != '')?'name="'.$args['name'].'"':'').' value="true" '.(($args['className'] != '')?'class="'.$args['className'].'"':'').' '.(($args['style'] != '')?'style="'.$args['style'].'"':'').' '.(($args['required'])?'required':'').' />';
379
  }
380
+ if($args['label'] != '') { $HTML .= '<label for="'.(($args['id'] != '')?$args['id']:'').'">'.$args['label'].'</label>'; }
381
  if($args['helpText'] != '') { $HTML .= '<small>'.$args['helpText'].'</small>'; }
382
  if($args['useParagraph']) { $HTML .= '</p>'; }
383
  $JS .= 'jQuery("#'.(($args['id'] != '')?$args['id']:'').'").button({ create: function(event, ui) { jQuery(this).button("option", "label", (jQuery(this).is(":checked")?"'.(($args['checkedLabel'] != '')?$args['checkedLabel']:'').'":"'.(($args['uncheckedLabel'] != '')?$args['uncheckedLabel']:'').'")) }}).change(function () { jQuery(this).button("option", "label", (jQuery(this).is(":checked")?"'.(($args['checkedLabel'] != '')?$args['checkedLabel']:'').'":"'.(($args['uncheckedLabel'] != '')?$args['uncheckedLabel']:'').'")); });';
includes/inpostads.php CHANGED
@@ -1,4 +1,23 @@
1
- <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /* Begin Ad Above Post Content */
3
  add_action('wp_ajax_wp_insert_inpostads_above_form_get_content', 'wp_insert_inpostads_above_form_get_content');
4
  function wp_insert_inpostads_above_form_get_content() {
@@ -94,10 +113,55 @@ function wp_insert_inpostads_form_get_content($position) {
94
  echo '<h3>Ad Code</h3>';
95
  echo '<div>';
96
  $abtestingMode = get_option('wp_insert_abtesting_mode');
97
- $control->add_control(array('type' => 'textarea', 'style' => 'height: 220px;', 'optionName' => 'primary_ad_code'));
98
- $control->create_section('Ad Code (Primary Network)');
99
- echo $control->HTML;
100
- $control->clear_controls();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
  $control->add_control(array('type' => 'textarea', 'style' => 'height: 220px;', 'optionName' => 'secondary_ad_code'));
103
  $control->create_section('Ad Code (Secondary Network)');
@@ -182,8 +246,10 @@ function wp_insert_inpostads_form_get_content($position) {
182
  echo '</div>';
183
  echo '<h3>Geo Targeting</h3>';
184
  echo '<div>';
185
- echo '<p><b>This feature is temporarily unavailable as the servers we were using for FREE Geo Ip service has shut down.</b><br />(If you are interested in supporting us setup our own servers for continuing this service please contact the Author via support@smartlogix.co.in)</p>';
186
- echo '<p>A Geo Targeted Ads have a higher priority than Ads configured via Multiple Ad Networks / A-B Testing.<br />If a Geo Targeting match is found all other Ads (Primary, Secondary and Tertiary Networks) will be ignored.</p>';
 
 
187
  $control->add_control(array('type' => 'choosen-multiselect', 'label' => 'Countries', 'optionName' => 'geo_group1_countries', 'options' => wp_insert_get_countries()));
188
  $control->add_control(array('type' => 'textarea', 'label' => 'Ad Code', 'style' => 'height: 220px;', 'optionName' => 'geo_group1_adcode'));
189
  $control->create_section('Group 1');
@@ -197,6 +263,9 @@ function wp_insert_inpostads_form_get_content($position) {
197
  $control->set_HTML('<div class="wp_insert_rule_block">'.$control->HTML.'</div><div style="clear: both;"></div>');
198
  echo $control->HTML;
199
  $control->clear_controls();
 
 
 
200
  echo '</div>';
201
  echo '<h3>Styles</h3>';
202
  echo '<div>';
@@ -226,6 +295,8 @@ function wp_insert_inpostads_form_get_content($position) {
226
  echo '<script type="text/javascript">';
227
  echo $control->JS;
228
  echo 'jQuery("#wp_insert_inpostads_'.$position.'_accordion").accordion({ icons: { header: "ui-icon-circle-arrow-e", activeHeader: "ui-icon-circle-arrow-s" }, heightStyle: "auto" });';
 
 
229
  echo '</script>';
230
  echo '</div>';
231
  }
@@ -234,6 +305,9 @@ function wp_insert_inpostads_form_save_action($position) {
234
  $inpostAds = get_option('wp_insert_inpostads');
235
  $inpostAds[$position]['status'] = ((isset($_POST['wp_insert_inpostads_'.$position.'_status']) && ($_POST['wp_insert_inpostads_'.$position.'_status'] == 'true'))?'1':'');
236
 
 
 
 
237
  $inpostAds[$position]['primary_ad_code'] = ((isset($_POST['wp_insert_inpostads_'.$position.'_primary_ad_code']))?$_POST['wp_insert_inpostads_'.$position.'_primary_ad_code']:'');
238
  $inpostAds[$position]['secondary_ad_code'] = ((isset($_POST['wp_insert_inpostads_'.$position.'_secondary_ad_code']))?$_POST['wp_insert_inpostads_'.$position.'_secondary_ad_code']:'');
239
  $inpostAds[$position]['tertiary_ad_code'] = ((isset($_POST['wp_insert_inpostads_'.$position.'_tertiary_ad_code']))?$_POST['wp_insert_inpostads_'.$position.'_tertiary_ad_code']:'');
@@ -433,6 +507,15 @@ function wp_insert_inpostads_the_content($content) {
433
  if(!is_feed() && is_main_query()) {
434
  $inpostAds = get_option('wp_insert_inpostads');
435
 
 
 
 
 
 
 
 
 
 
436
  if(wp_insert_get_ad_status($inpostAds['middle'])) {
437
  $paragraphCount = wp_insert_inpostads_get_paragraph_count($content);
438
  if($paragraphCount > 1) {
@@ -452,15 +535,6 @@ function wp_insert_inpostads_the_content($content) {
452
  }
453
  }
454
  }
455
- if(wp_insert_get_ad_status($inpostAds['left'])) {
456
- $content = '<div class="wpInsert wpInsertInPostAd wpInsertLeft" style="float: left; '.(($inpostAds['left']['styles'] != '')?$inpostAds['left']['styles']:'').'">'.wp_insert_get_geotargeted_adcode($inpostAds['left']).'</div>'.$content;
457
- }
458
- if(wp_insert_get_ad_status($inpostAds['right'])) {
459
- $content = '<div class="wpInsert wpInsertInPostAd wpInsertRight" style="float: right; '.(($inpostAds['right']['styles'] != '')?$inpostAds['right']['styles']:'').'">'.wp_insert_get_geotargeted_adcode($inpostAds['right']).'</div>'.$content;
460
- }
461
- if(wp_insert_get_ad_status($inpostAds['above'])) {
462
- $content = '<div class="wpInsert wpInsertInPostAd wpInsertAbove"'.(($inpostAds['above']['styles'] != '')?' style="'.$inpostAds['above']['styles'].'"':'').'>'.wp_insert_get_geotargeted_adcode($inpostAds['above']).'</div>'.$content;
463
- }
464
  if(wp_insert_get_ad_status($inpostAds['below'])) {
465
  $content = $content.'<div class="wpInsert wpInsertInPostAd wpInsertBelow"'.(($inpostAds['below']['styles'] != '')?' style="'.$inpostAds['below']['styles'].'"':'').'>'.wp_insert_get_geotargeted_adcode($inpostAds['below']).'</div>';
466
  }
1
+ <?php
2
+ /* Begin Add Card in Admin Panel */
3
+ add_action('wp_insert_plugin_card', 'wp_insert_inpostads_plugin_card', 10);
4
+ function wp_insert_inpostads_plugin_card() {
5
+ echo '<div class="plugin-card">';
6
+ echo '<div class="plugin-card-top">';
7
+ echo '<h4>In-Post Ads</h4>';
8
+ echo '<p>Ads shown within the post content.</p>';
9
+ echo '</div>';
10
+ echo '<div class="plugin-card-bottom">';
11
+ echo '<p><a id="wp_insert_inpostads_above" href="javascript:;">Ad - Above Post Content</a></p>';
12
+ echo '<p><a id="wp_insert_inpostads_middle" href="javascript:;">Ad - Middle of Post Content</a></p>';
13
+ echo '<p><a id="wp_insert_inpostads_below" href="javascript:;">Ad - Below Post Content</a></p>';
14
+ echo '<p><a id="wp_insert_inpostads_left" href="javascript:;">Ad - Left of Post Content</a></p>';
15
+ echo '<p><a id="wp_insert_inpostads_right" href="javascript:;">Ad - Right of Post Content</a></p>';
16
+ echo '</div>';
17
+ echo '</div>';
18
+ }
19
+ /* End Add Card in Admin Panel */
20
+
21
  /* Begin Ad Above Post Content */
22
  add_action('wp_ajax_wp_insert_inpostads_above_form_get_content', 'wp_insert_inpostads_above_form_get_content');
23
  function wp_insert_inpostads_above_form_get_content() {
113
  echo '<h3>Ad Code</h3>';
114
  echo '<div>';
115
  $abtestingMode = get_option('wp_insert_abtesting_mode');
116
+
117
+ if($position == 'above' || $position == 'middle') {
118
+ $adTypes = array(
119
+ array('text' => 'Use Generic / Custom Ad Code', 'value' => 'generic'),
120
+ array('text' => 'vi stories', 'value' => 'vicode'),
121
+ );
122
+ $control->add_control(array('type' => 'select', 'label' => 'Ad Type', 'optionName' => 'primary_ad_code_type', 'options' => $adTypes));
123
+ echo $control->HTML;
124
+ $control->clear_controls();
125
+
126
+ $control->add_control(array('type' => 'textarea', 'style' => 'height: 220px;', 'optionName' => 'primary_ad_code'));
127
+ $control->create_section('<span id="primary_ad_code_type_generic" class="isSelectedIndicator"></span>Generic / Custom Ad Code (Primary Network)');
128
+ $control->set_HTML('<div class="wp_insert_rule_block">'.$control->HTML.'</div>');
129
+ echo $control->HTML;
130
+ $control->clear_controls();
131
+
132
+ $IsVILoggedin = wp_insert_vi_api_is_loggedin();
133
+ $isJSTagGenerated = ((wp_insert_vi_api_get_vi_code() === false)?false:true);
134
+ $isVIDisabled = false;
135
+ $viMessage = '';
136
+ if(!$IsVILoggedin && !$isJSTagGenerated) {
137
+ $isVIDisabled = true;
138
+ $viMessage = '<p>Introducing <b>vi stories</b> – the video content and advertising player.</p>';
139
+ $viMessage .= '<p>Before you can use <b>vi stories</b>, you must configure it. Once you’ve signed up, in the <i>video intelligence</i> panel, click <i>Sign in</i> then click <i>Configure</i></p>';
140
+ } else if($IsVILoggedin && !$isJSTagGenerated) {
141
+ $isVIDisabled = true;
142
+ $viMessage .= '<p>Before you can use <b>vi stories</b>, you must configure it. In the <i>video intelligence</i> panel, click <i>Configure</i></p>';
143
+ //$viMessage .= '<p><a id="wp_insert_inpostads_vi_customize_adcode" href="javascript:;" class="button button-primary aligncenter">Configure vi Code</a></p>'; /*Button being temporarily removed to avoid confusion for users*/
144
+ } else if(!$IsVILoggedin && $isJSTagGenerated) {
145
+ $isVIDisabled = false;
146
+ $viMessage = '<p>Before you can use <b>vi stories</b>, you must configure it. Once you’ve signed up, in the <i>video intelligence</i> panel, click <i>Sign in</i> then click <i>Configure</i></p>';
147
+ } else {
148
+ $isVIDisabled = false;
149
+ $viMessage = wp_insert_vi_customize_adcode_get_settings();
150
+ $viMessage .= '<p>To configure <b>vi stories</b>, go to the <i>video intelligence</i> panel, click <i>Configure</i></p>';
151
+ //$viMessage .= '<p><a id="wp_insert_inpostads_vi_customize_adcode" href="javascript:;" class="button button-primary aligncenter">Configure vi Code</a></p>'; /*Button being temporarily removed to avoid confusion for users*/
152
+ }
153
+
154
+ $control->HTML .= $viMessage;
155
+ $control->create_section('<span id="primary_ad_code_type_vicode" class="isSelectedIndicator '.(($isVIDisabled)?'disabled':'').'"></span>vi stories (Primary Network)');
156
+ $control->set_HTML('<div class="wp_insert_rule_block">'.$control->HTML.'</div><div style="clear: both;"></div>');
157
+ echo $control->HTML;
158
+ $control->clear_controls();
159
+ } else {
160
+ $control->add_control(array('type' => 'textarea', 'style' => 'height: 220px;', 'optionName' => 'primary_ad_code'));
161
+ $control->create_section('Ad Code (Primary Network)');
162
+ echo $control->HTML;
163
+ $control->clear_controls();
164
+ }
165
 
166
  $control->add_control(array('type' => 'textarea', 'style' => 'height: 220px;', 'optionName' => 'secondary_ad_code'));
167
  $control->create_section('Ad Code (Secondary Network)');
246
  echo '</div>';
247
  echo '<h3>Geo Targeting</h3>';
248
  echo '<div>';
249
+ echo '<p>';
250
+ echo 'A Geo Targeted Ads have a higher priority than Ads configured via Multiple Ad Networks / A-B Testing.<br />';
251
+ echo 'If a Geo Targeting match is found all other Ads (Primary, Secondary and Tertiary Networks) will be ignored.<br />';
252
+ echo '</p>';
253
  $control->add_control(array('type' => 'choosen-multiselect', 'label' => 'Countries', 'optionName' => 'geo_group1_countries', 'options' => wp_insert_get_countries()));
254
  $control->add_control(array('type' => 'textarea', 'label' => 'Ad Code', 'style' => 'height: 220px;', 'optionName' => 'geo_group1_adcode'));
255
  $control->create_section('Group 1');
263
  $control->set_HTML('<div class="wp_insert_rule_block">'.$control->HTML.'</div><div style="clear: both;"></div>');
264
  echo $control->HTML;
265
  $control->clear_controls();
266
+ echo '<p>';
267
+ echo 'This feature uses the Free Geo ip service from <a href="http://freegeoip.net/">freegeoip.net</a>, if you find this feature useful please consider donating to the project at <a href="http://freegeoip.net/">freegeoip.net</a>';
268
+ echo '</p>';
269
  echo '</div>';
270
  echo '<h3>Styles</h3>';
271
  echo '<div>';
295
  echo '<script type="text/javascript">';
296
  echo $control->JS;
297
  echo 'jQuery("#wp_insert_inpostads_'.$position.'_accordion").accordion({ icons: { header: "ui-icon-circle-arrow-e", activeHeader: "ui-icon-circle-arrow-s" }, heightStyle: "auto" });';
298
+ echo 'primary_ad_code_type_change();';
299
+ echo 'wp_insert_inpostads_vi_customize_adcode();';
300
  echo '</script>';
301
  echo '</div>';
302
  }
305
  $inpostAds = get_option('wp_insert_inpostads');
306
  $inpostAds[$position]['status'] = ((isset($_POST['wp_insert_inpostads_'.$position.'_status']) && ($_POST['wp_insert_inpostads_'.$position.'_status'] == 'true'))?'1':'');
307
 
308
+ if($position == 'above' || $position == 'middle') {
309
+ $inpostAds[$position]['primary_ad_code_type'] = ((isset($_POST['wp_insert_inpostads_'.$position.'_primary_ad_code_type']))?$_POST['wp_insert_inpostads_'.$position.'_primary_ad_code_type']:'');
310
+ }
311
  $inpostAds[$position]['primary_ad_code'] = ((isset($_POST['wp_insert_inpostads_'.$position.'_primary_ad_code']))?$_POST['wp_insert_inpostads_'.$position.'_primary_ad_code']:'');
312
  $inpostAds[$position]['secondary_ad_code'] = ((isset($_POST['wp_insert_inpostads_'.$position.'_secondary_ad_code']))?$_POST['wp_insert_inpostads_'.$position.'_secondary_ad_code']:'');
313
  $inpostAds[$position]['tertiary_ad_code'] = ((isset($_POST['wp_insert_inpostads_'.$position.'_tertiary_ad_code']))?$_POST['wp_insert_inpostads_'.$position.'_tertiary_ad_code']:'');
507
  if(!is_feed() && is_main_query()) {
508
  $inpostAds = get_option('wp_insert_inpostads');
509
 
510
+ if(wp_insert_get_ad_status($inpostAds['left'])) {
511
+ $content = '<div class="wpInsert wpInsertInPostAd wpInsertLeft" style="float: left; '.(($inpostAds['left']['styles'] != '')?$inpostAds['left']['styles']:'').'">'.wp_insert_get_geotargeted_adcode($inpostAds['left']).'</div>'.$content;
512
+ }
513
+ if(wp_insert_get_ad_status($inpostAds['right'])) {
514
+ $content = '<div class="wpInsert wpInsertInPostAd wpInsertRight" style="float: right; '.(($inpostAds['right']['styles'] != '')?$inpostAds['right']['styles']:'').'">'.wp_insert_get_geotargeted_adcode($inpostAds['right']).'</div>'.$content;
515
+ }
516
+ if(wp_insert_get_ad_status($inpostAds['above'])) {
517
+ $content = '<div class="wpInsert wpInsertInPostAd wpInsertAbove"'.(($inpostAds['above']['styles'] != '')?' style="'.$inpostAds['above']['styles'].'"':'').'>'.wp_insert_get_geotargeted_adcode($inpostAds['above']).'</div>'.$content;
518
+ }
519
  if(wp_insert_get_ad_status($inpostAds['middle'])) {
520
  $paragraphCount = wp_insert_inpostads_get_paragraph_count($content);
521
  if($paragraphCount > 1) {
535
  }
536
  }
537
  }
 
 
 
 
 
 
 
 
 
538
  if(wp_insert_get_ad_status($inpostAds['below'])) {
539
  $content = $content.'<div class="wpInsert wpInsertInPostAd wpInsertBelow"'.(($inpostAds['below']['styles'] != '')?' style="'.$inpostAds['below']['styles'].'"':'').'>'.wp_insert_get_geotargeted_adcode($inpostAds['below']).'</div>';
540
  }
includes/inthemeads.php CHANGED
@@ -1,4 +1,28 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /* Begin Add New In-Theme Content */
3
  add_action('wp_ajax_wp_insert_inthemeads_new_form_get_content', 'wp_insert_inthemeads_new_form_get_content');
4
  function wp_insert_inthemeads_new_form_get_content() {
@@ -145,8 +169,10 @@ function wp_insert_inthemeads_form_get_content($identifier) {
145
  echo '</div>';
146
  echo '<h3>Geo Targeting</h3>';
147
  echo '<div>';
148
- echo '<p><b>This feature is temporarily unavailable as the servers we were using for FREE Geo Ip service has shut down.</b><br />(If you are interested in supporting us setup our own servers for continuing this service please contact the Author via support@smartlogix.co.in)</p>';
149
- echo '<p>A Geo Targeted Ads have a higher priority than Ads configured via Multiple Ad Networks / A-B Testing.<br />If a Geo Targeting match is found all other Ads (Primary, Secondary and Tertiary Networks) will be ignored.</p>';
 
 
150
  $control->add_control(array('type' => 'choosen-multiselect', 'label' => 'Countries', 'optionName' => 'geo_group1_countries', 'options' => wp_insert_get_countries()));
151
  $control->add_control(array('type' => 'textarea', 'label' => 'Ad Code', 'style' => 'height: 220px;', 'optionName' => 'geo_group1_adcode'));
152
  $control->create_section('Group 1');
@@ -160,6 +186,9 @@ function wp_insert_inthemeads_form_get_content($identifier) {
160
  $control->set_HTML('<div class="wp_insert_rule_block">'.$control->HTML.'</div><div style="clear: both;"></div>');
161
  echo $control->HTML;
162
  $control->clear_controls();
 
 
 
163
  echo '</div>';
164
  echo '<h3>Styles</h3>';
165
  echo '<div>';
1
  <?php
2
+ /* Begin Add Card in Admin Panel */
3
+ add_action('wp_insert_plugin_card', 'wp_insert_inthemeads_plugin_card', 30);
4
+ function wp_insert_inthemeads_plugin_card() {
5
+ echo '<div class="plugin-card">';
6
+ echo '<div class="plugin-card-top">';
7
+ echo '<h4>In-Theme Ads</h4>';
8
+ echo '<p>Ads embedded directly inside theme files (Advanced Users Only).</p>';
9
+ echo '</div>';
10
+ echo '<div class="plugin-card-bottom">';
11
+ $inthemeads = get_option('wp_insert_inthemeads');
12
+ if(isset($inthemeads) && is_array($inthemeads)) {
13
+ foreach($inthemeads as $key => $value) {
14
+ echo '<p>';
15
+ echo '<a id="wp_insert_inthemeads_'.$key.'" href="javascript:;" onclick="wp_insert_inthemeads_click_handler(\''.$key.'\', \''.$value['title'].'\')">In-Theme Ad : '.$value['title'].'</a>';
16
+ echo '<span class="dashicons dashicons-dismiss wp_insert_delete_icon" onclick="wp_insert_inthemeads_remove(\''.$key.'\')"></span>';
17
+ echo '</p>';
18
+ }
19
+ }
20
+ echo '<p style="text-align: center; padding: 20px 0 10px;"><a id="wp_insert_inthemeads_new" href="#" class="button-secondary">Add New In-Theme Ad</a></p>';
21
+ echo '</div>';
22
+ echo '</div>';
23
+ }
24
+ /* End Add Card in Admin Panel */
25
+
26
  /* Begin Add New In-Theme Content */
27
  add_action('wp_ajax_wp_insert_inthemeads_new_form_get_content', 'wp_insert_inthemeads_new_form_get_content');
28
  function wp_insert_inthemeads_new_form_get_content() {
169
  echo '</div>';
170
  echo '<h3>Geo Targeting</h3>';
171
  echo '<div>';
172
+ echo '<p>';
173
+ echo 'A Geo Targeted Ads have a higher priority than Ads configured via Multiple Ad Networks / A-B Testing.<br />';
174
+ echo 'If a Geo Targeting match is found all other Ads (Primary, Secondary and Tertiary Networks) will be ignored.';
175
+ echo '</p>';
176
  $control->add_control(array('type' => 'choosen-multiselect', 'label' => 'Countries', 'optionName' => 'geo_group1_countries', 'options' => wp_insert_get_countries()));
177
  $control->add_control(array('type' => 'textarea', 'label' => 'Ad Code', 'style' => 'height: 220px;', 'optionName' => 'geo_group1_adcode'));
178
  $control->create_section('Group 1');
186
  $control->set_HTML('<div class="wp_insert_rule_block">'.$control->HTML.'</div><div style="clear: both;"></div>');
187
  echo $control->HTML;
188
  $control->clear_controls();
189
+ echo '<p>';
190
+ echo 'This feature uses the Free Geo ip service from <a href="http://freegeoip.net/">freegeoip.net</a>, if you find this feature useful please consider donating to the project at <a href="http://freegeoip.net/">freegeoip.net</a>';
191
+ echo '</p>';
192
  echo '</div>';
193
  echo '<h3>Styles</h3>';
194
  echo '<div>';
includes/tracking-codes.php CHANGED
@@ -1,4 +1,21 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /* Begin Analytics Embed */
3
  add_action('wp_ajax_wp_insert_trackingcodes_google_analytics_form_get_content', 'wp_insert_trackingcodes_google_analytics_form_get_content');
4
  function wp_insert_trackingcodes_google_analytics_form_get_content() {
1
  <?php
2
+ /* Begin Add Card in Admin Panel */
3
+ add_action('wp_insert_plugin_card', 'wp_insert_trackingcodes_plugin_card', 50);
4
+ function wp_insert_trackingcodes_plugin_card() {
5
+ echo '<div class="plugin-card">';
6
+ echo '<div class="plugin-card-top">';
7
+ echo '<h4>Tracking Codes</h4>';
8
+ echo '<p>Google Analytics and other embeddable codes directly inserted into the site.</p>';
9
+ echo '</div>';
10
+ echo '<div class="plugin-card-bottom">';
11
+ echo '<p><a id="wp_insert_trackingcodes_google_analytics" href="javascript:;">Google Analytics</a></p>';
12
+ echo '<p><a id="wp_insert_trackingcodes_header" href="javascript:;">Embed Code in Header</a></p>';
13
+ echo '<p><a id="wp_insert_trackingcodes_footer" href="javascript:;">Embed Code in Footer</a></p>';
14
+ echo '</div>';
15
+ echo '</div>';
16
+ }
17
+ /* End Add Card in Admin Panel */
18
+
19
  /* Begin Analytics Embed */
20
  add_action('wp_ajax_wp_insert_trackingcodes_google_analytics_form_get_content', 'wp_insert_trackingcodes_google_analytics_form_get_content');
21
  function wp_insert_trackingcodes_google_analytics_form_get_content() {
includes/vi-integration.php ADDED
@@ -0,0 +1,1227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* Begin Add Card in Admin Panel */
3
+ add_action('wp_insert_plugin_card', 'wp_insert_vi_plugin_card', 5);
4
+ function wp_insert_vi_plugin_card() {
5
+ echo '<div class="plugin-card vi-card">';
6
+ if(wp_insert_vi_api_is_loggedin()) {
7
+ wp_insert_vi_plugin_card_content(true);
8
+ } else {
9
+ wp_insert_vi_plugin_card_content(false);
10
+ }
11
+ echo '</div>';
12
+ }
13
+
14
+ function wp_insert_vi_plugin_card_content($isLoggedin = false, $isAjaxRequest = false) {
15
+ if(!$isLoggedin) {
16
+ echo '<div class="plugin-card-top">';
17
+ echo '<div class="plugin-card-top-header">';
18
+ echo '<h4>Video content and video advertising – powered by video intelligence</h4>';
19
+ echo '</div>';
20
+ echo '<div class="plugin-card-top-content" '.(($isAjaxRequest)?'style="opacity: 0;"':'').'>';
21
+ echo '<p>Video content and video advertising – powered by video intelligence.</p>';
22
+ echo '<p>Advertisers pay more for video advertising when it’s matched with video content. This new video player will insert both on your page. It increases time on site, and commands a higher CPM than display advertising.</p>';
23
+ echo '<p>You’ll see video content that is matched to your sites keywords straight away. A few days after activation you’ll begin to receive revenue from advertising served before this video content.</p>';
24
+ echo '<ul>';
25
+ echo '<li>The set up takes only a few minutes</li>';
26
+ echo '<li>Up to 10x higher CPM than traditional display advertising</li>';
27
+ echo '<li>Users spend longer on your site thanks to professional video content</li>';
28
+ echo '<li>The video player is customizable to match your site</li>';
29
+ echo '</ul>';
30
+ echo '<p>Watch a <a href="http://demo.vi.ai/ViewsterBlog_Nintendo.html" target="_blank">demo</a> of how <b>vi stories</b> works.</p>';
31
+ echo '</div>';
32
+ echo '</div>';
33
+ echo '<div class="plugin-card-bottom" '.(($isAjaxRequest)?'style="opacity: 0;"':'').'>';
34
+ echo '<span>By clicking Sign Up button you agree to send current domain, email and affiliate ID to video intelligence.</span>';
35
+ echo '<a id="wp_insert_vi_login" href="javascript:;" class="button button-secondary">Log In</a>';
36
+ echo '<a id="wp_insert_vi_signup" href="javascript:;" class="button button-primary">Sign Up</a>';
37
+ echo '</div>';
38
+ } else {
39
+ $dashboardURL = wp_insert_vi_api_get_dashboardurl();
40
+ echo '<div class="plugin-card-top">';
41
+ echo '<div class="plugin-card-top-header">';
42
+ echo '<h4>Video content and video advertising – powered by video intelligence</h4>';
43
+ echo '</div>';
44
+ echo '<div class="plugin-card-top-content" '.(($isAjaxRequest)?'style="opacity: 0;"':'').'>';
45
+ echo '<p>Below you can see your current revenues.<br />Don’t see anything? Consult the <a target="_blank" href="https://www.vi.ai/frequently-asked-questions-vi-stories-for-wordpress/?utm_source=WordPress&utm_medium=Plugin%20FAQ&utm_campaign=WP%20Insert">FAQs</a>.</p>';
46
+ echo '<div id="wp_insert_vi_earnings_wrapper">';
47
+ echo '<div class="wp_insert_ajaxloader"></div>';
48
+ echo '</div>';
49
+ echo '</div>';
50
+ echo '</div>';
51
+ echo '<div class="plugin-card-bottom" '.(($isAjaxRequest)?'style="opacity: 0;"':'').'>';
52
+ echo '<a id="wp_insert_vi_dashboard" href="'.$dashboardURL.'" target="_blank" class="button button-primary alignleft">Publisher Dashboard</a>';
53
+ echo '<a id="wp_insert_vi_customize_adcode" href="javascript:;" class="button button-primary alignleft">Configure vi Code</a>';
54
+ echo '<a id="wp_insert_vi_logout" href="javascript:;" class="button button-secondary">Log Out</a>';
55
+ echo '</div>';
56
+ }
57
+ }
58
+
59
+ add_action('wp_ajax_wp_insert_vi_get_chart', 'wp_insert_vi_get_chart');
60
+ function wp_insert_vi_get_chart() {
61
+ check_ajax_referer('wp-insert', 'wp_insert_nonce');
62
+ $revenueData = wp_insert_vi_api_get_revenue_data();
63
+ if(isset($revenueData) && is_array($revenueData)) {
64
+ echo '###SUCCESS###';
65
+ echo '<div id="wp_insert_vi_earnings">';
66
+ echo '<span id="wp_insert_vi_earnings_label">Total Earnings</span>';
67
+ echo '<span id="wp_insert_vi_earnings_value">$'.$revenueData['netRevenue'].'</span>';
68
+ echo '</div>';
69
+ echo '<div id="wp_insert_vi_chart_wrapper">';
70
+ echo '<canvas id="wp_insert_vi_chart" width="348" height="139"></canvas>';
71
+ echo '<textarea id="wp_insert_vi_chart_data" style="display: none;">[';
72
+ if(isset($revenueData['mtdReport']) && is_array($revenueData['mtdReport']) & (count($revenueData['mtdReport']) > 0)) {
73
+ $isFirstItem = true;
74
+ foreach($revenueData['mtdReport'] as $reportData) {
75
+ if(!$isFirstItem) {
76
+ echo ',';
77
+ }
78
+ $date = DateTime::createFromFormat('d-m-Y', $reportData['date']);
79
+ echo '{"x": "'.$date->format('m/d/Y').'", "y": "'.$reportData['revenue'].'"}';
80
+ $isFirstItem = false;;
81
+ }
82
+ } else {
83
+ echo '{"x": "'.date('m/d/Y').'", "y": "0.00"}';
84
+ }
85
+ echo ']</textarea>';
86
+ echo '</div>';
87
+ echo '<div class="clear"></div>';
88
+ } else {
89
+ echo '<p class="viError">There was an error processing your request, our team was notified.<br />Please try again later.</p>';
90
+ echo '<div id="wp_insert_vi_earnings_wrapper">';
91
+ echo '<div id="wp_insert_vi_earnings">';
92
+ echo '<span id="wp_insert_vi_earnings_label">Total Earnings</span>';
93
+ echo '<span id="wp_insert_vi_earnings_value"><img src="'.WP_INSERT_URL.'includes/assets/images/vi-no-data.jpg?'.WP_INSERT_VERSION.'"></span>';
94
+ echo '</div>';
95
+ echo '<div id="wp_insert_vi_chart_wrapper">';
96
+ echo '<img width="348" height="139" src="'.WP_INSERT_URL.'includes/assets/images/vi-empty-graph.jpg?'.WP_INSERT_VERSION.'">';
97
+ echo '</div>';
98
+ echo '<div class="clear"></div>';
99
+ echo '</div>';
100
+ }
101
+ die();
102
+ }
103
+ /* End Add Card in Admin Panel */
104
+
105
+ /* Begin Signup Form */
106
+ add_action('wp_ajax_wp_insert_vi_signup_form_get_content', 'wp_insert_vi_signup_form_get_content');
107
+ function wp_insert_vi_signup_form_get_content() {
108
+ check_ajax_referer('wp-insert', 'wp_insert_nonce');
109
+ $signupURL = wp_insert_vi_api_get_signupurl();
110
+ if(($signupURL != false) && ($signupURL != '')) {
111
+ echo '<div class="wp_insert_popup_content_wrapper">';
112
+ echo '<iframe src="'.$signupURL.'?email='.get_bloginfo('admin_email').'&domain='.wp_insert_get_domain_name_from_url(get_bloginfo('url')).'&aid=WP_insert" style="width: 100%; max-width: 870px; min-height: 554px;"></iframe>';
113
+ echo '<script type="text/javascript">';
114
+ echo 'jQuery(".ui-dialog-buttonset").find("button").first().remove();';
115
+ echo 'jQuery(".ui-dialog-buttonset").find("button").first().find("span:nth-child(2)").hide().after("<span class=\'ui-button-text\'>Close</span>");';
116
+ echo '</script>';
117
+ echo '</div>';
118
+ } else {
119
+ echo '<div class="wp_insert_popup_content_wrapper">';
120
+ echo '<p> There was an error processing your request. Please try again later. </p>';
121
+ echo '</div>';
122
+ }
123
+ die();
124
+ }
125
+ /* End Signup Form */
126
+
127
+ /* Begin Login Form */
128
+ add_action('wp_ajax_wp_insert_vi_login_form_get_content', 'wp_insert_vi_login_form_get_content');
129
+ function wp_insert_vi_login_form_get_content() {
130
+ check_ajax_referer('wp-insert', 'wp_insert_nonce');
131
+ echo '<div class="wp_insert_popup_content_wrapper">';
132
+ echo '<div class="wp_insert_vi_loginform_wrapper">';
133
+ wp_insert_vi_login_form_get_controls();
134
+ echo '</div>';
135
+ echo '<script type="text/javascript">';
136
+ echo $control->JS;
137
+ echo 'jQuery(".ui-dialog-buttonset").find("button").first().find("span:nth-child(2)").hide().after("<span class=\'ui-button-text\'>Login</span>");';
138
+ echo 'jQuery(".ui-dialog-buttonset").find("button").first().find("span:nth-child(1)").attr("class", "ui-button-icon-primary ui-icon ui-icon-key");';
139
+ echo '</script>';
140
+ echo '</div>';
141
+ die();
142
+ }
143
+
144
+ add_action('wp_ajax_wp_insert_vi_login_form_save_action', 'wp_insert_vi_login_form_save_action');
145
+ function wp_insert_vi_login_form_save_action() {
146
+ check_ajax_referer('wp-insert', 'wp_insert_nonce');
147
+ if(isset($_POST['wp_insert_vi_login_username']) && ($_POST['wp_insert_vi_login_username'] != '') && isset($_POST['wp_insert_vi_login_password']) && ($_POST['wp_insert_vi_login_password'] != '')) {
148
+ $token = wp_insert_vi_api_login($_POST['wp_insert_vi_login_username'], $_POST['wp_insert_vi_login_password']);
149
+ if(is_array($token) && (isset($token['status'])) && ($token['status'] == 'error')) {
150
+ wp_insert_vi_login_form_get_controls();
151
+ if($token['errorCode'] == 'WIVI008') {
152
+ echo '<p class="wp_insert_vi_login_error">'.$token['message'].'</p>';
153
+ } else {
154
+ echo '<p class="wp_insert_vi_login_error">Error Code: '.$token['errorCode'].'<br />Please contact support or try again later!'.'</p>';
155
+ }
156
+ } else {
157
+ echo '###SUCCESS###';
158
+ wp_insert_vi_plugin_card_content(true, true);
159
+ }
160
+ }
161
+ die();
162
+ }
163
+
164
+ function wp_insert_vi_login_form_get_controls() {
165
+ $control = new smartlogixControls();
166
+ $control->HTML .= '<p>Please log in with the received credentials to complete the integration:</p>';
167
+ $control->add_control(array('type' => 'text', 'id' => 'wp_insert_vi_login_username', 'name' => 'wp_insert_vi_login_username', 'label' => 'Email', 'value' => ''));
168
+ $control->add_control(array('type' => 'password', 'id' => 'wp_insert_vi_login_password', 'name' => 'wp_insert_vi_login_password', 'label' => 'Password', 'value' => ''));
169
+ $control->create_section('Login');
170
+ echo $control->HTML;
171
+ }
172
+
173
+ add_action('wp_ajax_wp_insert_vi_update_adstxt', 'wp_insert_vi_update_adstxt');
174
+ function wp_insert_vi_update_adstxt() {
175
+ check_ajax_referer('wp-insert', 'wp_insert_nonce');
176
+
177
+ $adstxtContent = wp_insert_adstxt_get_content();
178
+ $adstxtContentData = array_filter(explode("\n", trim($adstxtContent)), 'trim');
179
+ $viEntry = wp_insert_vi_api_get_adstxt_content();
180
+ if(strpos(str_replace(array("\r", "\n", " "), '', $adstxtContent), str_replace(array("\r", "\n", " "), '', $viEntry)) !== false) {
181
+ die();
182
+ } else {
183
+ $updatedAdstxtContent = '';
184
+ if(strpos($adstxtContent, '# 41b5eef6') !== false) {
185
+ foreach($adstxtContentData as $line) {
186
+ if(strpos($line, '# 41b5eef6') !== false) {
187
+
188
+ } else {
189
+ $updatedAdstxtContent .= str_replace(array("\r", "\n", " "), '', $line)."\r\n";
190
+ }
191
+ }
192
+ $updatedAdstxtContent .= $viEntry;
193
+ } else {
194
+ $updatedAdstxtContent .= $adstxtContent."\r\n".$viEntry;
195
+ }
196
+
197
+ if(wp_insert_adstxt_update_content($updatedAdstxtContent)) {
198
+ echo '###SUCCESS###';
199
+ echo '<div class="notice notice-warning wp_insert_adsstxt_notice is-dismissible" style="padding: 5px 15px;">';
200
+ echo '<div style="float: left; max-width: 875px; font-size: 14px; font-family: Arial; line-height: 18px; color: #232323;">';
201
+ echo '<p><b>ADS.TXT has been added</b></p>';
202
+ echo '<p>Wp-Insert has updated your ads.txt file with lines that declare video intelligence as a legitimate seller of your inventory and enables you to make more money through video intelligence. Read the <a target="_blank" href="https://www.vi.ai/frequently-asked-questions-vi-stories-for-wordpress/?utm_source=WordPress&utm_medium=Plugin%20FAQ&utm_campaign=WP%20Insert">FAQ</a>.</p>';
203
+ echo '</div>';
204
+ echo '<img style="float: right; margin-right: 20px; margin-top: 13px;" src="'.WP_INSERT_URL.'includes/assets/images/vi-big-logo.png?'.WP_INSERT_VERSION.'" />';
205
+ echo '<div class="clear"></div>';
206
+ echo '<button type="button" class="notice-dismiss" onclick="javascript:jQuery(this).parent().remove()"><span class="screen-reader-text">Dismiss this notice.</span></button>';
207
+ echo '</div>';
208
+ } else {
209
+ echo '###FAIL###';
210
+ echo '<div class="notice notice-error wp_insert_adsstxt_notice is-dismissible" style="padding: 5px 15px;">';
211
+ echo '<div style="float: left; max-width: 875px; font-size: 14px; font-family: Arial; line-height: 18px; color: #232323;">';
212
+ echo '<p><b>ADS.TXT couldn’t be added</b></p>';
213
+ echo '<p>Important note: Wp-Insert hasn’t been able to update your ads.txt file. Please make sure that you enter the following lines manually:</p>';
214
+ echo '<p><code style="display: block;">'.trim(str_replace(array("\r\n", "\r", "\n"), "<br />", $viEntry)).'</code><br />Only by doing so, you\'ll be able to make more money through video intelligence (vi.ai).</p>';
215
+ echo '</div>';
216
+ echo '<img style="float: right; margin-right: 20px; margin-top: 13px;" src="'.WP_INSERT_URL.'includes/assets/images/vi-big-logo.png?'.WP_INSERT_VERSION.'" />';
217
+ echo '<div class="clear"></div>';
218
+ echo '<button type="button" class="notice-dismiss" onclick="javascript:jQuery(this).parent().remove()"><span class="screen-reader-text">Dismiss this notice.</span></button>';
219
+ echo '</div>';
220
+ }
221
+ }
222
+ die();
223
+ }
224
+ /* End Login Form */
225
+
226
+ /* Begin Logout */
227
+ add_action('wp_ajax_wp_insert_vi_logout_action', 'wp_insert_vi_logout_action');
228
+ function wp_insert_vi_logout_action() {
229
+ check_ajax_referer('wp-insert', 'wp_insert_nonce');
230
+ wp_insert_vi_api_logout();
231
+ echo '###SUCCESS###';
232
+ wp_insert_vi_plugin_card_content(false, true);
233
+ die();
234
+ }
235
+ /* End Logout */
236
+
237
+ /* Begin Configure vi Code */
238
+ add_action('wp_ajax_wp_insert_vi_customize_adcode_form_get_content', 'wp_insert_vi_customize_adcode_form_get_content');
239
+ function wp_insert_vi_customize_adcode_form_get_content() {
240
+ check_ajax_referer('wp-insert', 'wp_insert_nonce');
241
+ $vicodeSettings = get_option('wp_insert_vi_code_settings');
242
+ $control = new smartlogixControls(array('optionIdentifier' => 'wp_insert_vi_code_settings', 'values' => $vicodeSettings));
243
+ $control->HTML = '<div class="wp_insert_popup_content_wrapper">';
244
+ $control->HTML .= '<p>Use this form to customize the look of the video unit. Use the same parameters as your WordPress theme for a natural look on your site.<br />You can use <b>vi stories</b> for <i>In-Post Ads: Ad - Above Post Content</i> and <i>In-Post Ads: Ad - Middle of Post Content</i></p>';
245
+ $control->HTML .= '<div class="wp_insert_vi_popup_right_column">';
246
+ $control->HTML .= '<img style="margin: 0 auto; display: block;" src="'.WP_INSERT_URL.'includes/assets/images/advertisement-preview.png?'.WP_INSERT_VERSION.'" />';
247
+ $control->HTML .= '</div>';
248
+ $control->HTML .= '<div class="wp_insert_vi_popup_left_column">';
249
+ $control->HTML .= '<p id="wp_insert_vi_customize_adcode_keywords_required_error" style="display: none;" class="viError">Keywords contains invalid characters, Some required fields are missing</p>';
250
+ $control->HTML .= '<p id="wp_insert_vi_customize_adcode_keywords_error" style="display: none;" class="viError">Keywords contains invalid characters</p>';
251
+ $control->HTML .= '<p id="wp_insert_vi_customize_adcode_required_error" style="display: none;" class="viError">Some required fields are missing</p>';
252
+ $adUnitOptions = array(
253
+ /*array('text' => 'Select Ad Unit', 'value' => 'select'),*/
254
+ array('text' => 'vi stories', 'value' => 'NATIVE_VIDEO_UNIT'),
255
+ /*array('text' => 'Outstream', 'value' => 'FLOATING_OUTSTREAM')*/
256
+ );
257
+ $control->add_control(array('type' => 'select', 'label' => ' Ad Unit*', 'optionName' => 'ad_unit_type', 'helpText' => '</small><span class="tooltipWrapper"><span class="tooltip">- vi stories (video advertising + video content)</span></span><small>', 'options' => $adUnitOptions));/*<br />- out-stream (video advertising)*/
258
+ $control->add_control(array('type' => 'textarea', 'label' => 'Keywords', 'optionName' => 'keywords', 'helpText' => '</small><span class="tooltipWrapper"><span class="tooltip">Comma separated values describing the content of the page e.g. \'cooking, grilling, pulled pork\'</span></span><small>'));
259
+ $IABParentCategories = array(
260
+ array('text' => 'Select tier 1 category', 'value' => 'select'),
261
+ array('text' => 'Arts & Entertainment', 'value' => 'IAB1'),
262
+ array('text' => 'Automotive', 'value' => 'IAB2'),
263
+ array('text' => 'Business', 'value' => 'IAB3'),
264
+ array('text' => 'Careers', 'value' => 'IAB4'),
265
+ array('text' => 'Education', 'value' => 'IAB5'),
266
+ array('text' => 'Family & Parenting', 'value' => 'IAB6'),
267
+ array('text' => 'Health & Fitness', 'value' => 'IAB7'),
268
+ array('text' => 'Food & Drink', 'value' => 'IAB8'),
269
+ array('text' => 'Hobbies & Interests', 'value' => 'IAB9'),
270
+ array('text' => 'Home & Garden', 'value' => 'IAB10'),
271
+ array('text' => 'Law, Gov’t & Politics', 'value' => 'IAB11'),
272
+ array('text' => 'News', 'value' => 'IAB12'),
273
+ array('text' => 'Personal Finance', 'value' => 'IAB13'),
274
+ array('text' => 'Society', 'value' => 'IAB14'),
275
+ array('text' => 'Science', 'value' => 'IAB15'),
276
+ array('text' => 'Pets', 'value' => 'IAB16'),
277
+ array('text' => 'Sports', 'value' => 'IAB17'),
278
+ array('text' => 'Style & Fashion', 'value' => 'IAB18'),
279
+ array('text' => 'Technology & Computing', 'value' => 'IAB19'),
280
+ array('text' => 'Travel', 'value' => 'IAB20'),
281
+ array('text' => 'Real Estate', 'value' => 'IAB21'),
282
+ array('text' => 'Shopping', 'value' => 'IAB22'),
283
+ array('text' => 'Religion & Spirituality', 'value' => 'IAB23'),
284
+ array('text' => 'Uncategorized', 'value' => 'IAB24'),
285
+ array('text' => 'Non-Standard Content', 'value' => 'IAB25'),
286
+ array('text' => 'Illegal Content', 'value' => 'IAB26')
287
+ );
288
+ $control->add_control(array('type' => 'select', 'label' => 'IAB Category*', 'optionName' => 'iab_category_parent', 'helpText' => '</small><a class="textTip" target="_blank" href="'.wp_insert_vi_api_get_iabCategoriesURL().'">See Complete List</a><small>', 'options' => $IABParentCategories));
289
+ $IABChildCategories = array(
290
+ array('text' => 'Select tier 2 category', 'value' => 'select'),
291
+ array('text' => 'Books & Literature', 'value' => 'IAB1-1', 'metadata' => array('parent' => 'IAB1')),
292
+ array('text' => 'Celebrity Fan/Gossip', 'value' => 'IAB1-2', 'metadata' => array('parent' => 'IAB1')),
293
+ array('text' => 'Fine Art', 'value' => 'IAB1-3', 'metadata' => array('parent' => 'IAB1')),
294
+ array('text' => 'Humor', 'value' => 'IAB1-4', 'metadata' => array('parent' => 'IAB1')),
295
+ array('text' => 'Movies', 'value' => 'IAB1-5', 'metadata' => array('parent' => 'IAB1')),
296
+ array('text' => 'Music', 'value' => 'IAB1-6', 'metadata' => array('parent' => 'IAB1')),
297
+ array('text' => 'Television', 'value' => 'IAB1-7', 'metadata' => array('parent' => 'IAB1')),
298
+ array('text' => 'Auto Parts', 'value' => 'IAB2-1', 'metadata' => array('parent' => 'IAB2')),
299
+ array('text' => 'Auto Repair', 'value' => 'IAB2-2', 'metadata' => array('parent' => 'IAB2')),
300
+ array('text' => 'Buying/Selling Cars', 'value' => 'IAB2-3', 'metadata' => array('parent' => 'IAB2')),
301
+ array('text' => 'Car Culture', 'value' => 'IAB2-4', 'metadata' => array('parent' => 'IAB2')),
302
+ array('text' => 'Certified Pre-Owned', 'value' => 'IAB2-5', 'metadata' => array('parent' => 'IAB2')),
303
+ array('text' => 'Convertible', 'value' => 'IAB2-6', 'metadata' => array('parent' => 'IAB2')),
304
+ array('text' => 'Coupe', 'value' => 'IAB2-7', 'metadata' => array('parent' => 'IAB2')),
305
+ array('text' => 'Crossover', 'value' => 'IAB2-8', 'metadata' => array('parent' => 'IAB2')),
306
+ array('text' => 'Diesel', 'value' => 'IAB2-9', 'metadata' => array('parent' => 'IAB2')),
307
+ array('text' => 'Electric Vehicle', 'value' => 'IAB2-10', 'metadata' => array('parent' => 'IAB2')),
308
+ array('text' => 'Hatchback', 'value' => 'IAB2-11', 'metadata' => array('parent' => 'IAB2')),
309
+ array('text' => 'Hybrid', 'value' => 'IAB2-12', 'metadata' => array('parent' => 'IAB2')),
310
+ array('text' => 'Luxury', 'value' => 'IAB2-13', 'metadata' => array('parent' => 'IAB2')),
311
+ array('text' => 'MiniVan', 'value' => 'IAB2-14', 'metadata' => array('parent' => 'IAB2')),
312
+ array('text' => 'Mororcycles', 'value' => 'IAB2-15', 'metadata' => array('parent' => 'IAB2')),
313
+ array('text' => 'Off-Road Vehicles', 'value' => 'IAB2-16', 'metadata' => array('parent' => 'IAB2')),
314
+ array('text' => 'Performance Vehicles', 'value' => 'IAB2-17', 'metadata' => array('parent' => 'IAB2')),
315
+ array('text' => 'Pickup', 'value' => 'IAB2-18', 'metadata' => array('parent' => 'IAB2')),
316
+ array('text' => 'Road-Side Assistance', 'value' => 'IAB2-19', 'metadata' => array('parent' => 'IAB2')),
317
+ array('text' => 'Sedan', 'value' => 'IAB2-20', 'metadata' => array('parent' => 'IAB2')),
318
+ array('text' => 'Trucks & Accessories', 'value' => 'IAB2-21', 'metadata' => array('parent' => 'IAB2')),
319
+ array('text' => 'Vintage Cars', 'value' => 'IAB2-22', 'metadata' => array('parent' => 'IAB2')),
320
+ array('text' => 'Wagon', 'value' => 'IAB2-23', 'metadata' => array('parent' => 'IAB2')),
321
+ array('text' => 'Advertising', 'value' => 'IAB3-1', 'metadata' => array('parent' => 'IAB3')),
322
+ array('text' => 'Agriculture', 'value' => 'IAB3-2', 'metadata' => array('parent' => 'IAB3')),
323
+ array('text' => 'Biotech/Biomedical', 'value' => 'IAB3-3', 'metadata' => array('parent' => 'IAB3')),
324
+ array('text' => 'Business Software', 'value' => 'IAB3-4', 'metadata' => array('parent' => 'IAB3')),
325
+ array('text' => 'Construction', 'value' => 'IAB3-5', 'metadata' => array('parent' => 'IAB3')),
326
+ array('text' => 'Forestry', 'value' => 'IAB3-6', 'metadata' => array('parent' => 'IAB3')),
327
+ array('text' => 'Government', 'value' => 'IAB3-7', 'metadata' => array('parent' => 'IAB3')),
328
+ array('text' => 'Green Solutions', 'value' => 'IAB3-8', 'metadata' => array('parent' => 'IAB3')),
329
+ array('text' => 'Human Resources', 'value' => 'IAB3-9', 'metadata' => array('parent' => 'IAB3')),
330
+ array('text' => 'Logistics', 'value' => 'IAB3-10', 'metadata' => array('parent' => 'IAB3')),
331
+ array('text' => 'Marketing', 'value' => 'IAB3-11', 'metadata' => array('parent' => 'IAB3')),
332
+ array('text' => 'Metals', 'value' => 'IAB3-12', 'metadata' => array('parent' => 'IAB3')),
333
+ array('text' => 'Career Planning', 'value' => 'IAB4-1', 'metadata' => array('parent' => 'IAB4')),
334
+ array('text' => 'College', 'value' => 'IAB4-2', 'metadata' => array('parent' => 'IAB4')),
335
+ array('text' => 'Financial Aid', 'value' => 'IAB4-3', 'metadata' => array('parent' => 'IAB4')),
336
+ array('text' => 'Job Fairs', 'value' => 'IAB4-4', 'metadata' => array('parent' => 'IAB4')),
337
+ array('text' => 'Job Search', 'value' => 'IAB4-5', 'metadata' => array('parent' => 'IAB4')),
338
+ array('text' => 'Resume Writing/Advice', 'value' => 'IAB4-6', 'metadata' => array('parent' => 'IAB4')),
339
+ array('text' => 'Nursing', 'value' => 'IAB4-7', 'metadata' => array('parent' => 'IAB4')),
340
+ array('text' => 'Scholarships', 'value' => 'IAB4-8', 'metadata' => array('parent' => 'IAB4')),
341
+ array('text' => 'Telecommuting', 'value' => 'IAB4-9', 'metadata' => array('parent' => 'IAB4')),
342
+ array('text' => 'U.S. Military', 'value' => 'IAB4-10', 'metadata' => array('parent' => 'IAB4')),
343
+ array('text' => 'Career Advice', 'value' => 'IAB4-11', 'metadata' => array('parent' => 'IAB4')),
344
+ array('text' => '7-12 Education', 'value' => 'IAB5-1', 'metadata' => array('parent' => 'IAB5')),
345
+ array('text' => 'Adult Education', 'value' => 'IAB5-2', 'metadata' => array('parent' => 'IAB5')),
346
+ array('text' => 'Art History', 'value' => 'IAB5-3', 'metadata' => array('parent' => 'IAB5')),
347
+ array('text' => 'Colledge Administration', 'value' => 'IAB5-4', 'metadata' => array('parent' => 'IAB5')),
348
+ array('text' => 'College Life', 'value' => 'IAB5-5', 'metadata' => array('parent' => 'IAB5')),
349
+ array('text' => 'Distance Learning', 'value' => 'IAB5-6', 'metadata' => array('parent' => 'IAB5')),
350
+ array('text' => 'English as a 2nd Language', 'value' => 'IAB5-7', 'metadata' => array('parent' => 'IAB5')),
351
+ array('text' => 'Language Learning', 'value' => 'IAB5-8', 'metadata' => array('parent' => 'IAB5')),
352
+ array('text' => 'Graduate School', 'value' => 'IAB5-9', 'metadata' => array('parent' => 'IAB5')),
353
+ array('text' => 'Homeschooling', 'value' => 'IAB5-10', 'metadata' => array('parent' => 'IAB5')),
354
+ array('text' => 'Homework/Study Tips', 'value' => 'IAB5-11', 'metadata' => array('parent' => 'IAB5')),
355
+ array('text' => 'K-6 Educators', 'value' => 'IAB5-12', 'metadata' => array('parent' => 'IAB5')),
356
+ array('text' => 'Private School', 'value' => 'IAB5-13', 'metadata' => array('parent' => 'IAB5')),
357
+ array('text' => 'Special Education', 'value' => 'IAB5-14', 'metadata' => array('parent' => 'IAB5')),
358
+ array('text' => 'Studying Business', 'value' => 'IAB5-15', 'metadata' => array('parent' => 'IAB5')),
359
+ array('text' => 'Adoption', 'value' => 'IAB6-1', 'metadata' => array('parent' => 'IAB6')),
360
+ array('text' => 'Babies & Toddlers', 'value' => 'IAB6-2', 'metadata' => array('parent' => 'IAB6')),
361
+ array('text' => 'Daycare/Pre School', 'value' => 'IAB6-3', 'metadata' => array('parent' => 'IAB6')),
362
+ array('text' => 'Family Internet', 'value' => 'IAB6-4', 'metadata' => array('parent' => 'IAB6')),
363
+ array(