Visitors Traffic Real Time Statistics - Version 1.17

Version Description

  1. bug fixing in RTL interface
  2. adding subscription box
Download this release

Release Info

Developer osamaesh
Plugin Icon 128x128 Visitors Traffic Real Time Statistics
Version 1.17
Comparing to
See all releases

Code changes from version 1.3 to 1.17

Files changed (102) hide show
  1. Visitors-Traffic-Real-Time-Statistics.php +131 -10
  2. WPHitsCounter.php +1031 -470
  3. ahc_about.php +0 -0
  4. ahc_help.php +0 -0
  5. ahc_settings.php +5 -0
  6. css/ar_css.css +1 -1
  7. css/en_newcss.css +0 -115
  8. css/eng_css.css +222 -0
  9. css/{en_css.css → engl_css.css} +120 -18
  10. css/jquery.jqplot.min.css +1 -0
  11. css/sweetalerts.css +1 -0
  12. database_basics_data.php +2 -1
  13. functions.php +2061 -1012
  14. images/247.png +0 -0
  15. images/24_7.ico +0 -0
  16. images/Icon-user.png +0 -0
  17. images/Spinner-1s-200px.svg +49 -0
  18. images/VisualEditor_-_Icon_-_Search.svg.png +0 -0
  19. images/browsers_nodata.png +0 -0
  20. images/contact-center-reporting-icon.png +0 -0
  21. images/decrease.png +0 -0
  22. images/down.png +0 -0
  23. images/increase.png +0 -0
  24. images/latestwords_nodata.png +0 -0
  25. images/live.gif +0 -0
  26. images/logo.png +0 -0
  27. images/myheaderbg.png +0 -0
  28. images/new_ticket_title.jpg +0 -0
  29. images/newticket.png +0 -0
  30. images/online.png +0 -0
  31. images/openW.jpg +0 -0
  32. images/openW.png +0 -0
  33. images/output_ZD6GUg-1-2.gif +0 -0
  34. images/plugin-1.png +0 -0
  35. images/plugin-2.png +0 -0
  36. images/plugin-3.png +0 -0
  37. images/plugin-4.png +0 -0
  38. images/plugin-5.png +0 -0
  39. images/plugin-6.png +0 -0
  40. images/recent_nodata.png +0 -0
  41. images/se_nodata.png +0 -0
  42. images/searchengin.png +0 -0
  43. images/searchengins.png +0 -0
  44. images/settings.jpg +0 -0
  45. images/stats.png +0 -0
  46. images/stats2.png +0 -0
  47. images/stats2.psd +0 -0
  48. images/stats3.png +0 -0
  49. images/topref_nodata.png +0 -0
  50. images/up.png +0 -0
  51. images/upgrade.png +0 -0
  52. images/visitors.png +0 -0
  53. images/visits.png +0 -0
  54. images/vtrts.png +0 -0
  55. images/vtrts_ads.gif +0 -0
  56. images/wordpress-plugins.png +0 -0
  57. init.php +55 -25
  58. js/ahc_jqscripts.js +358 -0
  59. js/front.js +59 -0
  60. js/jqplot.canvasAxisLabelRenderer.min.js +3 -0
  61. js/jqplot.canvasAxisTickRenderer.min.js +3 -0
  62. js/jqplot.canvasTextRenderer.min.js +3 -0
  63. js/jqplot.dateAxisRenderer.min.js +3 -0
  64. js/jqplot.enhancedLegendRenderer.min.js +3 -0
  65. js/jqplot.highlighter.min.js +3 -0
  66. js/jqplot.pieRenderer.min.js +3 -0
  67. js/jquery.jqplot.min.js +8 -0
  68. js/js.js +0 -183
  69. js/sweetalert.min.js +1 -0
  70. lang/ar_lang.php +23 -23
  71. lang/en_lang.php +23 -23
  72. lang/js/ar_lang.js +3 -3
  73. lang/js/en_lang.js +3 -3
  74. lib/Chart_js/.gitignore +0 -7
  75. lib/Chart_js/CONTRIBUTING.md +0 -20
  76. lib/Chart_js/Chart.js +0 -3379
  77. lib/Chart_js/Chart.min.js +5 -9
  78. lib/Chart_js/bower.json +0 -11
  79. lib/Chart_js/docs/00-Getting-Started.md +0 -200
  80. lib/Chart_js/docs/01-Line-Chart.md +0 -160
  81. lib/Chart_js/docs/02-Bar-Chart.md +0 -143
  82. lib/Chart_js/docs/03-Radar-Chart.md +0 -177
  83. lib/Chart_js/docs/04-Polar-Area-Chart.md +0 -172
  84. lib/Chart_js/docs/05-Pie-Doughnut-Chart.md +0 -158
  85. lib/Chart_js/docs/06-Advanced.md +0 -152
  86. lib/Chart_js/docs/07-Notes.md +0 -42
  87. lib/Chart_js/gulpfile.js +0 -131
  88. lib/Chart_js/package.json +0 -24
  89. lib/Chart_js/samples/bar.html +0 -48
  90. lib/Chart_js/samples/doughnut.html +0 -67
  91. lib/Chart_js/samples/line.html +0 -54
  92. lib/Chart_js/samples/pie.html +0 -58
  93. lib/Chart_js/samples/polar-area.html +0 -60
  94. lib/Chart_js/samples/radar.html +0 -53
  95. lib/Chart_js/src/Chart.Bar.js +0 -294
  96. lib/Chart_js/src/Chart.Core.js +0 -1943
  97. lib/Chart_js/src/Chart.Doughnut.js +0 -184
  98. lib/Chart_js/src/Chart.Line.js +0 -366
  99. lib/Chart_js/src/Chart.PolarArea.js +0 -248
  100. lib/Chart_js/src/Chart.Radar.js +0 -343
  101. lib/Chart_js/utils.js +147 -0
  102. lib/bootstrap/css/bootstrap-rtl.min.css +8 -0
Visitors-Traffic-Real-Time-Statistics.php CHANGED
@@ -1,21 +1,142 @@
1
  <?php
2
  /*
3
- Plugin Name: Visitors Traffic Real Time Statistics
4
- Description: Hits counter that shows analytical numbers of your WordPress site visitors and hits. <a href="admin.php?page=ahc_hits_counter_menu">Dashboard</a> | <a href="http://www.wp-buy.com/product/visitors-traffic-real-time-statistics-pro">Upgrade to pro.</a>
5
  Author: wp-buy
6
  Author URI: https://www.wp-buy.com/
7
- Version: 1.3
8
-
 
9
  */
10
 
11
- define('AHC_PLUGIN_MAIN_FILE', __FILE__);
12
- define('AHC_PLUGIN_ROOT_DIR', dirname(__FILE__));
13
 
14
- require_once("functions.php");
15
- require_once("init.php");
16
 
17
- $path = plugin_basename( __FILE__ );
18
- add_action("after_plugin_row_{$path}", 'ahc_after_plugin_row', 10, 3);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  //--------------------------------------------
21
  ?>
1
  <?php
2
  /*
3
+ Plugin Name: Visitor Traffic Real Time Statistics
4
+ Description: Hits counter that shows analytical numbers of your WordPress site visitors and hits.
5
  Author: wp-buy
6
  Author URI: https://www.wp-buy.com/
7
+ Version: 1.17
8
+ Text Domain: vtrts-free
9
+ Domain Path: /languages
10
  */
11
 
 
 
12
 
 
 
13
 
14
+
15
+ define('AHCFREE_PLUGIN_MAIN_FILE', __FILE__);
16
+ define('AHCFREE_PLUGIN_ROOT_DIR', dirname(__FILE__));
17
+
18
+ require_once(AHCFREE_PLUGIN_ROOT_DIR. "/functions.php");
19
+ require_once(AHCFREE_PLUGIN_ROOT_DIR."/init.php");
20
+
21
+ if( !function_exists('get_plugin_data') ){
22
+ include_once(ABSPATH . 'wp-includes/pluggable.php');
23
+
24
+ }
25
+
26
+
27
+ function ahcfree_plugin_action_links( $links ) {
28
+
29
+ $links = array_merge( array(
30
+ '<a href="' . esc_url( admin_url( '/admin.php?page=ahc_hits_counter_settings' ) ) . '">' . __( 'Settings', 'ahcfree' ) . '</a>',
31
+ '<a href="' . esc_url( admin_url( '/admin.php?page=ahc_hits_counter_menu_free' ) ) . '">' . __( 'Dashboard', 'ahcfree' ) . '</a>',
32
+ '<a target="_blank" href="' . esc_url('https://www.wp-buy.com/product/visitors-traffic-real-time-statistics-pro/' ) . '"><b style="color:green">' . __( 'Upgrade to PRO', 'ahcfree' ) . '</b></a>'
33
+
34
+ ), $links );
35
+
36
+ return $links;
37
+
38
+ }
39
+ add_action( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'ahcfree_plugin_action_links' );
40
+
41
+
42
+ if ( function_exists('get_plugin_data') ) {
43
+ $woodhl_detail = get_plugin_data( __FILE__ );
44
+ $installed_version = get_option( 'visitors-traffic-real-time-statistics-free-version' );
45
+ if( $installed_version != $woodhl_detail['Version'] ){
46
+ add_action( 'plugins_loaded', 'ahcfix_init' );
47
+ update_option( 'visitors-traffic-real-time-statistics-free-version', $woodhl_detail['Version'] );
48
+ }
49
+ }
50
+
51
+
52
+ function ahcfree_HideMessageAjaxFunction()
53
+ {
54
+ add_option( 'ahcfree_upgrade_message','yes');
55
+ }
56
+
57
+
58
+ function ahcfree_after_plugin_row($plugin_file, $plugin_data, $status) {
59
+
60
+ if(get_option('ahcfree_upgrade_message') !='yes')
61
+ {
62
+ $class_name = $plugin_data['slug'];
63
+
64
+ $upgradeMsg = '<tr id="' .$class_name. '-plugin-update-tr" class="plugin-update-tr active">';
65
+ $upgradeMsg .= '<td colspan="3" class="plugin-update">';
66
+ $upgradeMsg .= '<div id="' .$class_name. '-upgradeMsg" class="update-message" style="background:#FFF8E5; padding-left:10px; border-left:#FFB900 solid 4px" >';
67
+
68
+ $upgradeMsg .= 'You are running visitor traffic free. To get more features (<b style="color:red">Online users, GEO locations and visitors on the map</b>), you can <a href="https://www.wp-buy.com/product/visitors-traffic-real-time-statistics-pro/#plugins-page" target="_blank"><strong>upgrade now</strong></a> or ';
69
+
70
+ $upgradeMsg .= '<span id="HideMe" style="cursor:pointer" ><a href="javascript:void(0)"><strong>dismiss</strong></a> this message</span>';
71
+ $upgradeMsg .= '</div>';
72
+ $upgradeMsg .= '</td>';
73
+ $upgradeMsg .= '</tr>';
74
+
75
+
76
+ echo $upgradeMsg;
77
+ ?>
78
+
79
+ <script type="text/javascript">
80
+ jQuery(document).ready(function() {
81
+ var row = jQuery('#<?php echo $class_name;?>-plugin-update-tr').closest('tr').prev();
82
+ jQuery(row).addClass('update');
83
+
84
+
85
+ jQuery("#HideMe").click(function(){
86
+
87
+ jQuery("#<?php echo $class_name;?>-upgradeMsg").empty();
88
+ jQuery("#<?php echo $class_name;?>-upgradeMsg").removeAttr("style");
89
+
90
+ localStorage.setItem("vtrts_hide_upgrade_message", "hide_msg");
91
+
92
+
93
+ });
94
+
95
+ if(localStorage.getItem("vtrts_hide_upgrade_message") == "hide_msg")
96
+ {
97
+
98
+ jQuery("#<?php echo $class_name;?>-upgradeMsg").empty();
99
+ jQuery("#<?php echo $class_name;?>-upgradeMsg").removeAttr("style");
100
+ }
101
+
102
+ });
103
+ </script>
104
+
105
+
106
+ <?php
107
+
108
+ }
109
+ }
110
+
111
+ function ahcfree_row_meta( $meta_fields, $file ) {
112
+
113
+ if ( strpos($file,'Visitors-Traffic-Real-Time-Statistics.php') == false) {
114
+
115
+ return $meta_fields;
116
+ }
117
+
118
+ echo "<style>.pluginrows-rate-stars { display: inline-block; color: #ffb900; position: relative; top: 3px; }.pluginrows-rate-stars svg{ fill:#ffb900; } .pluginrows-rate-stars svg:hover{ fill:#ffb900 } .pluginrows-rate-stars svg:hover ~ svg{ fill:none; } </style>";
119
+
120
+ $plugin_rate = "https://wordpress.org/support/plugin/visitors-traffic-real-time-statistics/reviews/?rate=5#new-post";
121
+ $plugin_filter = "https://wordpress.org/support/plugin/visitors-traffic-real-time-statistics/reviews/?filter=5";
122
+ $svg_xmlns = "https://www.w3.org/2000/svg";
123
+ $svg_icon = '';
124
+
125
+ for ( $i = 0; $i < 5; $i++ ) {
126
+ $svg_icon .= "<svg xmlns='" . esc_url( $svg_xmlns ) . "' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg>";
127
+ }
128
+
129
+ $meta_fields[] = '<a href="' . esc_url( $plugin_filter ) . '" target="_blank"><span class="dashicons dashicons-thumbs-up"></span>' . __( 'Vote!', 'pluginrows' ) . '</a>';
130
+ $meta_fields[] = "<a href='" . esc_url( $plugin_rate ) . "' target='_blank' title='" . esc_html__( 'Rate', 'pluginrows' ) . "'><i class='pluginrows-rate-stars'>" . $svg_icon . "</i></a>";
131
+
132
+ return $meta_fields;
133
+ }
134
+
135
+
136
+ $path = plugin_basename( __FILE__ );
137
+ add_action("after_plugin_row_{$path}", 'ahcfree_after_plugin_row', 10, 3);
138
+ add_action( 'wp_ajax_ahcfree_HideMessageAjaxFunction', 'ahcfree_HideMessageAjaxFunction' );
139
+ add_filter( 'plugin_row_meta', 'ahcfree_row_meta', 10, 4 );
140
 
141
  //--------------------------------------------
142
  ?>
WPHitsCounter.php CHANGED
@@ -1,519 +1,1080 @@
1
  <?php
2
 
3
- //use GeoIp2\Database\Reader;
4
-
5
- class WPHitsCounter{
6
-
7
- var $pageId;
8
- var $pageTitle;
9
- var $postType;
10
- var $ipAddress;
11
- var $ipIsUnknown;
12
- var $userAgent;
13
- var $referer;
14
- var $refererSite;
15
- var $browser;
16
- var $searchEngine;
17
- var $keyWords;
18
- var $requestUri;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
 
20
 
21
- /**
22
- * Constructor
23
- *
24
- * @param integer $page_id
25
- * @param string $page_title Optional
26
- * @param string $post_type Optional
27
- */
28
- public function __construct($page_id, $page_title = NULL, $post_type = NULL){
29
- global $_SERVER;
30
- $this->ipAddress = ahc_get_client_ip_address();
31
- if($this->ipAddress == 'UNKNOWN'){
32
- $this->ipIsUnknown = true;
33
- $this->ipAddress = 'UNKNOWN'.uniqid();
34
- } else{
35
- $this->ipIsUnknown = false;
36
- }
37
 
38
- $this->userAgent = $_SERVER['HTTP_USER_AGENT'];
39
- $this->pageId = (isset($_GET['page_id'])) ? $_GET['page_id'] : $page_id;
40
- $this->pageTitle = $page_title;
41
- $this->postType = $post_type;
42
- $this->requestUri = trim($_SERVER['REQUEST_URI'], '/');
43
- if(isset($_SERVER['HTTP_REFERER']) && !empty($_SERVER['HTTP_REFERER'])){
44
- $hostName = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
45
- if($hostName != $_SERVER['SERVER_NAME']){
46
- $this->referer = $_SERVER['HTTP_REFERER'];
47
- $this->refererSite = $hostName;
48
- }
49
- }
50
- $this->searchEngine = NULL;
51
- $this->keyWords = NULL;
52
  }
 
 
 
 
 
 
 
 
53
  //--------------------------------------------
54
- /**
55
- * Trace visitor hit
56
- *
57
- * @return void
58
- */
59
- public function traceVisitorHit(){
60
- $this->cleanUnwantedRecords();
61
- $this->cleanHitsTable();
62
- if(!$this->isHitRecorded()){
63
- $visitorRecorded = $this->isVisitorRecorded();
64
- $this->getBrowser();
65
- usleep(10000);
66
- if(!empty($this->refererSite)){
67
- $this->getSearchEngine();
68
- }
69
-
70
- if(!$this->isTodayPreparedInDb()){
71
- $this->PrepareForTodayInDb();
72
- }
73
-
74
- if(!$visitorRecorded){
75
- $this->updateVisitsTime(1, 1);
76
- $this->updateVisitors(1, 1);
77
- } else{
78
- $this->updateVisitsTime(0, 1);
79
- $this->updateVisitors(0, 1);
80
- }
81
-
82
- if(!empty($this->pageId) && !empty($this->pageTitle) && $this->postType == 'post'){
83
- $this->updateTitleTraffic($this->pageId, $this->pageTitle);
84
- }
85
-
86
- if(!empty($this->keyWords) && !empty($this->searchEngine)){
87
- $this->updateKeywords($this->ipAddress, $this->keyWords, $this->referer, $this->searchEngine, $this->browser);
88
- }
89
-
90
- if(!empty($this->refererSite)){
91
- $this->updateReferingSites($this->refererSite);
92
- }
93
-
94
- if(!empty($this->searchEngine)){
95
- $this->updateSearchingVisits($this->searchEngine);
96
- }
97
-
98
- $this->updateBrowsers($this->browser);
99
-
100
- if(!$visitorRecorded){
101
- $this->updateRecentVisitors($this->ipAddress, $this->referer, $this->searchEngine, $this->browser);
102
- }
103
-
104
- $this->recordThisHits();
105
- }
106
- }
107
  //--------------------------------------------
108
- /**
109
- * Is visit is already recorded
110
- *
111
- * @return boolean
112
- */
113
- protected function isHitRecorded(){
114
- global $wpdb;
115
- $sql = "SELECT COUNT(`hit_id`) AS ct FROM `ahc_hits` WHERE DATE(`hit_date`) = DATE(NOW()) AND `hit_ip_address` = %s AND `hit_page_id` = %s";
116
- $result = $wpdb->get_results($wpdb->prepare($sql, $this->ipAddress, $this->pageId) , OBJECT);
117
- if($result !== false){
118
- return ((int) $result[0]->ct > 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  }
 
 
121
  //--------------------------------------------
122
- /**
123
- * Is visitor is already recorded
124
- *
125
- * @return boolean
126
- */
127
- protected function isVisitorRecorded(){
128
- global $wpdb;
129
- $sql = "SELECT COUNT(`hit_id`) AS ct FROM `ahc_hits` WHERE DATE(`hit_date`) = DATE(NOW()) AND `hit_ip_address` = %s";
130
- $result = $wpdb->get_results($wpdb->prepare($sql, $this->ipAddress), OBJECT);
131
- if($result !== false){
132
- return ((int) $result[0]->ct > 0);
133
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  }
 
 
135
  //--------------------------------------------
136
- /**
137
- * Detect client browser
138
- *
139
- * @return void
140
- */
141
- protected function getBrowser(){
142
- if(strpos($this->userAgent, 'MSIE') !== false){
143
- $this->browser = 1;
144
- }
145
- elseif(strpos($this->userAgent, 'Trident') !== false){
146
- $this->browser = 1;
147
- }
148
- elseif(strpos($this->userAgent, 'Gecko') !== false){
149
- if(strpos($this->userAgent, 'Firefox') !== false){
150
- $this->browser = 2;
151
- }
152
- elseif(strpos($this->userAgent, 'Netscape') !== false){
153
- $this->browser = 3;
154
- }
155
- elseif(strpos($this->userAgent, 'Chrome') !== false){
156
- $this->browser = 4;
157
- }
158
- else{
159
- $this->browser = 5;
160
- }
161
- }
162
- elseif(strpos($this->userAgent, 'Opera Mini') !== false){
163
- $this->browser = 6;
164
- }
165
- elseif(strpos($this->userAgent, 'Opera') !== false){
166
- $this->browser = 7;
167
- }
168
- elseif(strpos($this->userAgent, 'Safari') !== false){
169
- $this->browser = 8;
170
- }
171
- elseif(strpos($this->userAgent, 'iPad') !== false){
172
- $this->browser = 9;
173
- }
174
- elseif(strpos($this->userAgent, 'Android') !== false){
175
- $this->browser = 10;
176
- }
177
- elseif(strpos($this->userAgent, 'AIR') !== false){
178
- $this->browser = 11;
179
- }
180
- elseif(strpos($this->userAgent, 'Fluid') !== false){
181
- $this->browser = 12;
182
- }
183
- elseif(strpos($this->userAgent, 'Maxthon') !== false){
184
- $this->browser = 13;
185
- }
186
- else{
187
- $this->browser = 14;
188
- }
189
  }
 
 
190
  //--------------------------------------------
191
- /**
192
- * Detect search engine
193
- *
194
- * @uses wpdb::prepare()
195
- * @uses wpdb::get_results()
196
- *
197
- * @return void
198
- */
199
- protected function getSearchEngine(){
200
- global $wpdb;
201
- $sql = "SELECT `srh_id`, `srh_query_parameter`, `srh_identifier` FROM `ahc_search_engines`";
202
- $results = $wpdb->get_results($sql, OBJECT);
203
- if($results !== false){
204
- foreach($results as $s){
205
- if(strpos($this->referer, $s->srh_identifier.'.') !== false){
206
- $this->searchEngine = $s->srh_id;
207
- $this->getKeyWords($s->srh_query_parameter);
208
- }
209
- }
210
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  }
 
 
212
  //--------------------------------------------
213
- /**
214
- * Detect search engine
215
- *
216
- * @uses wpdb::prepare()
217
- * @uses wpdb::get_results()
218
- *
219
- * @return void
220
- */
221
- protected function getKeyWords($query_param){
222
- $query = parse_url($this->referer, PHP_URL_QUERY);
223
- $query = rawurldecode($query);
224
- $arr = array();
225
- parse_str($query, $arr);
226
- if(isset($arr[$query_param])){
227
- $this->keyWords = $arr[$query_param];
228
- }
 
 
 
229
  }
230
- //--------------------------------------------
231
- /**
232
- * Is there a record prepared for today's visits
233
- *
234
- * @uses wpdb::get_results()
235
- *
236
- * @return boolean
237
- */
238
- protected function isTodayPreparedInDb(){
239
- global $wpdb;
240
- $sql = "SELECT COUNT(`vst_id`) AS ct FROM `ahc_visitors` WHERE DATE(`vst_date`) = DATE(NOW())";
241
- $result = $wpdb->get_results($sql, OBJECT);
242
- if($result !== false){
243
- return ((int) $result[0]->ct > 0);
244
- }
245
  }
 
 
246
  //--------------------------------------------
247
- /**
248
- * Prepared a record for today's visits
249
- *
250
- * @uses wpdb::query()
251
- *
252
- * @return boolean
253
- */
254
- protected function PrepareForTodayInDb(){
255
- global $wpdb;
256
- $sql = "INSERT INTO `ahc_visitors` (`vst_date`, `vst_visitors`, `vst_visits`) VALUES (NOW(), 0, 0)";
257
- if($wpdb->query($sql) !== false){
258
- return true;
259
- }
260
- return false;
261
- }
 
 
 
262
  //--------------------------------------------
263
- /**
264
- * Clean daily hits table
265
- *
266
- * @uses wpdb::query()
267
- *
268
- * @return boolean
269
- */
270
- protected function cleanHitsTable(){
271
- global $wpdb;
272
- $sql = "DELETE FROM `ahc_hits` WHERE DATE(`hit_date`) <> DATE(NOW())";
273
- if($wpdb->query($sql) !== false){
274
- return true;
275
- } else{
276
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
  }
 
278
  }
 
 
279
  //--------------------------------------------
280
- /**
281
- * Update browser visits
282
- *
283
- * @uses wpdb::prepare()
284
- * @uses wpdb::query()
285
- *
286
- * @param integer $bsr_id
287
- * @return boolean
288
- */
289
- protected function updateBrowsers($bsr_id){
290
- global $wpdb;
291
- $sql = "UPDATE `ahc_browsers` SET bsr_visits = bsr_visits + 1 WHERE bsr_id = %d";
292
- if($wpdb->query($wpdb->prepare($sql, $bsr_id)) !== false){
293
- return true;
294
- }
295
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
296
  }
 
 
297
  //--------------------------------------------
298
- /**
299
- * Update visits sum order by search engine
300
- *
301
- * @uses wpdb::prepare()
302
- * @uses wpdb::get_results()
303
- * @uses wpdb::query()
304
- *
305
- * @param integer $srh_id
306
- * @return boolean
307
- */
308
- protected function updateSearchingVisits($srh_id){
309
- global $wpdb;
310
- $sql = "SELECT vtsh_id FROM `ahc_searching_visits` WHERE srh_id = %d AND DATE(vtsh_date) = DATE(NOW())";
311
- $result = $wpdb->get_results($wpdb->prepare($sql, $srh_id), OBJECT);
312
- if($result !== false){
313
- if($wpdb->num_rows > 0){
314
- $sql2 = "UPDATE `ahc_searching_visits` SET vtsh_visits = vtsh_visits + 1 WHERE vtsh_id = %d";
315
- return ($wpdb->query($wpdb->prepare($sql2, $result[0]->vtsh_id)) !== false);
316
- } else{
317
- $sql2 = "INSERT INTO `ahc_searching_visits` (srh_id, vtsh_date, vtsh_visits)
318
- VALUES (%d, NOW(), 1)";
319
- return ($wpdb->query($wpdb->prepare($sql2, $srh_id)) !== false);
320
- }
321
- } else{
322
- return false;
323
- }
 
 
 
 
 
 
 
 
324
  }
 
 
325
  //--------------------------------------------
326
- /**
327
- * Update visitors count
328
- *
329
- * @uses wpdb::prepare()
330
- * @uses wpdb::query()
331
- *
332
- * @param integer $visitors Optional
333
- * @param integer $visits Optional
334
- * @return boolean
335
- */
336
- protected function updateVisitors($visitors = 0, $visits = 0){
337
- global $wpdb;
338
- $sql = "UPDATE `ahc_visitors` SET vst_visitors = vst_visitors + %d, vst_visits = vst_visits + %d
339
- WHERE DATE(vst_date) = DATE(NOW())";
340
- return ($wpdb->query($wpdb->prepare($sql, $visitors, $visits)) !== false);
 
 
 
 
 
 
 
 
341
  }
 
 
 
 
342
  //--------------------------------------------
343
- /**
344
- * Update referring sites visits table
345
- *
346
- * @uses wpdb::prepare()
347
- * @uses wpdb::query()
348
- * @uses wpdb::get_results()
349
- *
350
- * @param string $rfr_site_name. referring site name
351
- * @return boolean
352
- */
353
- protected function updateReferingSites($rfr_site_name){
354
- global $wpdb;
355
- $sql = "SELECT rfr_id FROM `ahc_refering_sites` where rfr_site_name = %s";
356
- $result = $wpdb->get_results($wpdb->prepare($sql, $rfr_site_name), OBJECT);
357
- if($result !== false){
358
- if(!empty($result)){
359
- $sql2 = "UPDATE `ahc_refering_sites` SET rfr_visits = rfr_visits + 1 WHERE rfr_id = %d";
360
- return ($wpdb->query($wpdb->prepare($sql2, $result[0]->rfr_id)) !== false);
361
- } else{
362
- $sql2 = "INSERT INTO `ahc_refering_sites` (rfr_site_name, rfr_visits)
363
- VALUES(%s, 1)";
364
- return ($wpdb->query($wpdb->prepare($sql2, $rfr_site_name)) !== false);
365
- }
366
- } else{
367
- return false;
368
- }
 
 
 
369
  }
 
 
370
  //--------------------------------------------
371
- /**
372
- * Update recent visitors table
373
- *
374
- * @uses wpdb::prepare()
375
- * @uses wpdb::query()
376
- *
377
- * @param string $vtr_ip_address. IP address
378
- * @param string $vtr_referer Optional. Referring site name
379
- * @param integer $srh_id Optional. Search engine ID
380
- * @param integer $bsr_id Optional. Browser ID
381
- * @param integer $ctr_id Optional. Country ID
382
- * @return boolean
383
- */
384
- protected function updateRecentVisitors($vtr_ip_address, $vtr_referer = '', $srh_id = NULL, $bsr_id = NULL, $ctr_id = NULL){
385
- global $wpdb;
386
- $sql = "INSERT INTO `ahc_recent_visitors` (vtr_ip_address, vtr_referer, srh_id, bsr_id, ctr_id, vtr_date, vtr_time)
387
- VALUES (%s, %s, %d, %d, %d, NOW(), NOW())";
388
- return ($wpdb->query($wpdb->prepare($sql, $vtr_ip_address, $vtr_referer, $srh_id, $bsr_id, $ctr_id)) !== false);
 
 
 
 
 
 
 
 
 
389
  }
 
 
 
 
390
  //--------------------------------------------
391
- /**
392
- * Update key words table
393
- *
394
- * @uses wpdb::prepare()
395
- * @uses wpdb::query()
396
- *
397
- * @param string $vtr_ip_address. IP address
398
- * @param string $kwd_keywords. Key word
399
- * @param string $kwd_referer. Referring site name.
400
- * @param integer $srh_id. Search engine ID
401
- * @param integer $bsr_id. Browser ID
402
- * @return boolean
403
- */
404
- protected function updateKeywords($kwd_ip_address, $kwd_keywords, $kwd_referer, $srh_id, $bsr_id){
405
- global $wpdb;
406
- $sql = "INSERT INTO `ahc_keywords` (kwd_ip_address, kwd_keywords, kwd_referer, srh_id, bsr_id, kwd_date, kwd_time)
407
- VALUES (%s, %s, %s, %d, %d, NOW(), NOW())";
408
- return ($wpdb->query($wpdb->prepare($sql, $kwd_ip_address, $kwd_keywords, $kwd_referer, $srh_id, $bsr_id)) !== false);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
409
  }
 
 
410
  //--------------------------------------------
411
- /**
412
- * Clean unwanted records. Only keeping a limit of fresh records. Limit is set by AHC_RECENT_VISITORS_LIMIT
413
- *
414
- * @uses wpdb::prepare()
415
- * @uses wpdb::get_results()
416
- * @uses wpdb::query()
417
- *
418
- * @return boolean
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
419
  */
420
- protected function cleanUnwantedRecords(){
421
- global $wpdb;
422
- $sql11 = "SELECT vtr_id FROM `ahc_recent_visitors` ORDER BY vtr_id LIMIT %d";
423
- $result = $wpdb->get_results($wpdb->prepare($sql11, AHC_RECENT_VISITORS_LIMIT), OBJECT);
424
- if($result !== false){
425
- $ids1 = array();
426
- $length = count($result);
427
- foreach($result as $r){
428
- $ids1[] = $r->vtr_id;
429
- }
430
- $ids1 = implode(',', $ids1);
431
- $sql12 = "DELETE FROM `ahc_recent_visitors`".((!empty($ids1))? " WHERE vtr_id NOT IN (".$ids1.")" : "");
432
-
433
- $sql21 = "SELECT kwd_id FROM `ahc_keywords` ORDER BY kwd_id LIMIT %d";
434
- $result2 = $wpdb->get_results($wpdb->prepare($sql21, AHC_RECENT_KEYWORDS_LIMIT), OBJECT);
435
- if($result2 !== false){
436
- $ids2 = array();
437
- foreach($result2 as $r){
438
- $ids2[] = $r->kwd_id;
439
- }
440
- $ids2 = implode(',', $ids2);
441
- $sql22 = "DELETE FROM `ahc_keywords`".((!empty($ids2))? " WHERE kwd_id NOT IN (".$ids2.")" : "");
442
-
443
- if($wpdb->query($sql12) !== false){
444
- return ($wpdb->query($sql22) !== false);
445
- }
446
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  }
448
- return false;
449
  }
 
 
 
 
450
  //--------------------------------------------
451
- /**
452
- * Update traffic by title table
453
- *
454
- * @uses wpdb::prepare()
455
- * @uses wpdb::get_results()
456
- * @uses wpdb::query()
457
- *
458
- * @param integer $til_page_id
459
- * @param string $til_page_title
460
- * @return boolean
461
- */
462
- protected function updateTitleTraffic($til_page_id, $til_page_title){
463
- global $wpdb;
464
- $sql = "SELECT til_id FROM `ahc_title_traffic` where til_page_id = %s";
465
- $result = $wpdb->get_results($wpdb->prepare($sql, $til_page_id), OBJECT);
466
- if($result !== false){
467
- if(!empty($result)){
468
- $sql2 = "UPDATE `ahc_title_traffic`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
469
  SET til_hits = til_hits + 1, til_page_title = %s
 
470
  WHERE til_id = %d";
471
- return ($wpdb->query($wpdb->prepare($sql2, $til_page_title, $result[0]->til_id)) !== false);
472
- } else{
473
- $sql2 = "INSERT INTO `ahc_title_traffic` (til_page_id, til_page_title, til_hits)
 
 
 
474
  VALUES(%s, %s, 1)";
475
- return ($wpdb->query($wpdb->prepare($sql2, $til_page_id, $til_page_title)) !== false);
476
- }
477
- } else{
478
- return false;
479
- }
 
480
  }
 
 
481
  //--------------------------------------------
482
- /**
483
- * Update visitor's & visits' times table
484
- *
485
- * @uses wpdb::prepare()
486
- * @uses wpdb::query()
487
- *
488
- * @param integer $visitors Optional
489
- * @param integer $visits Optional
490
- * @return boolean
491
- */
492
- protected function updateVisitsTime($visitors = 0, $visits = 0){
493
- global $wpdb;
494
- $sql = "UPDATE `ahc_visits_time` SET vtm_visitors = vtm_visitors + %d, vtm_visits = vtm_visits + %d
495
- WHERE TIME(vtm_time_from) <= TIME(NOW()) AND TIME(vtm_time_to) >= TIME(NOW())";
496
- return ($wpdb->query($wpdb->prepare($sql, $visitors, $visits)) !== false);
497
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
498
  //--------------------------------------------
499
- /**
500
- * Record (insert) the visit
501
- *
502
- * @uses wpdb::prepare()
503
- * @uses wpdb::query()
504
- *
505
- * @return boolean
506
- */
507
- protected function recordThisHits(){
508
- global $wpdb;
509
- $sql = "INSERT INTO `ahc_hits`
510
- (`hit_ip_address`, `hit_user_agent`, `hit_request_uri`, `hit_page_id`, `hit_page_title`, `hit_referer`, `hit_referer_site`,
 
 
 
 
 
 
 
 
 
 
 
 
511
  `srh_id`, `hit_search_words`, `bsr_id`, `hit_date`, `hit_time`)
512
- VALUES (%s, %s, %s, %s, %s, %s, %s, %d, %s, %d, NOW(), NOW())";
513
- $result = $wpdb->query($wpdb->prepare($sql, $this->ipAddress, $this->userAgent, $this->requestUri, $this->pageId, $this->pageTitle,
514
- $this->referer, $this->refererSite, $this->searchEngine, $this->keyWords, $this->browser));
515
- return ($result !== false);
516
- }
 
 
 
517
  //--------------------------------------------
518
  }
519
- ?>
 
1
  <?php
2
 
3
+ class AHCFree_WPHitsCounterPro {
4
+
5
+ var $pageId;
6
+ var $pageTitle;
7
+ var $postType;
8
+ var $ipAddress;
9
+ var $ipIsUnknown;
10
+ var $userAgent;
11
+ var $referer;
12
+ var $refererSite;
13
+ var $browser;
14
+ var $searchEngine;
15
+ var $countryInternetCode;
16
+ var $countryId;
17
+ var $keyWords;
18
+ var $requestUri;
19
+
20
+ /**
21
+
22
+ * Constructor
23
+
24
+ *
25
+
26
+ * @param integer $page_id
27
+
28
+ * @param string $page_title Optional
29
+
30
+ * @param string $post_type Optional
31
+
32
+ */
33
+ public function __construct($page_id, $page_title = NULL, $post_type = NULL) {
34
+
35
+ global $_SERVER;
36
+
37
+ $this->ipAddress = ahcfree_get_client_ip_address();
38
+
39
+
40
+ if ($this->ipAddress == 'UNKNOWN') {
41
+
42
+ $this->ipIsUnknown = true;
43
+
44
+ $this->ipAddress = 'UNKNOWN' . uniqid();
45
+ } else {
46
+
47
+ $this->ipIsUnknown = false;
48
+ }
49
+
50
+
51
+
52
+ $this->userAgent = $_SERVER['HTTP_USER_AGENT'];
53
+
54
+ $this->pageId = (isset($page_id)) ? $page_id : $_GET['page_id'];
55
+
56
+ $this->pageTitle = $page_title;
57
+
58
+ $this->postType = $post_type;
59
 
60
+ $this->requestUri = trim($_SERVER['REQUEST_URI'], '/');
61
 
62
+ //$post_permalink = get_the_permalink($this->pageId);
63
+ //$protocol_arr = array('http://','https://','www.');
64
+ //$link = str_replace($protocol_arr,'',$post_permalink);
65
+ //$this->requestUri = trim(str_replace($_SERVER['HTTP_HOST'],'',$link),'/');
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
+ if (isset($_SERVER['HTTP_REFERER']) && !empty($_SERVER['HTTP_REFERER'])) {
68
+
69
+ $hostName = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
70
+
71
+ if ($hostName != $_SERVER['SERVER_NAME']) {
72
+
73
+ $this->referer = $_SERVER['HTTP_REFERER'];
74
+
75
+ $this->refererSite = $hostName;
76
+ }
 
 
 
 
77
  }
78
+
79
+ $this->searchEngine = NULL;
80
+
81
+ $this->keyWords = NULL;
82
+
83
+ $this->countryId = NULL;
84
+ }
85
+
86
  //--------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  //--------------------------------------------
88
+
89
+ /**
90
+
91
+ * Trace visitor hit
92
+
93
+ *
94
+
95
+ * @return void
96
+
97
+ */
98
+ public function traceVisitorHit() {
99
+
100
+ //$this->cleanUnwantedRecords();
101
+
102
+ $this->cleanHitsTable();
103
+
104
+ if (!$this->isHitRecorded()) {
105
+
106
+ $visitorRecorded = $this->isVisitorRecorded();
107
+
108
+ $this->getBrowser();
109
+
110
+ usleep(1000);
111
+
112
+ if (!empty($this->refererSite)) {
113
+
114
+ $this->getSearchEngine();
115
+ }
116
+
117
+
118
+ /*
119
+ if (!$this->isTodayPreparedInDb()) {
120
+
121
+ $this->PrepareForTodayInDb();
122
+ }*/
123
+
124
+
125
+
126
+ if (!$visitorRecorded) {
127
+
128
+ $this->updateVisitsTime(1, 1);
129
+
130
+ $this->updateVisitors(1, 1);
131
+ } else {
132
+
133
+ $this->updateVisitsTime(0, 1);
134
+
135
+ $this->updateVisitors(0, 1);
136
+ }
137
+
138
+
139
+ if (!empty($this->pageId) && !empty($this->pageTitle) && ($this->postType == 'post' or $this->postType == 'product' or $this->postType == 'page')) {
140
+
141
+
142
+
143
+ $this->updateTitleTraffic($this->pageId, $this->pageTitle);
144
+ }
145
+
146
+
147
+
148
+ if (!empty($this->keyWords) && !empty($this->searchEngine)) {
149
+
150
+ $this->updateKeywords($this->ipAddress, $this->keyWords, $this->referer, $this->searchEngine, $this->browser, $this->countryId);
151
+ }
152
+
153
+
154
+
155
+ if (!empty($this->refererSite)) {
156
+
157
+ $this->updateReferingSites($this->refererSite);
158
+ }
159
+
160
+
161
+
162
+ if (!empty($this->searchEngine)) {
163
+
164
+ $this->updateSearchingVisits($this->searchEngine);
165
+ }
166
+
167
+
168
+
169
+ if (!empty($this->countryId)) {
170
+
171
+ if ($visitorRecorded) {
172
+
173
+ $this->updateCountries($this->countryId, 0, 1);
174
+ } else {
175
+
176
+ $this->updateCountries($this->countryId, 1, 1);
177
  }
178
+ }
179
+
180
+ $this->updateBrowsers($this->browser);
181
+
182
+
183
+
184
+ if (!$visitorRecorded) {
185
+
186
+ $this->updateRecentVisitors($this->ipAddress, $this->referer, $this->searchEngine, $this->browser, $this->countryId);
187
+ }
188
+
189
+
190
+
191
+ $this->recordThisHits();
192
  }
193
+ }
194
+
195
  //--------------------------------------------
196
+
197
+ /**
198
+
199
+ * Is visit is already recorded
200
+
201
+ *
202
+
203
+ * @return boolean
204
+
205
+ */
206
+ protected function isHitRecorded() {
207
+
208
+ global $wpdb;
209
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
210
+
211
+ $wpdb->insert(
212
+ 'ahc_online_users',
213
+ array(
214
+ 'date' => date('Y-m-d H:i:s'),
215
+ 'hit_ip_address' => $this->ipAddress,
216
+ 'hit_page_id' => $this->pageId,
217
+ )
218
+ );
219
+
220
+ $sql = "SELECT COUNT(`hit_id`) AS ct FROM `ahc_hits` WHERE DATE(`hit_date`) = '". date("Y-m-d") ."' AND `hit_ip_address` = %s AND `hit_page_id` = %s";
221
+
222
+ //$sql = "SELECT COUNT(`hit_id`) AS ct FROM `ahc_hits` WHERE DATE(CONVERT_TZ(CONCAT_WS(' ',hit_date,hit_time),'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) = DATE(CONVERT_TZ(NOW( ),'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) AND `hit_ip_address` = %s AND `hit_page_id` = %s";
223
+
224
+ $result = $wpdb->get_results($wpdb->prepare($sql, $this->ipAddress, $this->pageId), OBJECT);
225
+
226
+ if ($result !== false) {
227
+
228
+ return ((int) $result[0]->ct > 0);
229
  }
230
+ }
231
+
232
  //--------------------------------------------
233
+
234
+ /**
235
+
236
+ * Is visitor is already recorded
237
+
238
+ *
239
+
240
+ * @return boolean
241
+
242
+ */
243
+ protected function isVisitorRecorded() {
244
+
245
+ global $wpdb;
246
+
247
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
248
+
249
+ $sql = "SELECT COUNT(`hit_id`) AS ct FROM `ahc_hits` WHERE DATE(`hit_date`) = '". date("Y-m-d") ."' AND `hit_ip_address` = %s";
250
+
251
+ //$sql = "SELECT COUNT(`hit_id`) AS ct FROM `ahc_hits` WHERE DATE(CONVERT_TZ(CONCAT_WS(' ',hit_date,hit_time),'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) = DATE(CONVERT_TZ(NOW( ),'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) AND `hit_ip_address` = %s";
252
+
253
+ $result = $wpdb->get_results($wpdb->prepare($sql, $this->ipAddress), OBJECT);
254
+ if ($result !== false) {
255
+
256
+ return ((int) $result[0]->ct > 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  }
258
+ }
259
+
260
  //--------------------------------------------
261
+
262
+ /**
263
+
264
+ * Detect client browser
265
+
266
+ *
267
+
268
+ * @return void
269
+
270
+ */
271
+ protected function getBrowser() {
272
+
273
+ if (strpos($this->userAgent, 'MSIE') !== false) {
274
+
275
+ $this->browser = 1;
276
+ } elseif (strpos($this->userAgent, 'Trident') !== false) {
277
+
278
+ $this->browser = 1;
279
+ } elseif (strpos($this->userAgent, 'Gecko') !== false) {
280
+
281
+ if (strpos($this->userAgent, 'Firefox') !== false) {
282
+
283
+ $this->browser = 2;
284
+ } elseif (strpos($this->userAgent, 'Netscape') !== false) {
285
+
286
+ $this->browser = 3;
287
+ } elseif (strpos($this->userAgent, 'Chrome') !== false) {
288
+
289
+ $this->browser = 4;
290
+ } else {
291
+
292
+ $this->browser = 5;
293
+ }
294
+ } elseif (strpos($this->userAgent, 'Opera Mini') !== false) {
295
+
296
+ $this->browser = 6;
297
+ } elseif (strpos($this->userAgent, 'Opera') !== false) {
298
+
299
+ $this->browser = 7;
300
+ } elseif (strpos($this->userAgent, 'Safari') !== false) {
301
+
302
+ $this->browser = 8;
303
+ } elseif (strpos($this->userAgent, 'iPad') !== false) {
304
+
305
+ $this->browser = 9;
306
+ } elseif (strpos($this->userAgent, 'Android') !== false) {
307
+
308
+ $this->browser = 10;
309
+ } elseif (strpos($this->userAgent, 'AIR') !== false) {
310
+
311
+ $this->browser = 11;
312
+ } elseif (strpos($this->userAgent, 'Fluid') !== false) {
313
+
314
+ $this->browser = 12;
315
+ } elseif (strpos($this->userAgent, 'Maxthon') !== false) {
316
+
317
+ $this->browser = 13;
318
+ } else {
319
+
320
+ $this->browser = 14;
321
  }
322
+ }
323
+
324
  //--------------------------------------------
325
+
326
+ /**
327
+
328
+ * Detect country internet code
329
+
330
+ *
331
+
332
+ * @return void
333
+
334
+ */
335
+ protected function getCountryInternetCode() {
336
+
337
+ if (!$this->ipIsUnknown) {
338
+
339
+ $gi = geoip_open(AHCFREE_PLUGIN_ROOT_DIR . AHCFREE_DS . "geoip" . AHCFREE_DS . "data" . AHCFREE_DS . "GeoIP.dat", GEOIP_STANDARD);
340
+
341
+ $this->countryInternetCode = geoip_country_code_by_addr($gi, $this->ipAddress);
342
+
343
+ geoip_close($gi);
344
  }
345
+
346
+ if (empty($this->countryInternetCode)) {
347
+
348
+ $this->countryInternetCode = 'XX';
 
 
 
 
 
 
 
 
 
 
 
349
  }
350
+ }
351
+
352
  //--------------------------------------------
353
+
354
+ /**
355
+
356
+ * Detect country ID
357
+
358
+ *
359
+
360
+ * @uses wpdb::prepare()
361
+
362
+ * @uses wpdb::get_results()
363
+
364
+ *
365
+
366
+ * @return void
367
+
368
+ */
369
+
370
+
371
  //--------------------------------------------
372
+
373
+ /**
374
+
375
+ * Detect search engine
376
+
377
+ *
378
+
379
+ * @uses wpdb::prepare()
380
+
381
+ * @uses wpdb::get_results()
382
+
383
+ *
384
+
385
+ * @return void
386
+
387
+ */
388
+ protected function getSearchEngine() {
389
+
390
+ global $wpdb;
391
+
392
+ $sql = "SELECT `srh_id`, `srh_query_parameter`, `srh_identifier` FROM `ahc_search_engines`";
393
+
394
+ $results = $wpdb->get_results($sql, OBJECT);
395
+
396
+ if ($results !== false) {
397
+
398
+ foreach ($results as $s) {
399
+
400
+ if (strpos($this->referer, $s->srh_identifier . '.') !== false) {
401
+
402
+ $this->searchEngine = $s->srh_id;
403
+
404
+ $this->getKeyWords($s->srh_query_parameter);
405
  }
406
+ }
407
  }
408
+ }
409
+
410
  //--------------------------------------------
411
+
412
+ /**
413
+
414
+ * Detect search engine
415
+
416
+ *
417
+
418
+ * @uses wpdb::prepare()
419
+
420
+ * @uses wpdb::get_results()
421
+
422
+ *
423
+
424
+ * @return void
425
+
426
+ */
427
+ protected function getKeyWords($query_param) {
428
+
429
+ $query = parse_url($this->referer, PHP_URL_QUERY);
430
+
431
+ $query = rawurldecode($query);
432
+
433
+ $arr = array();
434
+
435
+ parse_str($query, $arr);
436
+
437
+ if (isset($arr[$query_param])) {
438
+
439
+ $this->keyWords = $arr[$query_param];
440
  }
441
+ }
442
+
443
  //--------------------------------------------
444
+
445
+ /**
446
+
447
+ * Is there a record prepared for today's visits
448
+
449
+ *
450
+
451
+ * @uses wpdb::get_results()
452
+
453
+ *
454
+
455
+ * @return boolean
456
+
457
+ */
458
+ protected function isTodayPreparedInDb() {
459
+
460
+ global $wpdb;
461
+
462
+ $del_sql = "DELETE v1 FROM ahc_visitors v1, ahc_visitors v2 WHERE v1.`vst_id` > v2.`vst_id` AND v1.`vst_date` = v2.`vst_date`";
463
+
464
+ //$del_sql = "DELETE v1 FROM ahc_visitors v1, ahc_visitors v2 WHERE v1.`vst_id` > v2.`vst_id` AND CONVERT_TZ(v1.vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "') = CONVERT_TZ(v2.vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "') ";
465
+
466
+ $del_result = $wpdb->get_results($del_sql, OBJECT);
467
+
468
+
469
+ $sql = "SELECT COUNT(`vst_id`) AS ct FROM `ahc_visitors` WHERE DATE(`vst_date`) = '".date("Y-m-d")."'";
470
+
471
+ //$sql = "SELECT COUNT(`vst_id`) AS ct FROM `ahc_visitors` WHERE DATE(CONVERT_TZ(vst_date,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) = DATE(CONVERT_TZ(NOW( ),'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "'))";
472
+
473
+ $result = $wpdb->get_results($sql, OBJECT);
474
+
475
+ if ($result !== false) {
476
+
477
+ return ((int) $result[0]->ct > 0);
478
  }
479
+ }
480
+
481
  //--------------------------------------------
482
+
483
+ /**
484
+
485
+ * Prepared a record for today's visits
486
+
487
+ *
488
+
489
+ * @uses wpdb::query()
490
+
491
+ *
492
+
493
+ * @return boolean
494
+
495
+ */
496
+ protected function PrepareForTodayInDb() {
497
+
498
+ global $wpdb;
499
+
500
+ $sql = "INSERT INTO `ahc_visitors` (`vst_date`, `vst_visitors`, `vst_visits`) VALUES ('".date("Y-m-d H:i:s")."', 0, 0)";
501
+
502
+ if ($wpdb->query($sql) !== false) {
503
+
504
+ return true;
505
  }
506
+
507
+ return false;
508
+ }
509
+
510
  //--------------------------------------------
511
+
512
+ /**
513
+
514
+ * Clean daily hits table
515
+
516
+ *
517
+
518
+ * @uses wpdb::query()
519
+
520
+ *
521
+
522
+ * @return boolean
523
+
524
+ */
525
+ protected function cleanHitsTable() {
526
+
527
+ global $wpdb;
528
+
529
+ $sql = "DELETE FROM ahc_online_users WHERE DATE(`date`) <> '".date("Y-m-d")."'";
530
+ $wpdb->query($sql);
531
+
532
+ $sql = "DELETE FROM `ahc_hits` WHERE DATE(`hit_date`) <> '".date("Y-m-d")."'";
533
+
534
+ if ($wpdb->query($sql) !== false) {
535
+
536
+ return true;
537
+ } else {
538
+
539
+ return false;
540
  }
541
+ }
542
+
543
  //--------------------------------------------
544
+
545
+ /**
546
+
547
+ * Update browser visits
548
+
549
+ *
550
+
551
+ * @uses wpdb::prepare()
552
+
553
+ * @uses wpdb::query()
554
+
555
+ *
556
+
557
+ * @param integer $bsr_id
558
+
559
+ * @return boolean
560
+
561
+ */
562
+ protected function updateBrowsers($bsr_id) {
563
+
564
+ global $wpdb;
565
+
566
+ $sql = "UPDATE `ahc_browsers` SET bsr_visits = bsr_visits + 1 WHERE bsr_id = %d";
567
+
568
+ if ($wpdb->query($wpdb->prepare($sql, $bsr_id)) !== false) {
569
+
570
+ return true;
571
  }
572
+
573
+ return false;
574
+ }
575
+
576
  //--------------------------------------------
577
+
578
+ /**
579
+
580
+ * Update country visits
581
+
582
+ *
583
+
584
+ * @uses wpdb::prepare()
585
+
586
+ * @uses wpdb::query()
587
+
588
+ *
589
+
590
+ * @param integer $ctr_id
591
+
592
+ * @param integer $visitors Optional
593
+
594
+ * @param integer $visits Optional
595
+
596
+ * @return boolean
597
+
598
+ */
599
+ protected function updateCountries($ctr_id, $visitors = 0, $visits = 0) {
600
+
601
+ global $wpdb;
602
+
603
+ $sql = "UPDATE `ahc_countries` SET ctr_visitors = ctr_visitors + %d, ctr_visits = ctr_visits + %d WHERE ctr_id = %d";
604
+
605
+ return ($wpdb->query($wpdb->prepare($sql, $visitors, $visits, $ctr_id)) !== false);
606
+ }
607
+
608
+ //--------------------------------------------
609
+
610
+ /**
611
+
612
+ * Update visits sum order by search engine
613
+
614
+ *
615
+
616
+ * @uses wpdb::prepare()
617
+
618
+ * @uses wpdb::get_results()
619
+
620
+ * @uses wpdb::query()
621
+
622
+ *
623
+
624
+ * @param integer $srh_id
625
+
626
+ * @return boolean
627
+
628
+ */
629
+ protected function updateSearchingVisits($srh_id) {
630
+
631
+ global $wpdb;
632
+
633
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
634
+
635
+ $sql = "SELECT vtsh_id FROM `ahc_searching_visits` WHERE srh_id = %d AND DATE(vtsh_date) = '".date("Y-m-d")."'";
636
+ //$sql = "SELECT vtsh_id FROM `ahc_searching_visits` WHERE srh_id = %d AND DATE(CONVERT_TZ(vtsh_date,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) = DATE(CONVERT_TZ(NOW( ),'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "'))";
637
+
638
+ $result = $wpdb->get_results($wpdb->prepare($sql, $srh_id), OBJECT);
639
+
640
+ if ($result !== false) {
641
+
642
+ if ($wpdb->num_rows > 0) {
643
+
644
+ $sql2 = "UPDATE `ahc_searching_visits` SET vtsh_visits = vtsh_visits + 1 WHERE vtsh_id = %d";
645
+
646
+ return ($wpdb->query($wpdb->prepare($sql2, $result[0]->vtsh_id)) !== false);
647
+ } else {
648
+
649
+ $sql2 = "INSERT INTO `ahc_searching_visits` (srh_id, vtsh_date, vtsh_visits)
650
+
651
+ VALUES (%d, %s, 1)";
652
+
653
+ return ($wpdb->query($wpdb->prepare($sql2, $srh_id, date("Y-m-d H:i:s"))) !== false);
654
+ }
655
+ } else {
656
+
657
+ return false;
658
  }
659
+ }
660
+
661
  //--------------------------------------------
662
+
663
+ /**
664
+
665
+ * Update visitors count
666
+
667
+ *
668
+
669
+ * @uses wpdb::prepare()
670
+
671
+ * @uses wpdb::query()
672
+
673
+ *
674
+
675
+ * @param integer $visitors Optional
676
+
677
+ * @param integer $visits Optional
678
+
679
+ * @return boolean
680
+
681
+ */
682
+ protected function updateVisitors($visitors = 0, $visits = 0) {
683
+
684
+ global $wpdb;
685
+
686
+
687
+ $sql = "INSERT INTO `ahc_daily_visitors_stats` (vst_date, vst_visitors, vst_visits) values(%s, %d, %d )";
688
+
689
+ $wpdb->query($wpdb->prepare($sql, date("Y-m-d H:i:s"), $visitors, $visits));
690
+
691
+ $sql = "INSERT INTO `ahc_visitors` (vst_date, vst_visitors, vst_visits) values(%s, %d, %d )";
692
+ //$sql = "UPDATE `ahc_visitors` SET vst_visitors = vst_visitors + %d, vst_visits = vst_visits + %d WHERE DATE(vst_date) = DATE(NOW())";
693
+
694
+ return ($wpdb->query($wpdb->prepare($sql, date("Y-m-d H:i:s"), $visitors, $visits)) !== false);
695
+ }
696
+
697
+ //--------------------------------------------
698
+
699
+ /**
700
+
701
+ * Update referring sites visits table
702
+
703
+ *
704
+
705
+ * @uses wpdb::prepare()
706
+
707
+ * @uses wpdb::query()
708
+
709
+ * @uses wpdb::get_results()
710
+
711
+ *
712
+
713
+ * @param string $rfr_site_name. referring site name
714
+
715
+ * @return boolean
716
+
717
+ */
718
+ protected function updateReferingSites($rfr_site_name) {
719
+
720
+ global $wpdb;
721
+
722
+ $sql = "SELECT rfr_id FROM `ahc_refering_sites` where rfr_site_name = %s";
723
+
724
+ $result = $wpdb->get_results($wpdb->prepare($sql, $rfr_site_name), OBJECT);
725
+
726
+ if ($result !== false) {
727
+
728
+ if (!empty($result)) {
729
+
730
+ $sql2 = "UPDATE `ahc_refering_sites` SET rfr_visits = rfr_visits + 1 WHERE rfr_id = %d";
731
+
732
+ return ($wpdb->query($wpdb->prepare($sql2, $result[0]->rfr_id)) !== false);
733
+ } else {
734
+
735
+ $sql2 = "INSERT INTO `ahc_refering_sites` (rfr_site_name, rfr_visits)
736
+
737
+ VALUES(%s, 1)";
738
+
739
+ return ($wpdb->query($wpdb->prepare($sql2, $rfr_site_name)) !== false);
740
+ }
741
+ } else {
742
+
743
+ return false;
744
+ }
745
+ }
746
+
747
+ //--------------------------------------------
748
+
749
+ /**
750
+
751
+ * Update recent visitors table
752
+
753
+ *
754
+
755
+ * @uses wpdb::prepare()
756
+
757
+ * @uses wpdb::query()
758
+
759
+ *
760
+
761
+ * @param string $vtr_ip_address. IP address
762
+
763
+ * @param string $vtr_referer Optional. Referring site name
764
+
765
+ * @param integer $srh_id Optional. Search engine ID
766
+
767
+ * @param integer $bsr_id Optional. Browser ID
768
+
769
+ * @param integer $ctr_id Optional. Country ID
770
+
771
+ * @return boolean
772
+
773
+ */
774
+ protected function updateRecentVisitors($vtr_ip_address, $vtr_referer = '', $srh_id = NULL, $bsr_id = NULL, $ctr_id = NULL) {
775
+
776
+ global $wpdb;
777
+
778
+
779
+
780
+
781
+ /* $ip_data = (ahcfree_advanced_get_link("http://ip-api.com/json/".$vtr_ip_address));
782
+ $ip_data = json_decode($ip_data['body']);
783
+
784
+ if($ip_data->city != '')
785
+ {
786
+
787
+ $ahc_city = $ip_data->city;
788
+ $ahc_region = $ip_data->regionName;
789
+ }
790
+
791
+ if(empty($ip_data->city) or empty($ip_data->regionName))
792
+ {
793
+ $ip_data = (ahcfree_advanced_get_link("http://api.db-ip.com/v2/c425dbfb764da5017d283d8a2d53360be0869a4b/".$vtr_ip_address));
794
+ $ip_data = json_decode($ip_data['body']);
795
+
796
+ $ahc_city = $ip_data->city;
797
+ $ahc_region = $ip_data->stateProv;
798
+ }
799
+
800
  */
801
+
802
+
803
+
804
+ $ip_data = (ahcfree_advanced_get_link("http://www.geoplugin.net/json.gp?ip=" . $vtr_ip_address));
805
+ $ip_data = json_decode($ip_data['body']);
806
+
807
+
808
+ if ($ip_data->geoplugin_city != '') {
809
+
810
+ $ahc_city = $ip_data->geoplugin_countryName;
811
+ $ahc_region = $ip_data->geoplugin_city;
812
+ }
813
+
814
+ if (empty($ip_data->geoplugin_city) or empty($ip_data->geoplugin_city)) {
815
+ $ip_data = (ahcfree_advanced_get_link("http://ip-api.com/json/" . $vtr_ip_address));
816
+ $ip_data = json_decode($ip_data['body']);
817
+
818
+ $ahc_city = $ip_data->city;
819
+ $ahc_region = $ip_data->regionName;
820
+ }
821
+
822
+
823
+ $sql = "INSERT INTO `ahc_recent_visitors` (vtr_ip_address, vtr_referer, srh_id, bsr_id, ctr_id, ahc_city, ahc_region, vtr_date, vtr_time) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)";
824
+
825
+
826
+
827
+ return ($wpdb->query($wpdb->prepare($sql, $vtr_ip_address, $vtr_referer, $srh_id, $bsr_id, $ctr_id, $ahc_city, $ahc_region, date("Y-m-d"), date("H:i:s") )) !== false);
828
+ }
829
+
830
+ //--------------------------------------------
831
+
832
+ /**
833
+
834
+ * Update key words table
835
+
836
+ *
837
+
838
+ * @uses wpdb::prepare()
839
+
840
+ * @uses wpdb::query()
841
+
842
+ *
843
+
844
+ * @param string $vtr_ip_address. IP address
845
+
846
+ * @param string $kwd_keywords. Key word
847
+
848
+ * @param string $kwd_referer. Referring site name.
849
+
850
+ * @param integer $srh_id. Search engine ID
851
+
852
+ * @param integer $bsr_id. Browser ID
853
+
854
+ * @param integer $ctr_id Optional. Country ID
855
+
856
+ * @return boolean
857
+
858
+ */
859
+ protected function updateKeywords($kwd_ip_address, $kwd_keywords, $kwd_referer, $srh_id, $bsr_id, $ctr_id = NULL) {
860
+
861
+ global $wpdb;
862
+
863
+ $sql = "INSERT INTO `ahc_keywords` (kwd_ip_address, kwd_keywords, kwd_referer, srh_id, ctr_id, bsr_id, kwd_date, kwd_time)
864
+
865
+ VALUES (%s, %s, %s, %d, %d, %d, %s, %s)";
866
+
867
+ return ($wpdb->query($wpdb->prepare($sql, $kwd_ip_address, $kwd_keywords, $kwd_referer, $srh_id, $ctr_id, $bsr_id, date("Y-m-d"), date("H:i:s"))) !== false);
868
+ }
869
+
870
+ //--------------------------------------------
871
+
872
+ /**
873
+
874
+ * Clean unwanted records. Only keeping a limit of fresh records. Limit is set by AHC_RECENT_VISITORS_LIMIT
875
+
876
+ *
877
+
878
+ * @uses wpdb::prepare()
879
+
880
+ * @uses wpdb::get_results()
881
+
882
+ * @uses wpdb::query()
883
+
884
+ *
885
+
886
+ * @return boolean
887
+
888
+ */
889
+ protected function cleanUnwantedRecords() {
890
+
891
+ global $wpdb;
892
+
893
+ $sql11 = "SELECT vtr_id FROM `ahc_recent_visitors` ORDER BY vtr_id LIMIT %d";
894
+
895
+ $result = $wpdb->get_results($wpdb->prepare($sql11, AHC_RECENT_VISITORS_LIMIT), OBJECT);
896
+
897
+ if ($result !== false) {
898
+
899
+ $ids1 = array();
900
+
901
+ $length = count($result);
902
+
903
+ foreach ($result as $r) {
904
+
905
+ $ids1[] = $r->vtr_id;
906
+ }
907
+
908
+ $ids1 = implode(',', $ids1);
909
+
910
+ $sql12 = "DELETE FROM `ahc_recent_visitors`" . ((!empty($ids1)) ? " WHERE vtr_id NOT IN (" . $ids1 . ")" : "");
911
+
912
+
913
+
914
+ $sql21 = "SELECT kwd_id FROM `ahc_keywords` ORDER BY kwd_id LIMIT %d";
915
+
916
+ $result2 = $wpdb->get_results($wpdb->prepare($sql21, AHCFREE_RECENT_KEYWORDS_LIMIT), OBJECT);
917
+
918
+ if ($result2 !== false) {
919
+
920
+ $ids2 = array();
921
+
922
+ foreach ($result2 as $r) {
923
+
924
+ $ids2[] = $r->kwd_id;
925
+ }
926
+
927
+ $ids2 = implode(',', $ids2);
928
+
929
+ $sql22 = "DELETE FROM `ahc_keywords`" . ((!empty($ids2)) ? " WHERE kwd_id NOT IN (" . $ids2 . ")" : "");
930
+
931
+
932
+
933
+ if ($wpdb->query($sql12) !== false) {
934
+
935
+ return ($wpdb->query($sql22) !== false);
936
  }
937
+ }
938
  }
939
+
940
+ return false;
941
+ }
942
+
943
  //--------------------------------------------
944
+
945
+ /**
946
+
947
+ * Update traffic by title table
948
+
949
+ *
950
+
951
+ * @uses wpdb::prepare()
952
+
953
+ * @uses wpdb::get_results()
954
+
955
+ * @uses wpdb::query()
956
+
957
+ *
958
+
959
+ * @param integer $til_page_id
960
+
961
+ * @param string $til_page_title
962
+
963
+ * @return boolean
964
+
965
+ */
966
+ protected function updateTitleTraffic($til_page_id, $til_page_title) {
967
+
968
+ global $wpdb;
969
+
970
+ $sql = "SELECT til_id FROM `ahc_title_traffic` where til_page_id = %s";
971
+
972
+ $result = $wpdb->get_results($wpdb->prepare($sql, $til_page_id), OBJECT);
973
+
974
+ if ($result !== false) {
975
+
976
+ if (!empty($result)) {
977
+
978
+ $sql2 = "UPDATE `ahc_title_traffic`
979
+
980
  SET til_hits = til_hits + 1, til_page_title = %s
981
+
982
  WHERE til_id = %d";
983
+
984
+ return ($wpdb->query($wpdb->prepare($sql2, $til_page_title, $result[0]->til_id)) !== false);
985
+ } else {
986
+
987
+ $sql2 = "INSERT INTO `ahc_title_traffic` (til_page_id, til_page_title, til_hits)
988
+
989
  VALUES(%s, %s, 1)";
990
+
991
+ return ($wpdb->query($wpdb->prepare($sql2, $til_page_id, $til_page_title)) !== false);
992
+ }
993
+ } else {
994
+
995
+ return false;
996
  }
997
+ }
998
+
999
  //--------------------------------------------
1000
+
1001
+ /**
1002
+
1003
+ * Update visitor's & visits' times table
1004
+
1005
+ *
1006
+
1007
+ * @uses wpdb::prepare()
1008
+
1009
+ * @uses wpdb::query()
1010
+
1011
+ *
1012
+
1013
+ * @param integer $visitors Optional
1014
+
1015
+ * @param integer $visits Optional
1016
+
1017
+ * @return boolean
1018
+
1019
+ */
1020
+ protected function updateVisitsTime($visitors = 0, $visits = 0) {
1021
+
1022
+ global $wpdb;
1023
+ $time = date('H:i:s');
1024
+ $sql = "UPDATE `ahc_visits_time` SET vtm_visitors = vtm_visitors + %d, vtm_visits = vtm_visits + %d
1025
+
1026
+ WHERE TIME(vtm_time_from) <= '$time' AND TIME(vtm_time_to) >= '$time'";
1027
+ $query = $wpdb->prepare($sql, $visitors, $visits);
1028
+ $result = ($wpdb->query($query) !== false);
1029
+
1030
+ $sql = "UPDATE `ahc_visits_time` SET vtm_visitors = 1
1031
+
1032
+ WHERE vtm_visitors = 0 AND TIME(vtm_time_from) <= '$time' AND TIME(vtm_time_to) >= '$time'";
1033
+ $query = $wpdb->query($sql);
1034
+
1035
+ $sql = "UPDATE `ahc_visits_time` SET vtm_visits = 1
1036
+
1037
+ WHERE vtm_visits = 0 AND TIME(vtm_time_from) <= '$time' AND TIME(vtm_time_to) >= '$time'";
1038
+ $query = $wpdb->query($sql);
1039
+
1040
+ return $result;
1041
+ }
1042
+
1043
  //--------------------------------------------
1044
+
1045
+ /**
1046
+
1047
+ * Record (insert) the visit
1048
+
1049
+ *
1050
+
1051
+ * @uses wpdb::prepare()
1052
+
1053
+ * @uses wpdb::query()
1054
+
1055
+ *
1056
+
1057
+ * @return boolean
1058
+
1059
+ */
1060
+ protected function recordThisHits() {
1061
+
1062
+ global $wpdb;
1063
+
1064
+ $sql = "INSERT INTO `ahc_hits`
1065
+
1066
+ (`hit_ip_address`, `hit_user_agent`, `hit_request_uri`, `hit_page_id`, `hit_page_title`, `ctr_id`, `hit_referer`, `hit_referer_site`,
1067
+
1068
  `srh_id`, `hit_search_words`, `bsr_id`, `hit_date`, `hit_time`)
1069
+
1070
+ VALUES (%s, %s, %s, %s, %s, %d, %s, %s, %d, %s, %d, %s, %s)";
1071
+
1072
+ $result = $wpdb->query($wpdb->prepare($sql, $this->ipAddress, $this->userAgent, $this->requestUri, $this->pageId, $this->pageTitle, $this->countryId, $this->referer, $this->refererSite, $this->searchEngine, $this->keyWords, $this->browser, date("Y-m-d"), date("H:i:s") ));
1073
+
1074
+ return ($result !== false);
1075
+ }
1076
+
1077
  //--------------------------------------------
1078
  }
1079
+
1080
+ ?>
ahc_about.php ADDED
File without changes
ahc_help.php ADDED
File without changes
ahc_settings.php ADDED
@@ -0,0 +1,5 @@
 
0
  i{
1
  }
 
2
  if (ahcfree_savesettings()) {
 
3
  <h1><img width="40px" src="<?php echo plugins_url('/images/logo.png', AHCFREE_PLUGIN_MAIN_FILE) ?>">&nbsp;Visitor Traffic Real Time Statistics <a title="change settings" href="admin.php?page=ahc_hits_counter_settings"><img src="<?php echo plugins_url('/images/settings.jpg', AHCFREE_PLUGIN_MAIN_FILE) ?>" /></a></h1><br />
4
  <div class="panel">
5
  <h2 style="height:35px !important; font-size:13px !important">Settings</h2>
6
  <option value="<?php echo $value; ?>" <?php echo ( $value == $custom_timezone_offset ) ? 'selected' : ''; ?>><?php echo $value; ?></option>
7
  global $wp_roles;
8
  if ( !isset( $wp_roles ) ) $wp_roles = new WP_Roles();
9
  $available_roles_names = $wp_roles->get_names();//we get all roles names
10
  $available_roles_capable = array();
11
  foreach ($available_roles_names as $role_key => $role_name) { //we iterate all the names
12
  $role_object = get_role( $role_key );//we get the Role Object
13
  $array_of_capabilities = $role_object->capabilities;//we get the array of capabilities for this role
14
  if($array_of_capabilities['update_plugins'] == 1 || $array_of_capabilities['manage_links'] == 1 || $array_of_capabilities['manage_sites'] == 1 ){ //we check if the upload_files capability is present, and if its present check if its 0 (FALSE in Php)
15
  $available_roles_capable[$role_key] = $role_name; //we populate the array of capable roles
16
  }
17
  }
18
 
19
  select: \'#ahcUserRoles\'
 
 
1
+
2
  i{
3
  }
4
+ if (!empty($_POST['save'])) {
5
  if (ahcfree_savesettings()) {
6
+ }
7
  <h1><img width="40px" src="<?php echo plugins_url('/images/logo.png', AHCFREE_PLUGIN_MAIN_FILE) ?>">&nbsp;Visitor Traffic Real Time Statistics <a title="change settings" href="admin.php?page=ahc_hits_counter_settings"><img src="<?php echo plugins_url('/images/settings.jpg', AHCFREE_PLUGIN_MAIN_FILE) ?>" /></a></h1><br />
8
  <div class="panel">
9
  <h2 style="height:35px !important; font-size:13px !important">Settings</h2>
10
  <option value="<?php echo $value; ?>" <?php echo ( $value == $custom_timezone_offset ) ? 'selected' : ''; ?>><?php echo $value; ?></option>
11
  global $wp_roles;
12
  if ( !isset( $wp_roles ) ) $wp_roles = new WP_Roles();
13
  $available_roles_names = $wp_roles->get_names();//we get all roles names
14
  $available_roles_capable = array();
15
  foreach ($available_roles_names as $role_key => $role_name) { //we iterate all the names
16
  $role_object = get_role( $role_key );//we get the Role Object
17
  $array_of_capabilities = $role_object->capabilities;//we get the array of capabilities for this role
18
  if($array_of_capabilities['update_plugins'] == 1 || $array_of_capabilities['manage_links'] == 1 || $array_of_capabilities['manage_sites'] == 1 ){ //we check if the upload_files capability is present, and if its present check if its 0 (FALSE in Php)
19
  $available_roles_capable[$role_key] = $role_name; //we populate the array of capable roles
20
  }
21
  }
22
 
23
  select: \'#ahcUserRoles\'
24
+ </div>
25
+ </form>
css/ar_css.css CHANGED
@@ -2,7 +2,7 @@
2
  html {height: 100%}
3
  body {height: 100%; margin:0; padding:0; overflow-x:hidden; font: 10px verdana;}
4
 
5
- .ahc_main_container{
6
  direction: rtl; /* ## */
7
  padding: 60px 20px;
8
  }
2
  html {height: 100%}
3
  body {height: 100%; margin:0; padding:0; overflow-x:hidden; font: 10px verdana;}
4
 
5
+ .ahcfree_main_container{
6
  direction: rtl; /* ## */
7
  padding: 60px 20px;
8
  }
css/en_newcss.css DELETED
@@ -1,115 +0,0 @@
1
- body {font: 10px verdana; background:#F1F1F1 !important}
2
-
3
- .legendsContainer{min-height: 410px; border: solid 1px #CCCCCC; border-radius: 5px; width:200px !important; padding: 10px; background-color: #F1F1F1;}
4
- .legendsContainer div.legend{float: left;display:inline; height:auto; width:180px !important; margin: 0 10px 10px 0;}
5
- div.legend span{font-size: 12px; line-height: 0.9;}
6
- div.legend span.color{display: block; float: left; width: 15px; height: 95%; margin-right: 8px;}
7
- div.legend span.name{margin-right: 5px;}
8
- div.legend span.value{color: #D34E4E;}
9
- .panel{
10
- margin-left:20px
11
- }
12
-
13
- .disabled_panel{
14
- background:#666;
15
- position:absolute
16
-
17
- }
18
-
19
- .ahc_main_container{
20
- direction: ltr; /* ## */
21
- font-family:Verdana, Geneva, sans-serif; font-size:8px !important;
22
- width:98%;
23
- }
24
- .ahc_main_container h1{
25
- font-size:20px;
26
- font-weight:normal;
27
- color:#657f97;
28
-
29
- }
30
- .hitsLogo{
31
- background:url(../images/hitslogo.png) left no-repeat;
32
- height:55px;
33
- width:55px;
34
- display:inline;
35
- float:left;
36
- }
37
- .rightPanelsContainer{float: left; /* ## */ margin: 0; padding: 0;}
38
- .leftPanelsContainer{float: right; /* ## */ margin: 0; padding: 0;}
39
- .cleaner{clear: both;}
40
- .panel, .panelcollapsed{
41
- background: #23282D;
42
- border:#23282D solid 1px;
43
- margin: 10px 0px;
44
- -moz-border-radius: 4px;
45
- -webkit-border-radius: 4px;
46
-
47
- }
48
- .panel h2, .panelcollapsed h2{
49
- font-size: 12px !important;
50
- font-weight: normal !important;
51
- margin: 0px !important;
52
-
53
- background-color:#666 !important;
54
- padding:5px !important;
55
-
56
- color: white !important;
57
- font-weight:bold !important;
58
- background-color:#23282D;
59
-
60
- -moz-border-radius: 3px !important;
61
- -webkit-border-radius: 3px !important;
62
- height:20px !important;
63
- }
64
- .panelcollapsed h2{
65
- background: #FFF url(../images/arrow_down.png) no-repeat 99% 50% !important;; /* ## */
66
- border-color: #CCC !important;;
67
- }
68
- .panelcontent{
69
- padding: 10px;
70
- background: #FFF;
71
- min-height:400px;
72
- }
73
- .panelcollapsed .panelcontent {display: none;}
74
- .panelcontent th{font-size: 12px; color: #657f97; font-weight: 0; padding: 5px; text-align: left; border-bottom:#CCC solid 1px; }
75
- .panelcontent td, .panelcontent td.values{text-align: left; color:#000; font-size: 12px; font-weight: 0; padding: 5px; text-align: left; border-bottom:#EFEFEF solid 1px}
76
- .panelcontent tr:hover{
77
- background:#F5F5F5
78
- }
79
-
80
- .fineFont{font-size: 10px !important}
81
-
82
- .lastVisitorsDetails{border-bottom: solid 1px #dad6ca; direction: ltr; padding: 5px;}
83
- .lastVisitorsDetails span{margin-right: 3px;}
84
- .lastVisitorsDetails img{vertical-align: middle;}
85
- .ipAddress{float: left; font-size: 14px; color: #3B9EF9; margin-bottom: 10px; margin-bottom: 10px;}
86
- .referingSite{color: #3B9EF9; margin-left: 5px; font-size: 12px;}
87
- .visitDateTime{float: right; color: #3B9EF9; font-size: 12px;}
88
-
89
- .lastSearchKeyWords, .visitorMarker{border-bottom: solid 1px #dad6ca; direction: ltr; padding: 5px;}
90
- .lastSearchKeyWords span, .countryMarker span{margin-right: 3px;}
91
- .lastSearchKeyWords img{vertical-align: middle;}
92
- .countryMarker{direction: ltr; padding: 5px;}
93
- .searchKeyWords{font-size: 14px;}
94
-
95
- .languageChanger{direction: rtl; /* ## */ font-size: 18px;}
96
-
97
- .countryMarker span.countryName, .visitorMarker span.ipAddress{margin-left: 5px;}
98
-
99
- .visitorMarker{border-bottom: dashed 1px #dad6ca;}
100
- .countryMarker span.countryName{font-size: 12px;}
101
- .countryMarker img{vertical-align: middle;}
102
- .visitorMarker span.ipAddress{font-size: 12px;}
103
- .visitorMarker span{float: left;}
104
-
105
- /* visitors graph begin */
106
- div.visitorsGraphContainer{float: left; width: 70%} /* ### */
107
- div.visitorsGraphContainer div.visitorsGraph{float: left; background-color: #82CE69; border-radius: 2px;}
108
- div.visitorsPercent{float: left; width: 25%; margin-left: 5px;} /* ### */
109
- /* visitors graph end */
110
-
111
- h2{
112
- text-align:left !important;
113
- font-size:14px !important;
114
- height:30px !important;
115
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
css/eng_css.css ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {background:#F1F1F1 !important}
2
+
3
+
4
+ .show-swal2{
5
+ width:700px !important;
6
+ height:500px !important;
7
+ }
8
+
9
+ .box_widget{
10
+ height:130px;
11
+ font-family:'Open Sans', sans-serif;
12
+ color:#FFF;
13
+ font-size:40px;
14
+ text-align:right;
15
+ padding-right:10px;
16
+ padding-top:10px;
17
+
18
+ }
19
+ .smallinputs{
20
+ width:40px !important;
21
+ background:#333
22
+ }
23
+ .txt
24
+ {
25
+ font-size:20px;
26
+ }
27
+
28
+
29
+ #ahcfree_currenttime{
30
+ color:gray;
31
+ font-size:20px !important;
32
+ float:right !important;
33
+ vertical-align:middle
34
+ }
35
+
36
+ .blueBox{
37
+ background:url("../images/visits.png") no-repeat;
38
+ background-position:bottom left;
39
+ background-color:#578ebe;
40
+ }
41
+
42
+ .redBox{
43
+ background:url("../images/visitors.png") no-repeat;
44
+ background-position:bottom left;
45
+ background-color:#e35b5a;
46
+
47
+ }
48
+
49
+ .greenBox{
50
+ background:url("../images/online.png") no-repeat;
51
+ background-position:bottom left;
52
+ background-color:#44b6ae;
53
+ }
54
+
55
+ .movBox{
56
+ background:url("../images/searchengin.png") no-repeat;
57
+ background-position:bottom left;
58
+ background-color:#8775a7;
59
+ }
60
+
61
+
62
+ .legendsContainer{ border: solid 1px #CCCCCC; border-radius: 5px; width:auto !important; height:auto; padding: 10px; background-color: #F1F1F1;}
63
+ .legendsContainer div.legend{float: left;display:inline; height: 15px; width:180px !important; margin: 0 10px 10px 0;}
64
+ div.legend span{font-size: 12px; line-height: 0.9;}
65
+ div.legend span.color{display: block; float: left; width: 15px; height: 95%; margin-right: 8px;}
66
+ div.legend span.name{margin-right: 5px;}
67
+ div.legend span.value{color: #D34E4E;}
68
+
69
+ .panel{
70
+ margin-left:20px;
71
+ font-size:15px;
72
+ }
73
+
74
+ .disabled_panel{
75
+ background:#666;
76
+ position:absolute
77
+
78
+ }
79
+
80
+ .ahcfree_main_container{
81
+ direction: ltr; /* ## */
82
+ font-family:Verdana, Geneva, sans-serif; font-size:8px !important;
83
+ width:98%;
84
+ }
85
+ .ahcfree_main_container h1{
86
+ font-size:20px;
87
+ font-weight:normal;
88
+ color:#657f97;
89
+
90
+ }
91
+ .hitsLogo{
92
+ background:url(../images/hitslogo.png) left no-repeat;
93
+ height:55px;
94
+ width:55px;
95
+ display:inline;
96
+ float:left;
97
+ }
98
+ .rightPanelsContainer{float: left; /* ## */ margin: 0; padding: 0;}
99
+ .leftPanelsContainer{float: right; /* ## */ margin: 0; padding: 0;}
100
+ .cleaner{clear: both;}
101
+ .panel, .panelcollapsed{
102
+ background: #eee;
103
+ border:#dfdfdf solid 1px;
104
+ margin: 10px 0px;
105
+ padding: 0px 0px 5px;
106
+ -moz-border-radius: 4px;
107
+ -webkit-border-radius: 4px;
108
+
109
+ }
110
+ .panel h2, .panelcollapsed h2{
111
+ font-size: 12px !important;
112
+ font-weight: normal !important;
113
+ margin: 0px !important;
114
+ padding: 4px !important;
115
+ background: url(../images/headerbg.png) repeat-x !important; /* ## */
116
+ border-bottom:#dfdfdf solid 1px !important;;
117
+ -moz-border-radius: 3px !important;
118
+ -webkit-border-radius: 3px !important;
119
+ height:23px !important;
120
+ background-color:#FFF !important;
121
+ padding-top:10px !important;
122
+ padding-left:7px !important;
123
+ color: #657f97 !important;
124
+ font-weight:bold !important;
125
+ }
126
+ .panelcollapsed h2{
127
+ background: #FFF url(../images/arrow_down.png) no-repeat 99% 50% !important;; /* ## */
128
+ border-color: #CCC !important;;
129
+ }
130
+ .panelcontent{
131
+ padding: 10px;
132
+ background: #FFF;
133
+
134
+ }
135
+ .panelcollapsed .panelcontent {display: none;}
136
+ .panelcontent th{font-size: 12px; color: #657f97; font-weight: 0; padding: 5px; text-align: left; border-bottom:#CCC solid 1px; }
137
+ .panelcontent td, .panelcontent td.values{text-align: left; font-size:14px; font-weight: 0; padding: 5px; text-align: left; border-bottom:#EFEFEF solid 1px}
138
+ .panelcontent tr:hover{
139
+ background:#F5F5F5
140
+ }
141
+
142
+ .fineFont{font-size: 10px !important}
143
+
144
+ .lastVisitorsDetails{border-bottom: solid 1px #dad6ca; direction: ltr; padding: 5px;}
145
+ .lastVisitorsDetails span{margin-right: 3px;}
146
+ .lastVisitorsDetails img{vertical-align: middle;}
147
+ .ipAddress{float: left; font-size: 14px; color: #3B9EF9; margin-bottom: 10px; margin-bottom: 10px; width:150px;}
148
+ .referingSite{color: #3B9EF9; margin-left: 5px; font-size: 12px;}
149
+ .visitDateTime{float: right; color: #3B9EF9; font-size: 12px;}
150
+
151
+ .lastSearchKeyWords, .visitorMarker{border-bottom: solid 1px #dad6ca; direction: ltr; padding: 5px;}
152
+ .lastSearchKeyWords span, .countryMarker span{margin-right: 3px;}
153
+ .lastSearchKeyWords img{vertical-align: middle;}
154
+ .countryMarker{direction: ltr; padding: 5px;}
155
+ .searchKeyWords{font-size: 14px;}
156
+
157
+ .languageChanger{direction: rtl; /* ## */ font-size: 18px;}
158
+
159
+ .countryMarker span.countryName, .visitorMarker span.ipAddress{margin-left: 5px;}
160
+
161
+ .visitorMarker{border-bottom: dashed 1px #dad6ca;}
162
+ .countryMarker span.countryName{font-size: 12px;}
163
+ .countryMarker img{vertical-align: middle;}
164
+ .visitorMarker span.ipAddress{font-size: 12px;}
165
+ .visitorMarker span{float: left;}
166
+
167
+ /* visitors graph begin */
168
+ div.visitorsGraphContainer{float: left; width: 70%} /* ### */
169
+ div.visitorsGraphContainer div.visitorsGraph{float: left; background-color:#9F6; border-radius: 2px;}
170
+ div.visitorsGraphContainer div.visitorsGraph2{float: left; background-color:#393; border-radius: 2px;}
171
+ div.visitorsGraphContainer div.visitorsGraph3{float: left; background-color:#060; border-radius: 2px;}
172
+ div.visitorsPercent{float: left; width: 25%; margin-left: 5px;} /* ### */
173
+ /* visitors graph end */
174
+
175
+ h2{
176
+ text-align:left !important;
177
+ font-size:14px !important;
178
+ height:30px !important;
179
+ }
180
+
181
+
182
+ .recentv tr td{
183
+ font-size:12px !important;
184
+ }
185
+
186
+ /*************************************/
187
+
188
+ .increase_counter{
189
+ background-image:url('../images/increase.png');
190
+ }
191
+
192
+ .decrease_counter{
193
+ background-image:url('../images/decrease.png');
194
+ }
195
+ span#up-down {
196
+ display: inline-block;
197
+ width: 50px;
198
+ height: 30px;
199
+ background-repeat: no-repeat;
200
+ background-position: center center;
201
+ }
202
+
203
+ .hits_duration_select{
204
+ padding-top: 10px;
205
+ padding-left: 10px;
206
+ }
207
+ #visitors_graph_stats{
208
+ position:relative;
209
+ }
210
+ .panelcontent.loader:after {
211
+ content: "";
212
+ background-image: url(../images/Spinner-1s-200px.svg);
213
+ background-repeat: no-repeat;
214
+ width: 100%;
215
+ height: 100%;
216
+ position: absolute;
217
+ left: 0;
218
+ top: 0;
219
+ background-position: center;
220
+ z-index: 9999;
221
+ background-color: rgba(255,255,255,0.6);
222
+ }
css/{en_css.css → engl_css.css} RENAMED
@@ -1,13 +1,71 @@
1
- body {font: 10px verdana; background:#F1F1F1 !important}
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- .legendsContainer{min-height: 410px; border: solid 1px #CCCCCC; border-radius: 5px; width:200px !important; padding: 10px; background-color: #F1F1F1;}
4
- .legendsContainer div.legend{float: left;display:inline; height:auto; width:180px !important; margin: 0 10px 10px 0;}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  div.legend span{font-size: 12px; line-height: 0.9;}
6
  div.legend span.color{display: block; float: left; width: 15px; height: 95%; margin-right: 8px;}
7
  div.legend span.name{margin-right: 5px;}
8
  div.legend span.value{color: #D34E4E;}
 
9
  .panel{
10
- margin-left:20px
 
11
  }
12
 
13
  .disabled_panel{
@@ -16,12 +74,12 @@ position:absolute
16
 
17
  }
18
 
19
- .ahc_main_container{
20
  direction: ltr; /* ## */
21
  font-family:Verdana, Geneva, sans-serif; font-size:8px !important;
22
  width:98%;
23
  }
24
- .ahc_main_container h1{
25
  font-size:20px;
26
  font-weight:normal;
27
  color:#657f97;
@@ -50,18 +108,17 @@ float:left;
50
  font-size: 12px !important;
51
  font-weight: normal !important;
52
  margin: 0px !important;
53
-
54
- background-color:#666 !important;
 
 
 
 
 
55
  padding-top:10px !important;
56
  padding-left:7px !important;
57
  color: #657f97 !important;
58
  font-weight:bold !important;
59
- padding: 4px !important;
60
- background: url(../images/myheaderbg.png) repeat-x !important; /* ## */
61
-
62
- -moz-border-radius: 3px !important;
63
- -webkit-border-radius: 3px !important;
64
- height:20px !important;
65
  }
66
  .panelcollapsed h2{
67
  background: #FFF url(../images/arrow_down.png) no-repeat 99% 50% !important;; /* ## */
@@ -70,11 +127,11 @@ float:left;
70
  .panelcontent{
71
  padding: 10px;
72
  background: #FFF;
73
- min-height:400px;
74
  }
75
  .panelcollapsed .panelcontent {display: none;}
76
  .panelcontent th{font-size: 12px; color: #657f97; font-weight: 0; padding: 5px; text-align: left; border-bottom:#CCC solid 1px; }
77
- .panelcontent td, .panelcontent td.values{text-align: left; color:#000; font-size: 12px; font-weight: 0; padding: 5px; text-align: left; border-bottom:#EFEFEF solid 1px}
78
  .panelcontent tr:hover{
79
  background:#F5F5F5
80
  }
@@ -84,7 +141,7 @@ background:#F5F5F5
84
  .lastVisitorsDetails{border-bottom: solid 1px #dad6ca; direction: ltr; padding: 5px;}
85
  .lastVisitorsDetails span{margin-right: 3px;}
86
  .lastVisitorsDetails img{vertical-align: middle;}
87
- .ipAddress{float: left; font-size: 14px; color: #3B9EF9; margin-bottom: 10px; margin-bottom: 10px;}
88
  .referingSite{color: #3B9EF9; margin-left: 5px; font-size: 12px;}
89
  .visitDateTime{float: right; color: #3B9EF9; font-size: 12px;}
90
 
@@ -106,7 +163,9 @@ background:#F5F5F5
106
 
107
  /* visitors graph begin */
108
  div.visitorsGraphContainer{float: left; width: 70%} /* ### */
109
- div.visitorsGraphContainer div.visitorsGraph{float: left; background-color: #82CE69; border-radius: 2px;}
 
 
110
  div.visitorsPercent{float: left; width: 25%; margin-left: 5px;} /* ### */
111
  /* visitors graph end */
112
 
@@ -115,3 +174,46 @@ h2{
115
  font-size:14px !important;
116
  height:30px !important;
117
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .show-swal2{
2
+ width:700px !important;
3
+ height:500px !important;
4
+ }
5
+
6
+ .box_widget{
7
+ height:130px;
8
+ font-family:'Open Sans', sans-serif;
9
+ color:#FFF;
10
+ font-size:40px;
11
+ text-align:right;
12
+ padding-right:10px;
13
+ padding-top:10px;
14
 
15
+ }
16
+ .smallinputs{
17
+ width:40px !important;
18
+ background:#333
19
+ }
20
+ .txt
21
+ {
22
+ font-size:20px;
23
+ }
24
+
25
+
26
+ #ahcfree_currenttime{
27
+ color:gray;
28
+ font-size:15px !important;
29
+ float:right !important;
30
+ vertical-align:middle
31
+ }
32
+
33
+ .blueBox{
34
+ background:url("../images/visits.png") no-repeat;
35
+ background-position:bottom left;
36
+ background-color:#578ebe;
37
+ }
38
+
39
+ .redBox{
40
+ background:url("../images/visitors.png") no-repeat;
41
+ background-position:bottom left;
42
+ background-color:#e35b5a;
43
+
44
+ }
45
+
46
+ .greenBox{
47
+ background:url("../images/online.png") no-repeat;
48
+ background-position:bottom left;
49
+ background-color:#44b6ae;
50
+ }
51
+
52
+ .movBox{
53
+ background:url("../images/searchengin.png") no-repeat;
54
+ background-position:bottom left;
55
+ background-color:#8775a7;
56
+ }
57
+
58
+
59
+ .legendsContainer{ border: solid 1px #CCCCCC; border-radius: 5px; width:auto !important; height:auto; padding: 10px; background-color: #F1F1F1;}
60
+ .legendsContainer div.legend{float: left;display:inline; height: 15px; width:180px !important; margin: 0 10px 10px 0;}
61
  div.legend span{font-size: 12px; line-height: 0.9;}
62
  div.legend span.color{display: block; float: left; width: 15px; height: 95%; margin-right: 8px;}
63
  div.legend span.name{margin-right: 5px;}
64
  div.legend span.value{color: #D34E4E;}
65
+
66
  .panel{
67
+ margin-left:20px;
68
+ font-size:15px;
69
  }
70
 
71
  .disabled_panel{
74
 
75
  }
76
 
77
+ .ahcfree_main_container{
78
  direction: ltr; /* ## */
79
  font-family:Verdana, Geneva, sans-serif; font-size:8px !important;
80
  width:98%;
81
  }
82
+ .ahcfree_main_container h1{
83
  font-size:20px;
84
  font-weight:normal;
85
  color:#657f97;
108
  font-size: 12px !important;
109
  font-weight: normal !important;
110
  margin: 0px !important;
111
+ padding: 4px !important;
112
+ background: url(../images/headerbg.png) repeat-x !important; /* ## */
113
+ border-bottom:#dfdfdf solid 1px !important;;
114
+ -moz-border-radius: 3px !important;
115
+ -webkit-border-radius: 3px !important;
116
+ height:23px !important;
117
+ background-color:#FFF !important;
118
  padding-top:10px !important;
119
  padding-left:7px !important;
120
  color: #657f97 !important;
121
  font-weight:bold !important;
 
 
 
 
 
 
122
  }
123
  .panelcollapsed h2{
124
  background: #FFF url(../images/arrow_down.png) no-repeat 99% 50% !important;; /* ## */
127
  .panelcontent{
128
  padding: 10px;
129
  background: #FFF;
130
+
131
  }
132
  .panelcollapsed .panelcontent {display: none;}
133
  .panelcontent th{font-size: 12px; color: #657f97; font-weight: 0; padding: 5px; text-align: left; border-bottom:#CCC solid 1px; }
134
+ .panelcontent td, .panelcontent td.values{text-align: left; font-size:14px; font-weight: 0; padding: 5px; text-align: left; border-bottom:#EFEFEF solid 1px}
135
  .panelcontent tr:hover{
136
  background:#F5F5F5
137
  }
141
  .lastVisitorsDetails{border-bottom: solid 1px #dad6ca; direction: ltr; padding: 5px;}
142
  .lastVisitorsDetails span{margin-right: 3px;}
143
  .lastVisitorsDetails img{vertical-align: middle;}
144
+ .ipAddress{float: left; font-size: 14px; color: #3B9EF9; margin-bottom: 10px; margin-bottom: 10px; width:150px;}
145
  .referingSite{color: #3B9EF9; margin-left: 5px; font-size: 12px;}
146
  .visitDateTime{float: right; color: #3B9EF9; font-size: 12px;}
147
 
163
 
164
  /* visitors graph begin */
165
  div.visitorsGraphContainer{float: left; width: 70%} /* ### */
166
+ div.visitorsGraphContainer div.visitorsGraph{float: left; background-color:#9F6; border-radius: 2px;}
167
+ div.visitorsGraphContainer div.visitorsGraph2{float: left; background-color:#393; border-radius: 2px;}
168
+ div.visitorsGraphContainer div.visitorsGraph3{float: left; background-color:#060; border-radius: 2px;}
169
  div.visitorsPercent{float: left; width: 25%; margin-left: 5px;} /* ### */
170
  /* visitors graph end */
171
 
174
  font-size:14px !important;
175
  height:30px !important;
176
  }
177
+
178
+
179
+ .recentv tr td{
180
+ font-size:12px !important;
181
+ }
182
+
183
+ /*************************************/
184
+
185
+ .increase_counter{
186
+ background-image:url('../images/increase.png');
187
+ }
188
+
189
+ .decrease_counter{
190
+ background-image:url('../images/decrease.png');
191
+ }
192
+ span#up-down {
193
+ display: inline-block;
194
+ width: 50px;
195
+ height: 30px;
196
+ background-repeat: no-repeat;
197
+ background-position: center center;
198
+ }
199
+
200
+ .hits_duration_select{
201
+ padding-top: 10px;
202
+ padding-left: 10px;
203
+ }
204
+ #visitors_graph_stats{
205
+ position:relative;
206
+ }
207
+ .panelcontent.loader:after {
208
+ content: "";
209
+ background-image: url(../images/Spinner-1s-200px.svg);
210
+ background-repeat: no-repeat;
211
+ width: 100%;
212
+ height: 100%;
213
+ position: absolute;
214
+ left: 0;
215
+ top: 0;
216
+ background-position: center;
217
+ z-index: 9999;
218
+ background-color: rgba(255,255,255,0.6);
219
+ }
css/jquery.jqplot.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .jqplot-target{position:relative;color:#666;font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;font-size:1em}.jqplot-axis{font-size:.75em}.jqplot-xaxis{margin-top:10px}.jqplot-x2axis{margin-bottom:10px}.jqplot-yaxis{margin-right:10px}.jqplot-y2axis,.jqplot-y3axis,.jqplot-y4axis,.jqplot-y5axis,.jqplot-y6axis,.jqplot-y7axis,.jqplot-y8axis,.jqplot-y9axis,.jqplot-yMidAxis{margin-left:10px;margin-right:10px}.jqplot-axis-tick,.jqplot-xaxis-tick,.jqplot-yaxis-tick,.jqplot-x2axis-tick,.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick,.jqplot-yMidAxis-tick{position:absolute;white-space:pre}.jqplot-xaxis-tick{top:0;left:15px;vertical-align:top}.jqplot-x2axis-tick{bottom:0;left:15px;vertical-align:bottom}.jqplot-yaxis-tick{right:0;top:15px;text-align:right}.jqplot-yaxis-tick.jqplot-breakTick{right:-20px;margin-right:0;padding:1px 5px 1px 5px;z-index:2;font-size:1.5em}.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick{left:0;top:15px;text-align:left}.jqplot-yMidAxis-tick{text-align:center;white-space:nowrap}.jqplot-xaxis-label{margin-top:10px;font-size:11pt;position:absolute}.jqplot-x2axis-label{margin-bottom:10px;font-size:11pt;position:absolute}.jqplot-yaxis-label{margin-right:10px;font-size:11pt;position:absolute}.jqplot-yMidAxis-label{font-size:11pt;position:absolute}.jqplot-y2axis-label,.jqplot-y3axis-label,.jqplot-y4axis-label,.jqplot-y5axis-label,.jqplot-y6axis-label,.jqplot-y7axis-label,.jqplot-y8axis-label,.jqplot-y9axis-label{font-size:11pt;margin-left:10px;position:absolute}.jqplot-meterGauge-tick{font-size:.75em;color:#999}.jqplot-meterGauge-label{font-size:1em;color:#999}table.jqplot-table-legend{margin-top:12px;margin-bottom:12px;margin-left:12px;margin-right:12px}table.jqplot-table-legend,table.jqplot-cursor-legend{background-color:rgba(255,255,255,0.6);border:1px solid #ccc;position:absolute;font-size:.75em}td.jqplot-table-legend{vertical-align:middle}td.jqplot-seriesToggle:hover,td.jqplot-seriesToggle:active{cursor:pointer}.jqplot-table-legend .jqplot-series-hidden{text-decoration:line-through}div.jqplot-table-legend-swatch-outline{border:1px solid #ccc;padding:1px}div.jqplot-table-legend-swatch{width:0;height:0;border-top-width:5px;border-bottom-width:5px;border-left-width:6px;border-right-width:6px;border-top-style:solid;border-bottom-style:solid;border-left-style:solid;border-right-style:solid}.jqplot-title{top:0;left:0;padding-bottom:.5em;font-size:1.2em}table.jqplot-cursor-tooltip{border:1px solid #ccc;font-size:.75em}.jqplot-cursor-tooltip{border:1px solid #ccc;font-size:.75em;white-space:nowrap;background:rgba(208,208,208,0.5);padding:1px}.jqplot-highlighter-tooltip,.jqplot-canvasOverlay-tooltip{border:1px solid #ccc;font-size:.75em;white-space:nowrap;background:rgba(208,208,208,0.5);padding:1px}.jqplot-point-label{font-size:.75em;z-index:2}td.jqplot-cursor-legend-swatch{vertical-align:middle;text-align:center}div.jqplot-cursor-legend-swatch{width:1.2em;height:.7em}.jqplot-error{text-align:center}.jqplot-error-message{position:relative;top:46%;display:inline-block}div.jqplot-bubble-label{font-size:.8em;padding-left:2px;padding-right:2px;color:rgb(20%,20%,20%)}div.jqplot-bubble-label.jqplot-bubble-label-highlight{background:rgba(90%,90%,90%,0.7)}div.jqplot-noData-container{text-align:center;background-color:rgba(96%,96%,96%,0.3)}
css/sweetalerts.css ADDED
@@ -0,0 +1 @@
 
1
+ .swal-noscroll{height:auto !important}.swal2-modal,.swal2-overlay{position:fixed;display:none}.swal2-overlay{background-color:rgba(0,0,0,.4);left:0;right:0;top:0;bottom:0;z-index:1000}.swal2-modal{background-color:#fff;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;border-radius:5px;box-sizing:border-box;text-align:center;left:50%;top:50%;margin-top:-200px;max-height:90%;overflow-x:hidden;overflow-y:auto;z-index:2000}.swal2-modal:focus{outline:0}.swal2-modal.loading{overflow-y:hidden}.swal2-modal h2{color:#575757;font-size:30px;text-align:center;font-weight:600;text-transform:none;position:relative;margin:0;padding:0;line-height:60px;display:block}.swal2-modal .swal2-spacer{height:10px;color:transparent;border:0}.swal2-modal button.styled{color:#fff;border:0;box-shadow:none;font-size:17px;font-weight:500;border-radius:3px;padding:10px 32px;margin:0 5px;cursor:pointer}.swal2-content,.swal2-icon{padding:0;position:relative}.swal2-modal button.styled:not(.loading)[disabled]{opacity:.4;cursor:no-drop}.swal2-modal button.styled.loading{box-sizing:border-box;border:4px solid transparent;width:40px;height:40px;padding:0;margin:-2px 30px;vertical-align:top;background-color:transparent!important;color:transparent;cursor:default;border-radius:100%;-webkit-animation:rotate-loading 1.5s linear 0s infinite normal;animation:rotate-loading 1.5s linear 0s infinite normal}.swal2-modal button:not(.styled).loading:after{display:inline-block;content:"";margin-left:5px;vertical-align:-1px;height:6px;width:6px;border:3px solid #999;border-right-color:transparent;border-radius:50%;-webkit-animation:rotate-loading 1.5s linear 0s infinite normal;animation:rotate-loading 1.5s linear 0s infinite normal}.swal2-checkbox input,.swal2-checkbox span,.swal2-radio input,.swal2-radio span{vertical-align:middle}.swal2-modal .swal2-image{margin:20px auto;max-width:100%}.swal2-modal .swal2-close{font-size:36px;line-height:36px;font-family:serif;position:absolute;top:5px;right:13px;cursor:pointer;color:#cfcfcf;-webkit-transition:all .1s ease;transition:all .1s ease}.swal2-modal .swal2-close:hover{color:#d55}.swal2-modal>.swal2-checkbox,.swal2-modal>.swal2-input,.swal2-modal>.swal2-radio,.swal2-modal>.swal2-select,.swal2-modal>.swal2-textarea{display:none}.swal2-content{font-size:18px;text-align:center;font-weight:300;float:none;margin:0;line-height:normal;color:#555}.swal2-icon.swal2-info,.swal2-icon.swal2-question,.swal2-icon.swal2-warning{font-size:60px;line-height:80px;text-align:center}.swal2-icon{width:80px;height:80px;border:4px solid grey;border-radius:50%;margin:20px auto 30px;box-sizing:content-box;cursor:default;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.swal2-icon.swal2-error{border-color:#f27474}.swal2-icon.swal2-error .x-mark{position:relative;display:block}.swal2-icon.swal2-error .line{position:absolute;height:5px;width:47px;background-color:#f27474;display:block;top:37px;border-radius:2px}.swal2-icon.swal2-error .line.left{-webkit-transform:rotate(45deg);transform:rotate(45deg);left:17px}.swal2-icon.swal2-error .line.right{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);right:16px}.swal2-icon.swal2-warning{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;color:#f8bb86;border-color:#f8bb86}.swal2-icon.swal2-info{font-family:"Open Sans",sans-serif;color:#3fc3ee;border-color:#3fc3ee}.swal2-icon.swal2-question{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;color:#c9dae1;border-color:#c9dae1}.swal2-icon.swal2-success{border-color:#a5dc86}.swal2-icon.swal2-success::after,.swal2-icon.swal2-success::before{content:'';position:absolute;width:60px;height:120px;background:#fff}.swal2-icon.swal2-success::before{border-radius:120px 0 0 120px;top:-7px;left:-33px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:60px 60px;transform-origin:60px 60px}.swal2-icon.swal2-success::after{border-radius:0 120px 120px 0;top:-11px;left:30px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:0 60px;transform-origin:0 60px}.swal2-icon.swal2-success .placeholder{width:80px;height:80px;border:4px solid rgba(165,220,134,.2);border-radius:50%;box-sizing:content-box;position:absolute;left:-4px;top:-4px;z-index:2}.swal2-icon.swal2-success .fix{width:7px;height:90px;background-color:#fff;position:absolute;left:28px;top:8px;z-index:1;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.swal2-icon.swal2-success .line{height:5px;background-color:#a5dc86;display:block;border-radius:2px;position:absolute;z-index:2}.swal2-icon.swal2-success .line.tip{width:25px;left:14px;top:46px;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.swal2-icon.swal2-success .line.long{width:47px;right:8px;top:38px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.swal2-checkbox,.swal2-input,.swal2-radio,.swal2-select,.swal2-textarea{margin:20px auto}.swal2-input:not([type=file]),.swal2-textarea{width:100%;box-sizing:border-box;border-radius:3px;border:1px solid #d7d7d7;font-size:18px;box-shadow:inset 0 1px 1px rgba(0,0,0,.06);-webkit-transition:all .3s;transition:all .3s}.swal2-input:not([type=file]).error,.swal2-textarea.error{border-color:#f06e57!important}.swal2-input:not([type=file]):focus,.swal2-textarea:focus{outline:0;box-shadow:0 0 3px #c4e6f5;border:1px solid #b4dbed}.swal2-input:not([type=file]):focus::-moz-placeholder,.swal2-textarea:focus::-moz-placeholder{-webkit-transition:opacity .3s 30ms ease;transition:opacity .3s 30ms ease;opacity:.8}.swal2-input:not([type=file]):focus:-ms-input-placeholder,.swal2-textarea:focus:-ms-input-placeholder{-webkit-transition:opacity .3s 30ms ease;transition:opacity .3s 30ms ease;opacity:.8}.swal2-input:not([type=file]):focus::-webkit-input-placeholder,.swal2-textarea:focus::-webkit-input-placeholder{-webkit-transition:opacity .3s 30ms ease;transition:opacity .3s 30ms ease;opacity:.8}.swal2-input:not([type=file])::-moz-placeholder,.swal2-textarea::-moz-placeholder{color:#bdbdbd}.swal2-input:not([type=file]):-ms-input-placeholder,.swal2-textarea:-ms-input-placeholder{color:#bdbdbd}.swal2-input:not([type=file])::-webkit-input-placeholder,.swal2-textarea::-webkit-input-placeholder{color:#bdbdbd}.swal2-input:not([type=file]){height:43px;padding:0 12px}.swal2-input[type=file]{font-size:20px}.swal2-textarea{height:108px;padding:12px}.swal2-select{color:#555;font-size:inherit;padding:5px 10px;min-width:40%;max-width:100%}.swal2-radio{border:0}.swal2-radio label:not(:first-child){margin-left:20px}.swal2-radio input{margin:0 3px 0 0}.swal2-checkbox{color:#555}.swal2-validationerror{background-color:#f1f1f1;margin:0 -20px;overflow:hidden;padding:10px;color:#797979;font-size:16px;font-weight:300;display:none}.swal2-validationerror::before{content:"!";display:inline-block;width:24px;height:24px;border-radius:50%;background-color:#ea7d7d;color:#fff;line-height:24px;text-align:center;margin-right:10px}@-webkit-keyframes showSweetAlert{0%{-webkit-transform:scale(.7);transform:scale(.7)}45%{-webkit-transform:scale(1.05);transform:scale(1.05)}80%{-webkit-transform:scale(.95);transform:scale(.95)}100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes showSweetAlert{0%{-webkit-transform:scale(.7);transform:scale(.7)}45%{-webkit-transform:scale(1.05);transform:scale(1.05)}80%{-webkit-transform:scale(.95);transform:scale(.95)}100%{-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes hideSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}100%{-webkit-transform:scale(.5);transform:scale(.5);opacity:0}}@keyframes hideSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}100%{-webkit-transform:scale(.5);transform:scale(.5);opacity:0}}.show-swal2{-webkit-animation:showSweetAlert .3s;animation:showSweetAlert .3s}.show-swal2.no-animation{-webkit-animation:none;animation:none}.hide-swal2{-webkit-animation:hideSweetAlert .15s forwards;animation:hideSweetAlert .15s forwards}.hide-swal2.no-animation{-webkit-animation:none;animation:none}@-webkit-keyframes animate-success-tip{0%,54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}100%{width:25px;left:14px;top:45px}}@keyframes animate-success-tip{0%,54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}100%{width:25px;left:14px;top:45px}}@-webkit-keyframes animate-success-long{0%,65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}100%{width:47px;right:8px;top:38px}}@keyframes animate-success-long{0%,65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}100%{width:47px;right:8px;top:38px}}@-webkit-keyframes rotatePlaceholder{0%,5%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}100%,12%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}}@keyframes rotatePlaceholder{0%,5%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}100%,12%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}}.animate-success-tip{-webkit-animation:animate-success-tip .75s;animation:animate-success-tip .75s}.animate-success-long{-webkit-animation:animate-success-long .75s;animation:animate-success-long .75s}.swal2-icon.swal2-success.animate::after{-webkit-animation:rotatePlaceholder 4.25s ease-in;animation:rotatePlaceholder 4.25s ease-in}@-webkit-keyframes animate-error-icon{0%{-webkit-transform:rotateX(100deg);transform:rotateX(100deg);opacity:0}100%{-webkit-transform:rotateX(0);transform:rotateX(0);opacity:1}}@keyframes animate-error-icon{0%{-webkit-transform:rotateX(100deg);transform:rotateX(100deg);opacity:0}100%{-webkit-transform:rotateX(0);transform:rotateX(0);opacity:1}}.animate-error-icon{-webkit-animation:animate-error-icon .5s;animation:animate-error-icon .5s}@-webkit-keyframes animate-x-mark{0%,50%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}80%{-webkit-transform:scale(1.15);transform:scale(1.15);margin-top:-6px}100%{-webkit-transform:scale(1);transform:scale(1);margin-top:0;opacity:1}}@keyframes animate-x-mark{0%,50%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}80%{-webkit-transform:scale(1.15);transform:scale(1.15);margin-top:-6px}100%{-webkit-transform:scale(1);transform:scale(1);margin-top:0;opacity:1}}.animate-x-mark{-webkit-animation:animate-x-mark .5s;animation:animate-x-mark .5s}@-webkit-keyframes pulse-warning{0%{border-color:#f8d486}100%{border-color:#f8bb86}}@keyframes pulse-warning{0%{border-color:#f8d486}100%{border-color:#f8bb86}}.pulse-warning{-webkit-animation:pulse-warning .75s infinite alternate;animation:pulse-warning .75s infinite alternate}@-webkit-keyframes rotate-loading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate-loading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}
database_basics_data.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  $internetCountryCodes = array(
3
  'A1' => 'Anonymous Proxy', 'A2' => 'Satellite Provider', 'O1' => 'Other Country', 'AD' => 'Andorra',
4
  'AE' => 'United Arab Emirates', 'AF' => 'Afghanistan', 'AG' => 'Antigua and Barbuda', 'AI' => 'Anguilla',
@@ -153,7 +154,7 @@ $contriesLatLng = array(
153
  'ZA' => array('-29.0000', '24.0000'), 'ZM' => array('-15.0000', '30.0000'), 'ZR' => array('-4.038333', '21.758664'),
154
  'ZW' => array('-20.0000', '30.0000')
155
  );
156
-
157
  $searchEngines = array(
158
  array('srh_name' => 'Google', 'srh_icon' => 'google.png', 'srh_query_parameter' => 'q', 'srh_identifier' => 'google',
159
  'crawlers' => array(
1
  <?php
2
+
3
  $internetCountryCodes = array(
4
  'A1' => 'Anonymous Proxy', 'A2' => 'Satellite Provider', 'O1' => 'Other Country', 'AD' => 'Andorra',
5
  'AE' => 'United Arab Emirates', 'AF' => 'Afghanistan', 'AG' => 'Antigua and Barbuda', 'AI' => 'Anguilla',
154
  'ZA' => array('-29.0000', '24.0000'), 'ZM' => array('-15.0000', '30.0000'), 'ZR' => array('-4.038333', '21.758664'),
155
  'ZW' => array('-20.0000', '30.0000')
156
  );
157
+
158
  $searchEngines = array(
159
  array('srh_name' => 'Google', 'srh_icon' => 'google.png', 'srh_query_parameter' => 'q', 'srh_identifier' => 'google',
160
  'crawlers' => array(
functions.php CHANGED
@@ -8,157 +8,261 @@
8
  *
9
  * @return void
10
  */
11
-
12
-
 
 
 
 
 
 
13
 
14
-
15
- function ahc_search_engins_count(){
16
- global $wpdb;
17
- $result = $wpdb->get_results("SELECT count(srh_id) as cnt FROM `ahc_searching_visits`", OBJECT);
18
- if($result !== false){
19
- return $result[0]->cnt;
20
- }
21
- return false;
22
-
23
-
24
- }
25
-
26
-
27
- function ahc_browsers_count(){
28
- global $wpdb;
29
- $result = $wpdb->get_results("SELECT count(`bsr_id`) as cnt FROM `ahc_browsers` WHERE `bsr_visits` > 0", OBJECT);
30
- if($result !== false){
31
- return $result[0]->cnt;
32
- }
33
- return false;
34
-
35
-
36
- }
37
-
38
- function ahc_getVisitsTime(){
39
- global $wpdb;
40
- $result = $wpdb->get_results("SELECT COUNT( `vtm_id` ) cnt FROM ahc_visits_time", OBJECT);
41
- if($result !== false){
42
- return $result[0]->cnt;
43
- }
44
- return false;
45
- }
46
 
47
- function ahc_getCountriesCount(){
48
- global $wpdb;
49
- $result = $wpdb->get_results("SELECT COUNT( `ctr_id` ) cnt FROM ahc_countries", OBJECT);
50
- if($result !== false){
51
- return $result[0]->cnt;
52
- }
53
- return false;
54
- }
55
-
56
-
57
- function ahc_set_default_options(){
58
- // plugin activation
59
- require_once("database_basics_data.php");
60
 
61
- if(get_option('ahc_wp_hits_counter_options') === false){
62
-
63
- $plugin_options = array();
64
- $plugin_options['ahc_version'] = '1.0';
65
- $plugin_options['available_languages'] = array('ar' => 'عربي', 'en' => 'English');
66
- $plugin_options['ahc_lang'] = 'en';
67
- $plugin_options['user_roles_to_not_track'] = array('administrator' => true, 'editor' => true, 'author' => true, 'contributor' => true, 'subscriber' => false);
68
- add_option( 'ahc_wp_hits_counter_options', $plugin_options);
69
- set_time_limit(300);
70
- }
71
- ahc_create_database_tables();
72
-
73
- if(ahc_getCountriesCount() == 0)
74
- {
75
- ahc_insert_countries_into_table($internetCountryCodes, $contriesLatLng);
76
- }
77
-
78
- if(ahc_search_engins_count() == 0)
79
  {
80
- ahc_insert_search_engines_into_table($searchEngines);
81
  }
82
 
83
- if(ahc_browsers_count() == 0)
84
- {
85
- ahc_insert_browsers_into_table($browsers);
86
- }
87
 
88
- if(ahc_getVisitsTime() == 0)
89
- {
90
- ahc_insert_visit_times_into_table($dayHours);
91
- }
92
 
 
93
 
 
94
 
95
-
 
 
 
 
 
 
 
 
 
 
96
  }
97
 
98
- function ahc_get_visitors_by_date(){
 
 
 
 
99
  global $wpdb;
100
- $lastDays = AHC_VISITORS_VISITS_LIMIT;
101
- $response = array();
102
- $beginning = new DateTime();
103
- $beginning->modify('-'.$lastDays.' day');
104
- $sql = "SELECT vst_date, vst_visitors
105
- FROM ahc_visitors
106
- WHERE DATE(vst_date) >= DATE(%s)";
107
-
108
 
109
- $results = $wpdb->get_results($wpdb->prepare($sql, $beginning->format('Y-m-d')), OBJECT);
110
- if($results !== false){
111
- for($i = count($results); $i < $lastDays; $i++){
112
- $beginning->modify('+1 day');
113
- $xx .= "['".$beginning->format('Y-m-d')."', 0], ";
 
 
 
 
 
 
 
 
 
 
 
 
114
  }
115
- foreach($results as $r)
116
- {
117
-
118
- $hitDate = new DateTime($r->vst_date);
119
- $xx .= "['".$hitDate->format('Y-m-d')."', ".$r->vst_visitors."], ";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  }
121
-
122
  }
123
- return '['.$xx.']';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  }
125
 
126
- function ahc_get_visits_by_date(){
127
  global $wpdb;
128
- $lastDays = AHC_VISITORS_VISITS_LIMIT;
129
- $response = array();
130
- $beginning = new DateTime();
131
- $beginning->modify('-'.$lastDays.' day');
132
- $sql = "SELECT vst_date, vst_visits
133
- FROM ahc_visitors
134
- WHERE DATE(vst_date) >= DATE(%s)";
135
-
136
-
137
- $results = $wpdb->get_results($wpdb->prepare($sql, $beginning->format('Y-m-d')), OBJECT);
138
- if($results !== false){
139
- for($i = count($results); $i < $lastDays; $i++){
140
- $beginning->modify('+1 day');
141
- $x .= "['".$beginning->format('Y-m-d')."', 0], ";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  }
143
- foreach($results as $r)
144
- {
145
- $hitDate = new DateTime($r->vst_date);
146
- $x .= "['".$hitDate->format('Y-m-d')."', ".$r->vst_visits."], ";
 
 
 
 
 
 
 
 
 
 
 
147
  }
148
-
149
  }
150
- return '['.$x.']';
151
- }
152
 
153
 
 
 
 
154
  //--------------------------------------------
155
  /**
156
  * Called when plugin is deactivated
157
  *
158
  * @return void
159
  */
160
- function ahc_unset_default_options(){
 
161
  }
 
162
  //--------------------------------------------
163
  /**
164
  * Creates plugin page link in the admin menu
@@ -168,20 +272,158 @@ function ahc_unset_default_options(){
168
  *
169
  * @return void
170
  */
171
- function ahc_create_admin_menu_link(){
172
- add_menu_page('Visitors Traffic Real Time Statistics', 'Visitors Traffic', 'manage_options', 'ahc_hits_counter_menu', 'ahc_create_plugin_overview_page',
173
- plugins_url('/images/vtrts.png', AHC_PLUGIN_MAIN_FILE));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  }
 
175
  //--------------------------------------------
176
  /**
177
  * Creates the main overview page
178
  *
179
  * @return void
180
  */
181
- function ahc_create_plugin_overview_page(){
182
- require_once(AHC_PLUGIN_ROOT_DIR.AHC_DS.'lang'.AHC_DS.Globals::$lang.'_lang.php');
183
- include("overview.php");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  }
 
185
  //--------------------------------------------
186
  /**
187
  * Returns links array of available languages
@@ -191,21 +433,22 @@ function ahc_create_plugin_overview_page(){
191
  *
192
  * @return array
193
  */
194
- function ahc_get_change_lang_links(){
195
- $plugin_options = get_option('ahc_wp_hits_counter_options');
196
- $links = array();
197
- $i = 0;
198
- foreach($plugin_options['available_languages'] as $key => $value){
199
- if(Globals::$lang != $key){
200
- $links[$i]['name'] = $value;
201
- $links[$i]['href'] = add_query_arg('ahc_lang', $key);
202
- $i++;
203
- }
204
- }
205
- unset($plugin_options);
206
- unset($i);
207
- return $links;
208
  }
 
209
  //--------------------------------------------
210
  /**
211
  * Decides whether or not should track the current visitor
@@ -215,23 +458,24 @@ function ahc_get_change_lang_links(){
215
  *
216
  * @return boolean
217
  */
218
- function ahc_should_track_visitor(){
219
- global $current_user;
220
- $allow = true;
221
- if(is_user_logged_in()){
222
- $user = new WP_User($current_user->ID);
223
- if(!empty($user->roles) && is_array($user->roles)){
224
- foreach($user->roles as $role){
225
- $found = (isset(Globals::$plugin_options['user_roles_to_not_track'][$role]))? Globals::$plugin_options['user_roles_to_not_track'][$role] : false;
226
- if($found){
227
- $allow = false;
228
- break;
229
- }
230
- }
231
- }
232
- }
233
- return $allow;
234
  }
 
235
  //--------------------------------------------
236
  /**
237
  * Returns true if the current user has administrator role
@@ -241,162 +485,173 @@ function ahc_should_track_visitor(){
241
  *
242
  * @return boolean
243
  */
244
- function ahc_has_administrator_role(){
245
- global $user_ID;
246
- $is_admin = false;
247
- if(is_user_logged_in()){
248
- $user = new WP_User($user_ID);
249
- if(!empty($user->roles) && is_array($user->roles)){
250
- foreach($user->roles as $role){
251
- if($role == 'administrator'){
252
- $is_admin = true;
253
- break;
254
- }
255
- }
256
- }
257
- }
258
- return $is_admin;
259
  }
 
260
  //--------------------------------------------
261
  /**
262
- * Creates database plugin tables
263
  *
264
  * @uses wpdb::query()
265
  *
266
  * @return boolean
267
  */
268
- /*
269
- function ahc_create_database_tables(){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  global $wpdb;
271
  $sqlQueries = array();
272
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_hits`
 
 
 
 
 
 
 
 
273
  (
274
- `hit_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
275
- PRIMARY KEY(`hit_id`),
276
  `hit_ip_address` VARCHAR(50) NOT NULL,
277
- `hit_user_agent` VARCHAR(200) NOT NULL,
278
- `hit_request_uri` VARCHAR(200) NULL,
279
  `hit_page_id` VARCHAR(30) NOT NULL,
280
- `hit_page_title` VARCHAR(200) NULL,
281
- `hit_referer` VARCHAR(300) NULL,
282
- `hit_referer_site` VARCHAR(100) NULL,
283
- `srh_id` INT(3) UNSIGNED NULL,
284
- `hit_search_words` VARCHAR(200) NULL,
285
- `bsr_id` INT(3) UNSIGNED NOT NULL,
286
- `hit_date` DATE NOT NULL,
287
- `hit_time` TIME NOT NULL
288
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
289
-
290
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_browsers`
291
- (
292
- `bsr_id` INT(3) UNSIGNED NOT NULL,
293
- PRIMARY KEY(`bsr_id`),
294
- `bsr_name` VARCHAR(100) NOT NULL,
295
- `bsr_icon` VARCHAR(50),
296
- `bsr_visits` INT(11) NOT NULL DEFAULT 0
297
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
298
 
299
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_search_engines`
300
- (
301
- `srh_id` INT(3) UNSIGNED NOT NULL AUTO_INCREMENT,
302
- PRIMARY KEY(`srh_id`),
303
- `srh_name` VARCHAR(100) NOT NULL,
304
- `srh_query_parameter` VARCHAR(10) NOT NULL,
305
- `srh_icon` VARCHAR(50),
306
- `srh_identifier` VARCHAR(50)
307
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
308
-
309
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_search_engine_crawlers`
310
- (
311
- `bot_name` VARCHAR(50) NOT NULL,
312
- `srh_id` INT(3) UNSIGNED NOT NULL
313
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
314
-
315
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_visitors`
316
- (
317
- `vst_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
318
- PRIMARY KEY (`vst_id`),
319
- `vst_date` DATE NOT NULL,
320
- `vst_visitors` INT(11) UNSIGNED NULL DEFAULT 0,
321
- `vst_visits` INT(11) UNSIGNED NULL DEFAULT 0
322
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
323
-
324
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_searching_visits`
325
- (
326
- `vtsh_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
327
- PRIMARY KEY (`vtsh_id`),
328
- `srh_id` INT(3) UNSIGNED NOT NULL,
329
- `vtsh_date` DATE NOT NULL,
330
- `vtsh_visits` INT(11) UNSIGNED NOT NULL DEFAULT 0
331
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
332
-
333
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_refering_sites`
334
- (
335
- `rfr_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
336
- PRIMARY KEY (`rfr_id`),
337
- `rfr_site_name` VARCHAR(100) NOT NULL,
338
- `rfr_visits` INT(11) UNSIGNED NULL DEFAULT 0
339
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
340
-
341
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_recent_visitors`
342
- (
343
- `vtr_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
344
- PRIMARY KEY (`vtr_id`),
345
- `vtr_ip_address` VARCHAR(50) NOT NULL,
346
- `vtr_referer` VARCHAR(300) NULL,
347
- `srh_id` INT(3) UNSIGNED NULL,
348
- `bsr_id` INT(3) UNSIGNED NOT NULL,
349
- `vtr_date` DATE NOT NULL,
350
- `vtr_time` TIME NOT NULL
351
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
352
-
353
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_keywords`
354
- (
355
- `kwd_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
356
- PRIMARY KEY (`kwd_id`),
357
- `kwd_ip_address` VARCHAR(50) NOT NULL,
358
- `kwd_keywords` VARCHAR(200) NOT NULL,
359
- `kwd_referer` VARCHAR(300) NOT NULL,
360
- `srh_id` INT(3) UNSIGNED NOT NULL,
361
- `bsr_id` INT(3) UNSIGNED NOT NULL,
362
- `kwd_date` DATE NOT NULL,
363
- `kwd_time` TIME NOT NULL
364
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
365
-
366
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_title_traffic`
367
- (
368
- `til_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
369
- PRIMARY KEY (`til_id`),
370
- `til_page_id` VARCHAR(30) NOT NULL,
371
- `til_page_title` VARCHAR(100),
372
- `til_hits` INT(11) UNSIGNED NOT NULL
373
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
374
-
375
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_visits_time`
376
- (
377
- `vtm_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
378
- PRIMARY KEY (`vtm_id`),
379
- `vtm_time_from` TIME NOT NULL,
380
- `vtm_time_to` TIME NOT NULL,
381
- `vtm_visitors` INT(11) UNSIGNED NOT NULL DEFAULT 0,
382
- `vtm_visits` INT(11) UNSIGNED NOT NULL DEFAULT 0
383
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
384
-
385
- foreach($sqlQueries as $sql){
386
- if($wpdb->query($sql) === false){
387
- return false;
388
- }
389
  }
390
- return true;
391
  }
392
- */
393
 
 
394
 
 
 
395
 
396
- function ahc_create_database_tables(){
397
- global $wpdb;
398
- $sqlQueries = array();
399
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_hits`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
400
  (
401
  `hit_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
402
  PRIMARY KEY(`hit_id`),
@@ -414,8 +669,24 @@ function ahc_create_database_tables(){
414
  `hit_date` DATE NOT NULL,
415
  `hit_time` TIME NOT NULL
416
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
417
-
418
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_browsers`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
419
  (
420
  `bsr_id` INT(3) UNSIGNED NOT NULL,
421
  PRIMARY KEY(`bsr_id`),
@@ -423,8 +694,8 @@ function ahc_create_database_tables(){
423
  `bsr_icon` VARCHAR(50),
424
  `bsr_visits` INT(11) NOT NULL DEFAULT 0
425
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
426
-
427
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_search_engines`
428
  (
429
  `srh_id` INT(3) UNSIGNED NOT NULL AUTO_INCREMENT,
430
  PRIMARY KEY(`srh_id`),
@@ -433,14 +704,14 @@ function ahc_create_database_tables(){
433
  `srh_icon` VARCHAR(50),
434
  `srh_identifier` VARCHAR(50)
435
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
436
-
437
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_search_engine_crawlers`
438
  (
439
  `bot_name` VARCHAR(50) NOT NULL,
440
  `srh_id` INT(3) UNSIGNED NOT NULL
441
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
442
-
443
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_countries`
444
  (
445
  `ctr_id` INT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
446
  PRIMARY KEY(`ctr_id`),
@@ -451,8 +722,8 @@ function ahc_create_database_tables(){
451
  `ctr_visitors` INT(11) NOT NULL DEFAULT 0,
452
  `ctr_visits` INT(11) NOT NULL DEFAULT 0
453
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
454
-
455
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_visitors`
456
  (
457
  `vst_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
458
  PRIMARY KEY (`vst_id`),
@@ -460,8 +731,20 @@ function ahc_create_database_tables(){
460
  `vst_visitors` INT(11) UNSIGNED NULL DEFAULT 0,
461
  `vst_visits` INT(11) UNSIGNED NULL DEFAULT 0
462
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
463
-
464
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_searching_visits`
 
 
 
 
 
 
 
 
 
 
 
 
465
  (
466
  `vtsh_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
467
  PRIMARY KEY (`vtsh_id`),
@@ -469,16 +752,18 @@ function ahc_create_database_tables(){
469
  `vtsh_date` DATE NOT NULL,
470
  `vtsh_visits` INT(11) UNSIGNED NOT NULL DEFAULT 0
471
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
472
-
473
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_refering_sites`
 
 
474
  (
475
  `rfr_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
476
  PRIMARY KEY (`rfr_id`),
477
  `rfr_site_name` VARCHAR(100) NOT NULL,
478
  `rfr_visits` INT(11) UNSIGNED NULL DEFAULT 0
479
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
480
-
481
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_recent_visitors`
482
  (
483
  `vtr_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
484
  PRIMARY KEY (`vtr_id`),
@@ -490,8 +775,8 @@ function ahc_create_database_tables(){
490
  `vtr_date` DATE NOT NULL,
491
  `vtr_time` TIME NOT NULL
492
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
493
-
494
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_keywords`
495
  (
496
  `kwd_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
497
  PRIMARY KEY (`kwd_id`),
@@ -504,8 +789,8 @@ function ahc_create_database_tables(){
504
  `kwd_date` DATE NOT NULL,
505
  `kwd_time` TIME NOT NULL
506
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
507
-
508
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_title_traffic`
509
  (
510
  `til_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
511
  PRIMARY KEY (`til_id`),
@@ -513,8 +798,8 @@ function ahc_create_database_tables(){
513
  `til_page_title` VARCHAR(100),
514
  `til_hits` INT(11) UNSIGNED NOT NULL
515
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
516
-
517
- $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_visits_time`
518
  (
519
  `vtm_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
520
  PRIMARY KEY (`vtm_id`),
@@ -523,120 +808,126 @@ function ahc_create_database_tables(){
523
  `vtm_visitors` INT(11) UNSIGNED NOT NULL DEFAULT 0,
524
  `vtm_visits` INT(11) UNSIGNED NOT NULL DEFAULT 0
525
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
526
-
527
- foreach($sqlQueries as $sql){
528
- if($wpdb->query($sql) === false){
529
- return false;
530
- }
531
- }
532
- return true;
 
 
 
 
 
 
 
533
  }
 
534
  //--------------------------------------------
535
  /**
536
- * Inserts search engines into ahc_search_engines table
537
  *
538
  * @uses wpdb::insert()
539
- * @uses wpdb::$insert_id
540
  *
541
- * @param array $searchEngines.
 
542
  * @return boolean
543
  */
544
- function ahc_insert_search_engines_into_table($searchEngines){
545
- global $wpdb;
546
- foreach($searchEngines as $se){
547
- $result = $wpdb->insert('ahc_search_engines', array(
548
- 'srh_name' => $se['srh_name'],
549
- 'srh_query_parameter' => $se['srh_query_parameter'],
550
- 'srh_icon' => $se['srh_icon'],
551
- 'srh_identifier' => $se['srh_identifier']
552
- ),
553
- array(
554
- '%s', '%s', '%s', '%s'
555
- )
556
- );
557
- if($result !== false){
558
- $srh_id = $wpdb->insert_id;
559
- foreach($se['crawlers'] as $crawler){
560
- $result2 = $wpdb->insert('ahc_search_engine_crawlers', array(
561
- 'bot_name' => $crawler,
562
- 'srh_id' => $srh_id
563
- ),
564
- array(
565
- '%s', '%d'
566
- )
567
- );
568
- if($result2 === false){
569
- return false;
570
- }
571
- }
572
- } else{
573
- return false;
574
- }
575
- }
576
- return true;
577
  }
 
578
  //--------------------------------------------
579
  /**
580
- * Inserts browsers into ahc_browsers table
581
  *
582
  * @uses wpdb::insert()
 
583
  *
584
- * @param array $browsers
585
  * @return boolean
586
  */
587
- function ahc_insert_browsers_into_table($browsers){
588
- global $wpdb;
589
- foreach($browsers as $browser){
590
- $result = $wpdb->insert('ahc_browsers', array(
591
- 'bsr_id' => $browser['bsr_id'],
592
- 'bsr_name' => $browser['bsr_name'],
593
- 'bsr_icon' => $browser['bsr_icon']
594
- ),
595
- array(
596
- '%d', '%s', '%s'
597
- )
598
- );
599
- if($result === false){
600
- return false;
601
- }
602
- }
603
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
604
  }
605
 
 
606
  /**
607
- * Inserts countries into ahc_countroes table
608
  *
609
  * @uses wpdb::insert()
610
  *
611
- * @param array $internetCountryCodes. internet codes and names of countries
612
- * @param array $contriesLatLng. LatLng of countries
613
  * @return boolean
614
  */
615
- function ahc_insert_countries_into_table($internetCountryCodes, $contriesLatLng){
616
- global $wpdb;
617
- $c = 1;
618
- $length = count($internetCountryCodes);
619
- foreach($internetCountryCodes as $internetCode => $countryName){
620
- $ctr_latitude = $ctr_longitude = NULL;
621
- if(isset($contriesLatLng[$internetCode])){
622
- $ctr_latitude = $contriesLatLng[$internetCode][0];
623
- $ctr_longitude = $contriesLatLng[$internetCode][1];
624
- }
625
- $result = $wpdb->insert('ahc_countries', array(
626
- 'ctr_name' => $countryName,
627
- 'ctr_internet_code' => $internetCode,
628
- 'ctr_latitude' => $ctr_latitude,
629
- 'ctr_longitude' => $ctr_longitude
630
- ),
631
- array(
632
- '%s', '%s', '%s', '%s'
633
- )
634
- );
635
- if($result === false){
636
- return false;
637
- }
638
- }
639
- return true;
640
  }
641
 
642
  //--------------------------------------------
@@ -648,24 +939,24 @@ function ahc_insert_countries_into_table($internetCountryCodes, $contriesLatLng)
648
  * @param array $dayHours
649
  * @return boolean
650
  */
651
- function ahc_insert_visit_times_into_table($dayHours){
652
- global $wpdb;
653
- foreach($dayHours as $t){
654
- $result = $wpdb->insert('ahc_visits_time', array(
655
- 'vtm_time_from' => $t['vtm_time_from'],
656
- 'vtm_time_to' => $t['vtm_time_to'],
657
- 'vtm_visitors' => 0
658
- ),
659
- array(
660
- '%s', '%s', '%d'
661
- )
662
- );
663
- if($result === false){
664
- return false;
665
- }
666
- }
667
- return true;
668
  }
 
669
  //--------------------------------------------
670
  /**
671
  * Returns the first and last days of the week of the date you pass
@@ -674,117 +965,130 @@ function ahc_insert_visit_times_into_table($dayHours){
674
  * @param string $format Optional
675
  * @return array
676
  */
677
- function ahc_get_week_limits($date, $format = 'Y-m-d'){
678
- $beginingDay = new DateTime($date);
679
- $endingDay = new DateTime($date);
680
- $date = new DateTime($date);
681
- switch($date->format('w')){
682
- case 0: // sun
683
- //$beginingDay->modify('-1 day');
684
- $endingDay->modify('+6 day');
685
- break;
686
-
687
- case 1: // mon
688
- $beginingDay->modify('-1 day');
689
- $endingDay->modify('+5 day');
690
- break;
691
-
692
- case 2: // Tue
693
- $beginingDay->modify('-2 day');;
694
- $endingDay->modify('+4 day');
695
- break;
696
-
697
- case 3: // Wed
698
- $beginingDay->modify('-3 day');;
699
- $endingDay->modify('+3 day');
700
- break;
701
-
702
- case 4: // Thu
703
- $beginingDay->modify('-4 day');
704
- $endingDay->modify('+2 day');
705
- break;
706
-
707
- case 6: // Fri
708
- $beginingDay->modify('-5 day');
709
- $endingDay->modify('+1 day');
710
- break;
711
- }
712
- return array(0 => $beginingDay->format($format), 1 => $endingDay->format($format));
 
 
 
 
 
 
713
  }
 
714
  //--------------------------------------------
715
  /**
716
  * Return summary statistics of visitors and visits
717
  *
718
  * @return array
719
  */
720
- function ahc_get_summary_statistics(){
721
- $arr = array();
722
- $arr['today'] = ahc_get_visitors_visits_in_period('today');
723
- $arr['yesterday'] = ahc_get_visitors_visits_in_period('yesterday');
724
- $arr['week'] = ahc_get_visitors_visits_in_period('week');
725
- $arr['month'] = ahc_get_visitors_visits_in_period('month');
726
- $arr['year'] = ahc_get_visitors_visits_in_period('year');
727
- $arr['total'] = ahc_get_visitors_visits_in_period();
728
- return $arr;
729
  }
 
730
  //--------------------------------------------
731
  /**
732
  * Return counts visitors and visits in certain day (today|yesterday), certain period(last week, last month, last year) or total
733
  *
734
  * @uses wpdb::prepare()
735
- * @uses wpdb::get_results()
736
- *
737
- * @param string $period Optional
738
- * @return mixed
739
- */
740
- function ahc_get_visitors_visits_in_period($period = 'total'){
741
- global $wpdb;
742
- $date = new DateTime();
743
- $sql = "SELECT SUM(vst_visitors) AS vst_visitors, SUM(vst_visits) AS vst_visits
744
- FROM `ahc_visitors`
745
- WHERE 1 = 1";
746
- $results = false;
747
- switch($period){
748
- case 'today':
749
- $sql .= " AND DATE(vst_date) = DATE(NOW())";
750
- $results = $wpdb->get_results($sql, OBJECT);
751
- break;
752
-
753
- case 'yesterday':
754
- $date->modify('-1 day');
755
- $sql .= " AND DATE(vst_date) = DATE(%s)";
756
- $results = $wpdb->get_results($wpdb->prepare($sql, $date->format('Y-m-d')), OBJECT);
757
- break;
758
-
759
- case 'week':
760
- $limits = ahc_get_week_limits($date->format('Y-m-d'));
761
- $sql .= " AND DATE(vst_date) >= DATE(%s) AND DATE(vst_date) <= DATE(%s)";
762
- $results = $wpdb->get_results($wpdb->prepare($sql, $limits[0], $limits[1]), OBJECT);
763
- break;
764
-
765
- case 'month':
766
- $sql .= " AND DATE(vst_date) >= DATE(%s) AND DATE(vst_date) <= DATE(%s)";
767
- $results = $wpdb->get_results($wpdb->prepare($sql, $date->format('Y-m-01'), $date->format('Y-m-d')), OBJECT);
768
- break;
769
-
770
- case 'year':
771
- $sql .= " AND DATE(vst_date) >= DATE(%s) AND DATE(vst_date) <= DATE(%s)";
772
- $results = $wpdb->get_results($wpdb->prepare($sql, $date->format('Y-01-01'), $date->format('Y-12-31')), OBJECT);
773
- break;
774
-
775
- default:
776
- $results = $wpdb->get_results($sql, OBJECT);
777
- }
778
-
779
- if($results !== false){
780
- return array(
781
- 'visitors' => (empty($results[0]->vst_visitors)? 0 : $results[0]->vst_visitors),
782
- 'visits' => (empty($results[0]->vst_visits)? 0 : $results[0]->vst_visits)
783
- );
784
- } else{
785
- return false;
786
- }
 
 
 
 
787
  }
 
788
  //--------------------------------------------
789
  /**
790
  * Return visits in a period from today
@@ -794,93 +1098,108 @@ function ahc_get_visitors_visits_in_period($period = 'total'){
794
  *
795
  * @return array
796
  */
797
- function ahc_get_visitors_visits_by_date(){
798
  global $wpdb;
799
  $lastDays = AHC_VISITORS_VISITS_LIMIT - 1;
800
  $response = array();
 
 
801
  $beginning = new DateTime();
802
- $beginning->modify('-'.$lastDays.' day');
803
- $sql = "SELECT vst_date, vst_visitors, vst_visits
 
 
804
  FROM ahc_visitors
805
- WHERE DATE(vst_date) >= DATE(%s)";
806
-
807
-
808
  $results = $wpdb->get_results($wpdb->prepare($sql, $beginning->format('Y-m-d')), OBJECT);
809
- if($results !== false){
810
  $response['success'] = true;
811
  $response['date'] = array();
812
- for($i = count($results); $i < $lastDays; $i++){
813
  $beginning->modify('+1 day');
814
  $response['data']['dates'][] = $beginning->format('d/m');
815
  $response['data']['visitors'][] = 0;
816
  $response['data']['visits'][] = 0;
817
  }
818
- foreach($results as $r){
 
819
  $hitDate = new DateTime($r->vst_date);
 
820
  $response['data']['dates'][] = $hitDate->format('d/m');
821
  $response['data']['visitors'][] = $r->vst_visitors;
822
  $response['data']['visits'][] = $r->vst_visits;
823
  }
824
- } else{
825
  $response['success'] = false;
826
  }
827
  return $response;
828
  }
829
- //--------------------------------------------
830
- /**
831
- * Return visitors visits that came from search engine in a period from today
832
- *
833
- * @uses wpdb::prepare()
834
- * @uses wpdb::get_results()
835
- *
836
- * @return array
837
- */
838
- function ahc_get_serch_visits_by_date(){
839
- global $wpdb;
840
- $searchEngines = ahc_get_all_search_engines();
841
- $lastDays = AHC_VISITORS_VISITS_SUMMARY_LIMIT - 1;
842
- $response = array();
843
- $beginning = new DateTime();
844
- $beginning->modify('-'.$lastDays.' day');
845
- $sql = "SELECT srh_id, vtsh_visits, vtsh_date
846
- FROM `ahc_searching_visits`
847
- WHERE DATE(vtsh_date) >= DATE(%s)";
848
-
849
- $results = $wpdb->get_results($wpdb->prepare($sql, $beginning->format('Y-m-d')), OBJECT);
850
- if($results !== false){
851
- $arr = array();
852
- foreach($results as $r){
853
- $hitDate = new DateTime($r->vtsh_date);
854
- $arr[$hitDate->format('Ymd').'-'.$r->srh_id] = $r->vtsh_visits;
855
- }
856
-
857
- $response['success'] = true;
858
- $response['data']['dates'] = array();
859
- foreach($searchEngines as $srhEng){
860
- $response['data']['search_engines'][$srhEng['srh_name']] = array();
861
- }
862
-
863
- $date = new DateTime();
864
- $date->modify('-'.$lastDays.' day');
865
- for($i = 0; $i <= $lastDays; $i++){
866
- $response['data']['dates'][] = $date->format('d/m');
867
-
868
- foreach($searchEngines as $srhEng){
869
- if(isset($arr[$date->format('Ymd').'-'.$srhEng['srh_id']])){
870
- $response['data']['search_engines'][$srhEng['srh_name']][] = $arr[$date->format('Ymd').'-'.$srhEng['srh_id']];
871
- } else{
872
- $response['data']['search_engines'][$srhEng['srh_name']][] = 0;
873
- }
874
- }
875
-
876
- $date->modify('+1 day');
877
- }
878
-
879
- } else{
880
- $response['success'] = false;
881
- }
882
- return $response;
 
 
 
 
 
 
 
883
  }
 
 
 
884
  //--------------------------------------------
885
  /**
886
  * Returns the total visits by search engines
@@ -889,14 +1208,15 @@ function ahc_get_serch_visits_by_date(){
889
  *
890
  * @return mixed
891
  */
892
- function ahc_get_total_visits_by_search_engines(){
893
- global $wpdb;
894
- $result = $wpdb->get_results("SELECT SUM(vtsh_visits) AS total FROM ahc_searching_visits", OBJECT);
895
- if($result !== false){
896
- return $result[0]->total;
897
- }
898
- return false;
899
  }
 
900
  //--------------------------------------------
901
  /**
902
  * Return counts visits happened by search engine result in certain day (today|yesterday), certain period(last week, last month, last year) or total
@@ -907,53 +1227,56 @@ function ahc_get_total_visits_by_search_engines(){
907
  * @param string $period Optional
908
  * @return mixed
909
  */
910
- function ahc_get_hits_search_engines_referers($period = 'total'){
911
- global $wpdb;
912
- $date = new DateTime();
913
- $sql = "SELECT srh_id, vtsh_visits
 
 
 
914
  FROM `ahc_searching_visits`";
915
- $results = false;
916
- switch($period){
917
- case 'today':
918
- $sql .= " WHERE DATE(vtsh_date) = DATE(NOW())";
919
- $results = $wpdb->get_results($sql, OBJECT);
920
- break;
921
-
922
- case 'yesterday':
923
- $date->modify('-1 day');
924
- $sql .= " WHERE DATE(vtsh_date) = DATE(%s)";
925
- $results = $wpdb->get_results($wpdb->prepare($sql, $date->format('Y-m-d')), OBJECT);
926
- break;
927
-
928
- case 'week':
929
- $limits = ahc_get_week_limits($date->format('Y-m-d'));
930
- $sql .= " WHERE DATE(vtsh_date) >= DATE(%s) AND DATE(vtsh_date) <= DATE(%s)";
931
- $results = $wpdb->get_results($wpdb->prepare($sql, $limits[0], $limits[1]), OBJECT);
932
- break;
933
-
934
- case 'month':
935
- $sql .= " WHERE DATE(vtsh_date) >= DATE('".$date->format('Y-m-01')."') AND DATE(vtsh_date) <= DATE('".$date->format('Y-m-t')."')";
936
- $results = $wpdb->get_results($wpdb->prepare($sql, $limits[0], $limits[1]), OBJECT);
937
- break;
938
-
939
- case 'year':
940
- $sql .= " WHERE DATE(vtsh_date) >= DATE(%s) AND DATE(vtsh_date) <= DATE(%s)";
941
- $results = $wpdb->get_results($wpdb->prepare($sql, $date->format('Y-01-01'), $date->format('Y-12-31')), OBJECT);
942
- break;
943
-
944
- default:
945
- $results = $wpdb->get_results($sql, OBJECT);
946
- }
947
-
948
- $hitsReferers = array();
949
- if($results !== false){
950
- foreach($results as $r){
951
- $hitsReferers[$r->srh_id] = $r->vtsh_visits;
952
- }
953
- return $hitsReferers;
954
- }
955
- return false;
956
  }
 
957
  //--------------------------------------------
958
  /**
959
  * Retrieves all search engines
@@ -962,23 +1285,24 @@ function ahc_get_hits_search_engines_referers($period = 'total'){
962
  *
963
  * @return mixed
964
  */
965
- function ahc_get_all_search_engines(){
966
- global $wpdb;
967
- $sql = "SELECT `srh_id`, `srh_name`, `srh_icon` FROM `ahc_search_engines`";
968
- $searchEngines = array();
969
- $c = 0;
970
- $results = $wpdb->get_results($sql, OBJECT);
971
- if($results !== false){
972
- foreach($results as $re){
973
- $searchEngines[$c]['srh_id'] = $re->srh_id;
974
- $searchEngines[$c]['srh_name'] = $re->srh_name;
975
- $searchEngines[$c]['srh_icon'] = $re->srh_icon;
976
- $c++;
977
- }
978
- return $searchEngines;
979
- }
980
- return false;
981
  }
 
982
  //--------------------------------------------
983
  /**
984
  * Retrieves count of visits order by browsers
@@ -987,28 +1311,66 @@ function ahc_get_all_search_engines(){
987
  *
988
  * @return array
989
  */
990
- function ahc_get_browsers_hits_counts(){
991
- global $wpdb;
992
- $sql = "SELECT `bsr_id`, `bsr_name`, `bsr_visits`
993
  FROM `ahc_browsers`
994
  WHERE `bsr_visits` > 0";
995
- $results = $wpdb->get_results($sql, OBJECT);
996
- $response = array();
997
- if($results !== false){
998
- $response['success'] = true;
999
- $response['data'] = array();
1000
- $c = 0;
1001
- foreach($results as $bsr){
1002
- $response['data'][$c]['bsr_id'] = $bsr->bsr_id;
1003
- $response['data'][$c]['bsr_name'] = $bsr->bsr_name;
1004
- $response['data'][$c]['hits'] = $bsr->bsr_visits;
1005
- $c++;
1006
- }
1007
- } else{
1008
- $response['success'] = false;
1009
- }
1010
- return $response;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1011
  }
 
1012
  //--------------------------------------------
1013
  /**
1014
  * Retrieves top referring sites
@@ -1018,26 +1380,104 @@ function ahc_get_browsers_hits_counts(){
1018
  *
1019
  * @return mixed
1020
  */
1021
- function ahc_get_top_refering_sites(){
1022
- global $wpdb;
1023
- $sql = "SELECT rfr_site_name, rfr_visits
1024
  FROM `ahc_refering_sites`
1025
  ORDER BY rfr_visits DESC
1026
  LIMIT %d OFFSET 0";
1027
- $results = $wpdb->get_results($wpdb->prepare($sql, AHC_TOP_REFERING_SITES_LIMIT), OBJECT);
1028
- if($results !== false){
1029
- $arr = array();
1030
- $c = 0;
1031
- foreach($results as $referer){
1032
- $arr[$c]['site_name'] = $referer->rfr_site_name;
1033
- $arr[$c]['total_hits'] = $referer->rfr_visits;
1034
- $c++;
1035
- }
1036
- return $arr;
1037
- } else{
1038
- return false;
1039
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1040
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1041
  //--------------------------------------------
1042
  /**
1043
  * Retrieves recent visitors
@@ -1047,37 +1487,56 @@ function ahc_get_top_refering_sites(){
1047
  *
1048
  * @return mixed
1049
  */
1050
- function ahc_get_recent_visitors(){
1051
- global $wpdb, $_SERVER;
1052
- $sql = "SELECT v.vtr_id, v.vtr_ip_address, v.vtr_referer, v.vtr_date, v.vtr_time,
1053
- b.bsr_name, b.bsr_icon
 
1054
  FROM `ahc_recent_visitors` AS v
1055
- JOIN `ahc_browsers` AS b ON v.bsr_id = b.bsr_id
 
1056
  WHERE v.vtr_ip_address NOT LIKE 'UNKNOWN%%'
1057
- ORDER BY v.vtr_date DESC
1058
- LIMIT %d OFFSET 0";
1059
-
1060
- $results = $wpdb->get_results($wpdb->prepare($sql, AHC_RECENT_VISITORS_LIMIT));
1061
- if($results !== false){
1062
- $arr = array();
1063
- $c = 0;
1064
- if(is_array($results)){
1065
- foreach($results as $hit){
1066
- $arr[$c]['hit_id'] = $hit->vtr_id;
1067
- $arr[$c]['hit_ip_address'] = $hit->vtr_ip_address;
1068
- $arr[$c]['hit_referer'] = (parse_url($hit->vtr_referer, PHP_URL_HOST) == $_SERVER['SERVER_NAME'])? '' : rawurldecode($hit->vtr_referer);
1069
- $arr[$c]['hit_date'] = $hit->vtr_date;
1070
- $arr[$c]['hit_time'] = $hit->vtr_time;
1071
- $arr[$c]['bsr_name'] = $hit->bsr_name;
1072
- $arr[$c]['bsr_icon'] = $hit->bsr_icon;
1073
- $c++;
1074
- }
1075
- }
1076
- return $arr;
1077
- } else{
1078
- return false;
1079
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1080
  }
 
1081
  //--------------------------------------------
1082
  /**
1083
  * Retrieves latest of key words used in search
@@ -1087,47 +1546,138 @@ function ahc_get_recent_visitors(){
1087
  *
1088
  * @return mixed
1089
  */
1090
- function ahc_get_latest_search_key_words_used(){
1091
- global $wpdb;
1092
- $sql = "SELECT k.kwd_ip_address, k.kwd_referer, k.kwd_keywords, k.kwd_date, k.kwd_time,
1093
- b.bsr_name, b.bsr_icon, s.srh_name, s.srh_icon
 
1094
  FROM `ahc_keywords` AS k
 
1095
  JOIN `ahc_browsers` AS b ON k.bsr_id = b.bsr_id
1096
  JOIN `ahc_search_engines` AS s on k.srh_id = s.srh_id
1097
- WHERE k.kwd_ip_address NOT LIKE 'UNKNOWN%%'
1098
  ORDER BY k.kwd_date DESC, k.kwd_time DESC
1099
  LIMIT %d OFFSET 0";
1100
-
1101
- $results = $wpdb->get_results($wpdb->prepare($sql, AHC_RECENT_KEYWORDS_LIMIT), OBJECT);
1102
- if($results !== false){
1103
- $arr = array();
1104
- $c = 0;
1105
- foreach($results as $re){
1106
- $arr[$c]['hit_referer'] = rawurldecode($re->kwd_referer);
1107
- $arr[$c]['hit_search_words'] = $re->kwd_keywords;
1108
- $arr[$c]['hit_date'] = $re->kwd_date;
1109
- $arr[$c]['hit_time'] = $re->kwd_time;
1110
- $arr[$c]['hit_ip_address'] = $re->kwd_ip_address;
1111
- $arr[$c]['bsr_name'] = $re->bsr_name;
1112
- $arr[$c]['bsr_icon'] = $re->bsr_icon;
1113
- $arr[$c]['srh_name'] = $re->srh_name;
1114
- $arr[$c]['srh_icon'] = $re->srh_icon;
1115
- $c++;
1116
- }
1117
- return $arr;
1118
- } else{
1119
- return false;
1120
- }
 
 
 
1121
  }
 
1122
  //--------------------------------------------
1123
  /**
1124
  * Is in login page
1125
  *
1126
  * @return boolean
1127
  */
1128
- function ahc_is_login_page() {
1129
- return in_array($GLOBALS['pagenow'], array('wp-login.php', 'wp-register.php'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1130
  }
 
1131
  //--------------------------------------------
1132
  /**
1133
  * Detect if the visitor is search engine bot
@@ -1135,42 +1685,44 @@ function ahc_is_login_page() {
1135
  * @uses wpdb::get_results()
1136
  *
1137
  * @return boolean
1138
- */
1139
- function ahc_is_search_engine_bot(){
1140
- global $wpdb, $_SERVER;
1141
- $results = $wpdb->get_results("SELECT `bot_name` FROM `ahc_search_engine_crawlers`", OBJECT);
1142
- foreach($results as $crawler){
1143
- if(stripos($_SERVER['HTTP_USER_AGENT'], $crawler->bot_name) !== false){
1144
- return true;
1145
- }
1146
- }
1147
-
1148
- if(stripos($_SERVER['REQUEST_URI'], 'robots.txt') !== false){
1149
- return true;
1150
- }
1151
-
1152
- if(stripos($_SERVER['REQUEST_URI'], 'Bot') !== false){
1153
- return true;
1154
- }
1155
-
1156
- if(stripos($_SERVER['REQUEST_URI'], 'bot') !== false){
1157
- return true;
1158
- }
1159
- return false;
1160
  }
 
1161
  //--------------------------------------------
1162
  /**
1163
  * Detect if the visitor is WordPress bot
1164
  *
1165
  * @return boolean
1166
  */
1167
- function ahc_is_wordpress_bot(){
1168
- global $_SERVER;
1169
- if(stripos($_SERVER['HTTP_USER_AGENT'], 'WordPress') !== false){
1170
- return true;
1171
- }
1172
- return false;
1173
  }
 
1174
  //--------------------------------------------
1175
  /**
1176
  * Detects post id, post title and post type of current page
@@ -1181,71 +1733,105 @@ function ahc_is_wordpress_bot(){
1181
  * @param object $query. this object is passed to the callback function of "parse_query" hooked action
1182
  * @return mixed
1183
  */
1184
- function ahc_detect_requested_page($query){
1185
- global $wpdb;
1186
- $page_id = '';
1187
- $vars = $query->query_vars;
1188
- if(isset($vars['p']) && !empty($vars['p'])){
1189
- $result = $wpdb->get_results($wpdb->prepare("SELECT post_title FROM ".$wpdb->prefix."posts WHERE ID = %d ", $vars['p']));
1190
- if($result !== false && $wpdb->num_rows > 0){
1191
- return array('page_id' => $vars['p'], 'page_title' => $result[0]->post_title, 'post_type' => 'post');
1192
- }
1193
- }
1194
-
1195
- else if(isset($vars['name']) && !empty($vars['name'])){
1196
- $result = $wpdb->get_results($wpdb->prepare("SELECT ID, post_title FROM ".$wpdb->prefix."posts WHERE post_name = %s ", $vars['name']));
1197
- if($result !== false && $wpdb->num_rows > 0){
1198
- return array('page_id' => $result[0]->ID, 'page_title' => $result[0]->post_title, 'post_type' => 'post');
1199
- }
1200
- }
1201
-
1202
- else if(isset($vars['pagename']) && !empty($vars['pagename'])){
1203
- $result = $wpdb->get_results($wpdb->prepare("SELECT ID, post_title FROM ".$wpdb->prefix."posts WHERE post_name = %s AND post_type = %s", get_subpage_name($vars['pagename']), 'page'));
1204
- if($result !== false && $wpdb->num_rows > 0){
1205
- return array('page_id' => $result[0]->ID, 'page_title' => $result[0]->post_title, 'post_type' => 'page');
1206
- }
1207
- }
1208
-
1209
- else if(isset($vars['page_id']) && !empty($vars['page_id'])){
1210
- $result = $wpdb->get_results($wpdb->prepare("SELECT post_title FROM ".$wpdb->prefix."posts WHERE ID = %s AND post_type = %s", $vars['page_id'], 'page'));
1211
- if($result !== false && $wpdb->num_rows > 0){
1212
- return array('page_id' => $page_id, 'page_title' => $result[0]->post_title, 'post_type' => 'page');
1213
- }
1214
- }
1215
-
1216
- else{
1217
- return array('page_id' => 'HOMEPAGE', 'page_title' => NULL, 'post_type' => NULL);
1218
- }
1219
  }
1220
 
1221
- function get_subpage_name($page_name) {
1222
- $sub_name = strrchr($page_name, '/');
1223
- if (!$sub_name) {
1224
- return $page_name;
1225
- }
1226
- return substr($sub_name,1);
1227
  }
 
1228
  //--------------------------------------------
1229
- /**
1230
- * Initiates tracking process
1231
- *
1232
- * @param object $query. this object is passed to this callback function of "parse_request" hooked action
1233
- * @return void
1234
- */
1235
- function ahc_track_visitor($query){
1236
- if(ahc_should_track_visitor() && !ahc_is_login_page() && !ahc_is_search_engine_bot() && !ahc_is_wordpress_bot()){
1237
- $page = ahc_detect_requested_page($query);
1238
- if(is_array($page)){
1239
- Globals::$page_id = $page['page_id'];
1240
- Globals::$page_title = $page['page_title'];
1241
- Globals::$post_type = $page['post_type'];
1242
- } else{
1243
- return;
1244
- }
1245
- $hitsCounter = new WPHitsCounter(Globals::$page_id, Globals::$page_title, Globals::$post_type);
1246
- $hitsCounter->traceVisitorHit();
1247
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1248
  }
 
 
 
1249
  //--------------------------------------------
1250
  /**
1251
  * Ceil for decimal numbers with precision
@@ -1255,20 +1841,22 @@ function ahc_track_visitor($query){
1255
  * @param string $separator
1256
  * @return float
1257
  */
1258
- function ceil_dec($number,$precision,$separator){
1259
- if(strpos($number, '.') !== false){
1260
- $numberpart=explode($separator,$number);
1261
- $numberpart[1]=substr_replace($numberpart[1],$separator,$precision,0);
1262
- if($numberpart[0]>=0)
1263
- {$numberpart[1]=ceil($numberpart[1]);}
1264
- else
1265
- {$numberpart[1]=floor($numberpart[1]);}
1266
-
1267
- $ceil_number= array($numberpart[0],$numberpart[1]);
1268
- return implode($separator,$ceil_number);
1269
- }
1270
- return $number;
 
1271
  }
 
1272
  //--------------------------------------------
1273
  /**
1274
  * Retrieve sum visits by post title
@@ -1278,42 +1866,43 @@ $numberpart[1]=substr_replace($numberpart[1],$separator,$precision,0);
1278
  *
1279
  * @return mixed
1280
  */
1281
- function ahc_get_traffic_by_title(){
1282
- global $wpdb;
1283
- $sql1 = "SELECT SUM(hits) AS sm FROM (
1284
  SELECT SUM(til_hits) AS hits
1285
  FROM ahc_title_traffic
1286
  GROUP BY til_page_id
1287
  ) myTable";
1288
-
1289
- $sql2 = "SELECT til_page_id, til_page_title, til_hits
1290
  FROM ahc_title_traffic
1291
  GROUP BY til_page_id
1292
  ORDER BY til_hits DESC
1293
  LIMIT %d OFFSET 0";
1294
-
1295
- $result1 = $wpdb->get_results($sql1);
1296
- if($result1 !== false){
1297
- $total = $result1[0]->sm;
1298
- $result2 = $wpdb->get_results($wpdb->prepare($sql2, AHC_TRAFFIC_BY_TITLE_LIMIT));
1299
- if($result2 !== false){
1300
- $arr = array();
1301
- if($wpdb->num_rows > 0){
1302
- $c = 0;
1303
- foreach($result2 as $r){
1304
- $arr[$c]['rank'] = $c + 1;
1305
- $arr[$c]['til_page_id'] = $r->til_page_id;
1306
- $arr[$c]['til_page_title'] = $r->til_page_title;
1307
- $arr[$c]['til_hits'] = $r->til_hits;
1308
- $arr[$c]['percent'] = ($total > 0)? ceil_dec((($r->til_hits / $total) * 100), 2, ".").' %' : 0;
1309
- $c++;
1310
- }
1311
- }
1312
- return $arr;
1313
- }
1314
- }
1315
- return false;
1316
  }
 
1317
  //--------------------------------------------
1318
  /**
1319
  * Retrieves sum of visits order by time
@@ -1322,71 +1911,147 @@ function ahc_get_traffic_by_title(){
1322
  *
1323
  * @return mixed
1324
  */
1325
- function ahc_get_time_visits(){
1326
- global $wpdb;
1327
- $sql1 = "SELECT SUM(vtm_visitors) AS sm FROM ahc_visits_time";
1328
- $sql2 = "SELECT vtm_time_from, vtm_time_to, vtm_visitors, vtm_visits
1329
- FROM ahc_visits_time";
1330
-
1331
- $result1 = $wpdb->get_results($sql1);
1332
- if($result1 !== false){
1333
- $total = $result1[0]->sm;
1334
- $result2 = $wpdb->get_results($sql2);
1335
- if($result2 !== false){
1336
- $arr = array();
1337
- $c = 0;
1338
- foreach($result2 as $r){
1339
- $timeFrom = $r->vtm_time_from;
1340
- $timeFrom = explode(':', $timeFrom);
1341
- $timeFrom = $timeFrom[0].':'.$timeFrom[1];
1342
- $timeTo = $r->vtm_time_to;
1343
- $timeTo = explode(':', $timeTo);
1344
- $timeTo = $timeTo[0].':'.$timeTo[1];
1345
-
1346
- $arr[$c]['vtm_time_from'] = $timeFrom;
1347
- $arr[$c]['vtm_time_to'] = $timeTo;
1348
- $arr[$c]['vtm_visitors'] = $r->vtm_visitors;
1349
- $arr[$c]['vtm_visits'] = $r->vtm_visits;
1350
- $arr[$c]['percent'] = ($total > 0)? ceil_dec((($r->vtm_visitors / $total) * 100), 2, ".") : 0;
1351
- $c++;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1352
  }
1353
- return $arr;
1354
- }
1355
- }
1356
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1357
  }
 
1358
  //--------------------------------------------
1359
  /**
1360
  * Returns client IP address
1361
  *
1362
  * @return string
1363
  */
1364
- function ahc_get_client_ip_address(){
1365
- global $_SERVER;
1366
- $ipAddress = '';
1367
- if(isset($_SERVER['HTTP_CLIENT_IP']) && !empty($_SERVER['HTTP_CLIENT_IP'])){
 
 
1368
  $ipAddress = $_SERVER['HTTP_CLIENT_IP'];
1369
- }
1370
- else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
1371
  $ipAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
1372
- }
1373
- else if(isset($_SERVER['HTTP_X_FORWARDED']) && !empty($_SERVER['HTTP_X_FORWARDED'])){
1374
  $ipAddress = $_SERVER['HTTP_X_FORWARDED'];
1375
- }
1376
- else if(isset($_SERVER['HTTP_FORWARDED_FOR']) && !empty($_SERVER['HTTP_FORWARDED_FOR'])){
1377
  $ipAddress = $_SERVER['HTTP_FORWARDED_FOR'];
1378
- }
1379
- else if(isset($_SERVER['HTTP_FORWARDED']) && !empty($_SERVER['HTTP_FORWARDED'])){
1380
  $ipAddress = $_SERVER['HTTP_FORWARDED'];
1381
- }
1382
- else if(isset($_SERVER['REMOTE_ADDR']) && !empty($_SERVER['REMOTE_ADDR'])){
1383
- $ipAddress = $_SERVER['REMOTE_ADDR'];
1384
- }
1385
- else{
1386
  $ipAddress = 'UNKNOWN';
1387
- }
1388
- return $ipAddress;
 
 
 
1389
  }
 
1390
  //--------------------------------------------
1391
  /**
1392
  * To include scripts and styles tags into the head
@@ -1398,117 +2063,501 @@ function ahc_get_client_ip_address(){
1398
  *
1399
  * @return void
1400
  */
1401
- function ahc_include_scripts(){
1402
- wp_register_style('ahc_lang_css', plugins_url('/css/en_newcss.css', AHC_PLUGIN_MAIN_FILE));
1403
- wp_enqueue_style('ahc_lang_css');
1404
-
1405
- wp_register_style('ahc_bootstrap_css', plugins_url('/lib/bootstrap/css/bootstrap.min.css', AHC_PLUGIN_MAIN_FILE));
1406
- wp_enqueue_style('ahc_bootstrap_css');
1407
-
1408
- wp_enqueue_script('jquery');
1409
-
1410
- wp_register_script('ahc_bootstrap_js', plugins_url('/lib/bootstrap/js/bootstrap.min.js', AHC_PLUGIN_MAIN_FILE));
1411
- wp_enqueue_script('ahc_bootstrap_js');
1412
-
1413
- wp_register_script('ahc_lang_js', plugins_url('/lang/js/'.Globals::$lang.'_lang.js', AHC_PLUGIN_MAIN_FILE));
1414
- wp_enqueue_script('ahc_lang_js');
1415
-
1416
- wp_register_script('ahc_main_js', plugins_url('/js/js.js', AHC_PLUGIN_MAIN_FILE));
1417
- wp_enqueue_script('ahc_main_js');
1418
-
1419
-
1420
- wp_register_script('ahc_Chart_js', plugins_url('/lib/Chart_js/Chart.min.js', AHC_PLUGIN_MAIN_FILE));
1421
- wp_enqueue_script('ahc_Chart_js');
1422
-
1423
- wp_register_script('ahc_google_maps', 'http://maps.googleapis.com/maps/api/js?key=AIzaSyB0fRgC_3Wmp1PY5ZsuzK8VEooiUvVQq3Q&sensor=false');
1424
- wp_enqueue_script('ahc_google_maps');
1425
-
1426
 
1427
 
1428
- }
1429
- //--------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1430
 
 
 
1431
 
 
 
1432
 
 
 
 
 
 
 
 
 
 
 
 
 
1433
  //---------------------------------------------Add button to the admin bar
1434
- function vtrts_add_items($admin_bar)
1435
- {
1436
- global $pluginsurl;
1437
 
1438
- $wccpadminurl = get_admin_url();
1439
  //The properties of the new item. Read More about the missing 'parent' parameter below
1440
  $args = array(
1441
- 'id' => 'visitorstraffic',
1442
- 'title' => __('<img src="'.plugins_url('/images/vtrtspro.png', AHC_PLUGIN_MAIN_FILE).'" style="vertical-align:middle;margin-right:5px;" alt="visitors traffic" title="visitors traffic" />' ),
1443
- 'href' => $wccpadminurl.'admin.php?page=ahc_hits_counter_menu',
1444
- 'meta' => array('title' => __('Visitors Traffic Real Time Statistics'),)
1445
- );
1446
-
1447
  //This is where the magic works.
1448
- $admin_bar->add_menu( $args);
1449
  }
 
1450
  //---------------------------------------- Add plugin settings link to Plugins page
1451
- function vtrtsp_plugin_add_settings_link( $links ) {
1452
- $settings_link = '<a href="admin.php?page=ahc_hits_counter_menu">' . __( 'visitors traffic' ) . '</a>';
1453
- array_push( $links, $settings_link );
1454
- return $links;
1455
  }
 
1456
  //------------------------------------------------------------------------
 
 
 
1457
 
 
 
 
 
 
 
 
 
 
 
1458
 
1459
- function ahc_HideMessageAjaxFunction()
1460
- {
1461
- add_option( 'ahc_upgrade_message','yes');
1462
- }
 
 
 
 
1463
 
1464
 
1465
- function ahc_after_plugin_row($plugin_file, $plugin_data, $status) {
1466
-
1467
- if(get_option('ahc_upgrade_message') !='yes')
1468
- {
1469
- $class_name = $plugin_data['slug'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1470
 
1471
- echo '<tr id="' .$class_name. '-plugin-update-tr" class="plugin-update-tr active">';
1472
- echo '<td colspan="3" class="plugin-update">';
1473
- echo '<div id="' .$class_name. '-upgradeMsg" class="update-message" style="background:#FFFF99" >';
1474
-
1475
- echo 'You are running visitors traffic real time statistics LITE. To get more features, you can <a href="http://www.wp-buy.com/product/visitors-traffic-real-time-statistics-pro" target="_blank"><strong>upgrade now</strong></a> or ';
1476
-
1477
- echo '<span id="HideMe" style="cursor:pointer" ><a href="javascript:void(0)"><strong>dismiss</strong></a> this message</span>';
1478
- echo '</div>';
1479
- echo '</td>';
1480
- echo '</tr>';
1481
-
1482
- ?>
1483
-
1484
- <script type="text/javascript">
1485
- jQuery(document).ready(function() {
1486
- var row = jQuery('#<?php echo $class_name;?>-plugin-update-tr').closest('tr').prev();
1487
- jQuery(row).addClass('update');
1488
-
1489
-
1490
- jQuery("#HideMe").click(function(){
1491
- jQuery.ajax({
1492
- type: 'POST',
1493
- url: '<?php echo admin_url();?>/admin-ajax.php',
1494
- data: {
1495
- action: 'ahc_HideMessageAjaxFunction'
1496
- },
1497
- success: function(data, textStatus, XMLHttpRequest){
1498
-
1499
- jQuery("#<?php echo $class_name;?>-upgradeMsg").hide();
1500
-
1501
- },
1502
- error: function(MLHttpRequest, textStatus, errorThrown){
1503
- alert(errorThrown);
1504
- }
1505
- });
1506
- });
1507
-
1508
- });
1509
- </script>
1510
-
1511
- <?php
1512
  }
1513
- }
1514
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  *
9
  * @return void
10
  */
11
+ function ahcfree_getVisitsTime() {
12
+ global $wpdb;
13
+ $result = $wpdb->get_results("SELECT COUNT( `vtm_id` ) cnt FROM ahc_visits_time", OBJECT);
14
+ if ($result !== false) {
15
+ return $result[0]->cnt;
16
+ }
17
+ return false;
18
+ }
19
 
20
+
21
+
22
+ /**
23
+ * change plugin settings
24
+ * @return void
25
+ */
26
+ function ahcfree_savesettings() {
27
+ global $wpdb;
28
+
29
+ $set_hits_days = intval($_POST['set_hits_days']);
30
+ $set_ajax_check = 15;
31
+ $posts_type = '';
32
+ $set_ips = esc_html($_POST['set_ips']);
33
+ $set_google_map = '';
34
+ $delete_plugin_data = isset($_POST['delete_plugin_data']) ? intval($_POST['delete_plugin_data']) : '';
35
+
36
+ $custom_timezone_offset = sanitize_text_field($_POST['set_custom_timezone']);
37
+ if ($custom_timezone_offset && $custom_timezone_offset != '') {
38
+ update_option('ahcfree_custom_timezone', $custom_timezone_offset);
39
+ }
40
+
41
+ $delete_plugin_data = (isset($delete_plugin_data)) ? intval($delete_plugin_data) : 0;
42
+ update_option('ahcfree_delete_plugin_data_on_uninstall', $delete_plugin_data);
 
 
 
 
 
 
 
 
 
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
+ $ahcUserRoles = '';
46
+ foreach ($_POST['ahcUserRoles'] as $v)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  {
48
+ $ahcUserRoles .= $v.",";
49
  }
50
 
 
 
 
 
51
 
 
 
 
 
52
 
53
+ $wsmUserRoles = substr($ahcUserRoles,0,-1);
54
 
55
+ update_option('ahcUserRoles',$ahcUserRoles);
56
 
57
+
58
+
59
+
60
+ $sql = $wpdb->prepare("UPDATE `ahc_settings` set `set_hits_days` = %s, `set_ajax_check` = %s, `set_ips` = %s, `set_google_map` = %s ", $set_hits_days, $set_ajax_check, $set_ips, $set_google_map);
61
+
62
+ if ($wpdb->query($sql) !== false) {
63
+
64
+ return true;
65
+ }
66
+
67
+ return false;
68
  }
69
 
70
+
71
+
72
+
73
+
74
+ function ahcfree_get_save_settings() {
75
  global $wpdb;
76
+ $table_exist = ahcfree_check_table_exists('ahc_settings');
77
+ if( $table_exist ){
78
+ $result = $wpdb->get_results("SELECT set_hits_days, set_ajax_check, set_ips, set_google_map FROM ahc_settings", OBJECT);
79
+ if ($result !== false) {
80
+ return $result;
81
+ }
82
+ }
 
83
 
84
+ return false;
85
+ }
86
+
87
+ function ahcfree_get_timezone_string() {
88
+ $custom_timezone = get_option('ahcfree_custom_timezone');
89
+ if (!$custom_timezone) {
90
+ $wsmTimeZone=get_option('timezone_string' );
91
+ if(is_null($wsmTimeZone) || $wsmTimeZone==''){
92
+ $wsmTimeZone=ahcfree_GetWPTimezoneString();
93
+ }
94
+ $custom_timezone= ahcfree_CleanupTimeZoneString($wsmTimeZone);
95
+
96
+ /*
97
+ $custom_timezone = get_option( 'timezone_string' );
98
+
99
+ if ( ! empty( $custom_timezone ) ) {
100
+ return $custom_timezone;
101
  }
102
+
103
+ $offset = get_option( 'gmt_offset' );
104
+ $hours = (int) $offset;
105
+ $minutes = ( $offset - floor( $offset ) ) * 60;
106
+ if( $hours < 10 ){
107
+ $hours = '0'+$hours;
108
+ }
109
+ echo $custom_timezone = sprintf( '%s:%s', $hours, $minutes );*/
110
+
111
+ }
112
+ return $custom_timezone;
113
+ }
114
+
115
+
116
+ function ahcfree_CleanupTimeZoneString($tzString){
117
+ $offset=$tzString;
118
+
119
+ if (preg_match('/^UTC[+-]/', $tzString)) {
120
+ $tzString= preg_replace('/UTC\+?/', '', $tzString);
121
+ }
122
+ if(is_numeric($tzString)){
123
+ $offset=sprintf('%02d:%02d', (int) $tzString, fmod(abs($tzString), 1) * 60);
124
+ if((int) $tzString>0){
125
+ $offset='+'.$offset;
126
  }
 
127
  }
128
+ return $offset;
129
+ }
130
+ function ahcfree_GetWPTimezoneString() {
131
+ // if site timezone string exists, return it
132
+ if ( $timezone = get_option( 'timezone_string' ) )
133
+ return $timezone;
134
+
135
+ // get UTC offset, if it isn't set then return UTC
136
+ if ( 0 === ( $utc_offset = get_option( 'gmt_offset', 0 ) ) )
137
+ return 'UTC';
138
+
139
+ // adjust UTC offset from hours to seconds
140
+ $utc_offset *= 3600;
141
+
142
+ // attempt to guess the timezone string from the UTC offset
143
+ if ( $timezone = timezone_name_from_abbr( '', $utc_offset, 0 ) ) {
144
+ return $timezone;
145
+ }
146
+
147
+ // last try, guess timezone string manually
148
+ $is_dst = date( 'I' );
149
+
150
+ foreach ( timezone_abbreviations_list() as $abbr ) {
151
+ foreach ( $abbr as $city ) {
152
+ if ( $city['dst'] == $is_dst && $city['offset'] == $utc_offset )
153
+ return $city['timezone_id'];
154
+ }
155
+ }
156
+
157
+ // fallback to UTC
158
+ return 'UTC';
159
+ }
160
+
161
+ function ahcfree_get_current_timezone_offset() {
162
+ $tz = ahcfree_get_timezone_string();
163
+ try {
164
+ $timeZone = new DateTimeZone($tz);
165
+ $date = new DateTime('now', $timeZone);
166
+ $date->setTimezone($timeZone);
167
+ } catch (Exception $e) {
168
+ $date = new DateTime('now');
169
+ }
170
+ return '+00:00';
171
+ // return $date->format('P');
172
  }
173
 
174
+ function ahcfree_last_hit_date() {
175
  global $wpdb;
176
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
177
+ $sql = "SELECT max(CONVERT_TZ(vtr_date,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) as last_date FROM ahc_recent_visitors";
178
+ //echo $sql = "SELECT max(vtr_date)) as last_date FROM ahc_recent_visitors";
179
+ $result = $wpdb->get_results($sql, OBJECT);
180
+ if ($result !== false) {
181
+ return $result[0]->last_date;
182
+ }
183
+ return date('Y-m-d', time());
184
+ }
185
+
186
+ function ahcfree_getCountriesCount() {
187
+ global $wpdb;
188
+ $result = $wpdb->get_results("SELECT COUNT( `ctr_id` ) cnt FROM ahc_countries", OBJECT);
189
+ if ($result !== false) {
190
+ return $result[0]->cnt;
191
+ }
192
+ return false;
193
+ }
194
+
195
+ function ahcfree_getBrowsersCount() {
196
+ global $wpdb;
197
+ $result = $wpdb->get_results("SELECT COUNT( `bsr_id` ) cnt FROM ahc_browsers", OBJECT);
198
+ if ($result !== false) {
199
+ return $result[0]->cnt;
200
+ }
201
+ return false;
202
+ }
203
+
204
+ function ahcfree_getSearchEnginesCount() {
205
+ global $wpdb;
206
+ $result = $wpdb->get_results("SELECT COUNT( `srh_id` ) cnt FROM ahc_search_engines", OBJECT);
207
+ if ($result !== false) {
208
+ return $result[0]->cnt;
209
+ }
210
+ return false;
211
+ }
212
+
213
+ function ahcfree_set_default_options() {
214
+ // plugin activation
215
+
216
+ require_once("database_basics_data.php");
217
+ if (get_option('ahcfree_wp_hits_counter_options') === false) {
218
+
219
+
220
+ $plugin_options = array();
221
+ $plugin_options['ahcfree_version'] = '1.0';
222
+ $plugin_options['available_languages'] = array('ar' => 'عربي', 'en' => 'English');
223
+ $plugin_options['ahcfree_lang'] = 'en';
224
+ $plugin_options['user_roles_to_not_track'] = array('administrator' => true, 'editor' => true, 'author' => true, 'contributor' => true, 'subscriber' => false);
225
+ add_option('ahcfree_wp_hits_counter_options', $plugin_options);
226
+ }
227
+ set_time_limit(300);
228
+ if (ahcfree_create_database_tables()) {
229
+
230
+ if (ahcfree_getVisitsTime() > 25) {
231
+ global $wpdb;
232
+ $result = $wpdb->get_results("DELETE FROM ahc_visits_time where `vtm_id` > 24", OBJECT);
233
  }
234
+
235
+ if (ahcfree_getCountriesCount() == 0) {
236
+ ahcfree_insert_countries_into_table($internetCountryCodes, $contriesLatLng);
237
+ }
238
+
239
+ if (ahcfree_getVisitsTime() == 0) {
240
+ ahcfree_insert_visit_times_into_table($dayHours);
241
+ }
242
+
243
+ if (ahcfree_getSearchEnginesCount() == 0) {
244
+ ahcfree_insert_search_engines_into_table($searchEngines);
245
+ }
246
+
247
+ if (ahcfree_getBrowsersCount() == 0) {
248
+ ahcfree_insert_browsers_into_table($browsers);
249
  }
 
250
  }
 
 
251
 
252
 
253
+ ahcfree_update_tables();
254
+ }
255
+
256
  //--------------------------------------------
257
  /**
258
  * Called when plugin is deactivated
259
  *
260
  * @return void
261
  */
262
+ function ahcfree_unset_default_options() {
263
+
264
  }
265
+
266
  //--------------------------------------------
267
  /**
268
  * Creates plugin page link in the admin menu
272
  *
273
  * @return void
274
  */
275
+ function ahcfree_create_admin_menu_link() {
276
+
277
+ global $current_user;
278
+ $ahcUserRole = explode(',',get_option('ahcUserRoles'));
279
+
280
+ $roles_arr = array();
281
+
282
+ foreach($ahcUserRole as $v) {
283
+ $roles_arr[] = strtolower($v);
284
+ }
285
+
286
+ if (! in_array( strtolower($current_user->roles[0]), $roles_arr ) && !(current_user_can('manage_options'))) {
287
+
288
+ return;
289
+ }
290
+
291
+ add_menu_page('Visitor Traffic Real Time Statistics', 'Visitor Traffic', 'manage_categories', 'ahc_hits_counter_menu_free', 'ahcfree_create_plugin_overview_page', plugins_url('/images/vtrts.png', AHCFREE_PLUGIN_MAIN_FILE));
292
+ add_submenu_page('ahc_hits_counter_menu_free', 'Visitor Traffic Real Time Statistics Settings', 'Settings', 'manage_categories', 'ahc_hits_counter_settings', 'ahcfree_create_plugin_settings_page');
293
+ $ahcfree_custom_timezone = get_option( 'ahcfree_custom_timezone', false );
294
+ if( !$ahcfree_custom_timezone ){
295
+ add_action('admin_notices', 'ahcfree_admin_notice_to_set_timezone');
296
+ }
297
+ $page = isset($_GET['page']) ? ahcfree_sanitizing($_GET['page']) : '';
298
+
299
+ if( $page == 'ahc_hits_counter_settings' ){
300
+ remove_action('admin_notices', 'ahcfree_admin_notice_to_set_timezone');
301
+ }
302
+ }
303
+
304
+ //--------------------------------------------
305
+ /**
306
+ * Format numbers
307
+ *
308
+ * @return number
309
+ */
310
+ function ahcfree_free_NumFormat($num) {
311
+ if ($num > 1000) {
312
+ return number_format($num, 0, ',', ',');
313
+ } else {
314
+ return $num;
315
+ }
316
+ }
317
+
318
+ //------
319
+ function ahcfree_countOnlineusers() {
320
+ global $wpdb;
321
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
322
+
323
+ $sql = "SELECT id FROM ahc_online_users WHERE `date` >= '". date("Y-m-d H:i:s", strtotime('-1 minute') ) ."' GROUP BY hit_ip_address";
324
+ $result = $wpdb->get_results($sql, OBJECT);
325
+ $online_users = "0";
326
+ if ($result !== false) {
327
+ $online_users = count($result);
328
+ //return $result[0]->onlineusers;
329
+ //echo json_encode($result[0]->onlineusers);
330
+ }
331
+ if( is_admin() ){
332
+ echo json_encode($online_users);
333
+ die;
334
+ }else{
335
+ return $online_users;
336
+ }
337
+
338
+ //return '0';
339
+
340
+ }
341
+
342
+ function ahcfree_init()
343
+ {
344
+
345
+ add_action('wp_ajax_ahcfree_track_visitor','ahcfree_track_visitor');
346
+ add_action('wp_ajax_nopriv_ahcfree_track_visitor','ahcfree_track_visitor');
347
+ }
348
+ add_action('admin_init','ahcfree_init');
349
+
350
+ function ahcfree_enqueue_scripts()
351
+ {
352
+ global $post, $wp_query;
353
+ $post_id = "HOMEPAGE";
354
+ $page_title = '';
355
+ $post_type = '';
356
+ if(is_singular() || is_page() )
357
+ {
358
+ $post_id = $post->ID;
359
+ $page_title = get_the_title($post->ID);
360
+ $post_type = get_post_type($post->ID);
361
+ }
362
+ if ( is_home() ) {
363
+ $post_id = "BLOGPAGE";
364
+ }
365
+ if( is_archive() ){
366
+ $post_id = get_the_archive_title();
367
+ }
368
+
369
+
370
+ wp_register_script('ahcfree_front_js', plugins_url('/js/front.js', AHCFREE_PLUGIN_MAIN_FILE),'jquery', '', false);
371
+ wp_enqueue_script('ahcfree_front_js');
372
+
373
+ wp_localize_script('ahcfree_front_js', 'ahcfree_ajax_front', array('ajax_url' => admin_url('admin-ajax.php'),
374
+ 'page_id' => $post_id,
375
+ 'page_title'=> $page_title,
376
+ 'post_type'=> $post_type
377
+ ));
378
  }
379
+ add_action('wp_enqueue_scripts','ahcfree_enqueue_scripts', 1);
380
  //--------------------------------------------
381
  /**
382
  * Creates the main overview page
383
  *
384
  * @return void
385
  */
386
+ function ahcfree_create_plugin_overview_page() {
387
+ require_once(AHCFREE_PLUGIN_ROOT_DIR . AHCFREE_DS . 'lang' . AHCFREE_DS . Globalsahcfree::$lang . '_lang.php');
388
+ include("overview.php");
389
+ }
390
+
391
+ //--------------------------------------------
392
+ /**
393
+ * Creates the plugin settings
394
+ *
395
+ * @return void
396
+ */
397
+ function ahcfree_create_plugin_settings_page() {
398
+
399
+ require_once(AHCFREE_PLUGIN_ROOT_DIR . AHCFREE_DS . 'lang' . AHCFREE_DS . Globalsahcfree::$lang . '_lang.php');
400
+ include("ahc_settings.php");
401
+ }
402
+
403
+ //--------------------------------------------
404
+ /**
405
+ * Creates the plugin help page
406
+ *
407
+ * @return void
408
+ */
409
+ function ahcfree_create_plugin_help_page() {
410
+
411
+ require_once(AHCFREE_PLUGIN_ROOT_DIR . AHCFREE_DS . 'lang' . AHCFREE_DS . Globalsahcfree::$lang . '_lang.php');
412
+ include("ahcfree_help.php");
413
+ }
414
+
415
+ //--------------------------------------------
416
+ /**
417
+ * Creates the plugin help page
418
+ *
419
+ * @return void
420
+ */
421
+ function ahcfree_create_plugin_about_page() {
422
+
423
+ require_once(AHCFREE_PLUGIN_ROOT_DIR . AHCFREE_DS . 'lang' . AHCFREE_DS . Globalsahcfree::$lang . '_lang.php');
424
+ include("ahcfree_about.php");
425
  }
426
+
427
  //--------------------------------------------
428
  /**
429
  * Returns links array of available languages
433
  *
434
  * @return array
435
  */
436
+ function ahcfree_get_change_lang_links() {
437
+ $plugin_options = get_option('ahcfree_wp_hits_counter_options');
438
+ $links = array();
439
+ $i = 0;
440
+ foreach ($plugin_options['available_languages'] as $key => $value) {
441
+ if (Globalsahcfree::$lang != $key) {
442
+ $links[$i]['name'] = $value;
443
+ $links[$i]['href'] = add_query_arg('ahcfree_lang', $key);
444
+ $i++;
445
+ }
446
+ }
447
+ unset($plugin_options);
448
+ unset($i);
449
+ return $links;
450
  }
451
+
452
  //--------------------------------------------
453
  /**
454
  * Decides whether or not should track the current visitor
458
  *
459
  * @return boolean
460
  */
461
+ function ahcfree_should_track_visitor() {
462
+ global $current_user;
463
+ $allow = true;
464
+ if (is_user_logged_in()) {
465
+ $user = new WP_User($current_user->ID);
466
+ if (!empty($user->roles) && is_array($user->roles)) {
467
+ foreach ($user->roles as $role) {
468
+ $found = (isset(Globalsahcfree::$plugin_options['user_roles_to_not_track'][$role])) ? Globalsahcfree::$plugin_options['user_roles_to_not_track'][$role] : false;
469
+ if ($found) {
470
+ $allow = false;
471
+ break;
472
+ }
473
+ }
474
+ }
475
+ }
476
+ return $allow;
477
  }
478
+
479
  //--------------------------------------------
480
  /**
481
  * Returns true if the current user has administrator role
485
  *
486
  * @return boolean
487
  */
488
+ function ahcfree_has_administrator_role() {
489
+ global $user_ID;
490
+ $is_admin = false;
491
+ if (is_user_logged_in()) {
492
+ $user = new WP_User($user_ID);
493
+ if (!empty($user->roles) && is_array($user->roles)) {
494
+ foreach ($user->roles as $role) {
495
+ if ($role == 'administrator') {
496
+ $is_admin = true;
497
+ break;
498
+ }
499
+ }
500
+ }
501
+ }
502
+ return $is_admin;
503
  }
504
+
505
  //--------------------------------------------
506
  /**
507
+ * Check if column exist or not
508
  *
509
  * @uses wpdb::query()
510
  *
511
  * @return boolean
512
  */
513
+ function ahcfree_check_table_column_exists($table_name, $column_name) {
514
+ global $wpdb;
515
+ $column = $wpdb->get_row($wpdb->prepare("SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s ", DB_NAME, $table_name, $column_name));
516
+
517
+ if (!empty($column)) {
518
+ return true;
519
+ }
520
+ return false;
521
+ }
522
+
523
+ //--------------------------------------------
524
+ /**
525
+ * Check if Table exist or not
526
+ *
527
+ * @uses wpdb::query()
528
+ *
529
+ * @return boolean
530
+ */
531
+ function ahcfree_check_table_exists($table_name) {
532
+ global $wpdb;
533
+ $table_data = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s", DB_NAME, $table_name));
534
+
535
+ if (!empty($table_data)) {
536
+ return true;
537
+ }
538
+ return false;
539
+ }
540
+
541
+
542
+ //--------------------------------------------
543
+ /**
544
+ * Creates database updates plugin tables
545
+ *
546
+ * @uses wpdb::query()
547
+ *
548
+ * @return boolean
549
+ */
550
+ function ahcfree_update_tables() {
551
+ global $wpdb;
552
+ $sqlQueries = array();
553
+
554
+ $sqlQueries[] = " drop table IF EXISTS `ahc_settings` ";
555
+ $sqlQueries[] = "
556
+ CREATE TABLE IF NOT EXISTS `ahc_settings` (
557
+ `set_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
558
+ `set_hits_days` int(10) unsigned NOT NULL DEFAULT '30',
559
+ `set_ajax_check` int(10) unsigned NOT NULL DEFAULT '10',
560
+ `set_ips` text DEFAULT NULL,
561
+ `set_google_map` varchar(100) NOT NULL DEFAULT 'today_visitors',
562
+
563
+ PRIMARY KEY (`set_id`)
564
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
565
+
566
+ //$sqlQueries[] = "alter table `ahc_recent_visitors` add COLUMN `ahc_city` varchar(230) NULL";
567
+ //$sqlQueries[] = "alter table `ahc_recent_visitors` add COLUMN `ahc_region` varchar(230) NULL";
568
+
569
+ /* code for error handling : "duplicate column name" : Taslim -Prism */
570
+ if ( ahcfree_check_table_exists('ahc_recent_visitors') === true && ahcfree_check_table_column_exists('ahc_recent_visitors', 'ahc_city') === false ) {
571
+ $sqlQueries[] = "alter table `ahc_recent_visitors` add COLUMN `ahc_city` varchar(230) NULL";
572
+ }
573
+
574
+ if ( ahcfree_check_table_exists('ahc_recent_visitors') === true && ahcfree_check_table_column_exists('ahc_recent_visitors', 'ahc_region') === false ) {
575
+ $sqlQueries[] = "alter table `ahc_recent_visitors` add COLUMN `ahc_region` varchar(230) NULL";
576
+ }
577
+
578
+ foreach ($sqlQueries as $sql) {
579
+ if ($wpdb->query($sql) === false) {
580
+ return false;
581
+ }
582
+ }
583
+
584
+
585
+ return true;
586
+ }
587
+
588
+ function ahcfix_init(){
589
  global $wpdb;
590
  $sqlQueries = array();
591
+ if ( ahcfree_check_table_exists('ahc_visitors') === true && ahcfree_check_table_column_exists('ahc_visitors', 'vst_date') ) {
592
+ $sqlQueries[] = "ALTER TABLE `ahc_visitors` CHANGE `vst_date` `vst_date` DATETIME NOT NULL";
593
+ }
594
+
595
+ if ( ahcfree_check_table_exists('ahc_searching_visits') === true && ahcfree_check_table_column_exists('ahc_searching_visits', 'vtsh_date') ) {
596
+ $sqlQueries[] = "ALTER TABLE `ahc_searching_visits` CHANGE `vtsh_date` `vtsh_date` DATETIME NOT NULL";
597
+ }
598
+
599
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_online_users`
600
  (
601
+ `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
602
+ PRIMARY KEY(`id`),
603
  `hit_ip_address` VARCHAR(50) NOT NULL,
 
 
604
  `hit_page_id` VARCHAR(30) NOT NULL,
605
+ `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
606
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
607
 
608
+
609
+ if( count($sqlQueries) ){
610
+ foreach ($sqlQueries as $sql) {
611
+ $wpdb->query($sql);
612
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
613
  }
 
614
  }
 
615
 
616
+ function ahcfree_add_settings() {
617
 
618
+ global $wpdb;
619
+ ahcfree_update_tables();
620
 
621
+ $sql1 = "truncate table `ahc_settings`";
622
+ $wpdb->query($sql1);
623
+
624
+ $sql = "insert into `ahc_settings` (set_id, set_hits_days, set_ajax_check, set_ips, set_google_map) values (1, 14, 15, null, 'today_visitors')";
625
+
626
+
627
+ if ($wpdb->query($sql) === false) {
628
+ return false;
629
+ }
630
+ return true;
631
+ }
632
+
633
+ //--------------------------------------------
634
+ /**
635
+ * Creates database plugin tables
636
+ *
637
+ * @uses wpdb::query()
638
+ *
639
+ * @return boolean
640
+ */
641
+ function ahcfree_create_database_tables() {
642
+ global $wpdb;
643
+ $sqlQueries = array();
644
+
645
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_online_users`
646
+ (
647
+ `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
648
+ PRIMARY KEY(`id`),
649
+ `hit_ip_address` VARCHAR(50) NOT NULL,
650
+ `hit_page_id` VARCHAR(30) NOT NULL,
651
+ `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
652
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
653
+
654
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_hits`
655
  (
656
  `hit_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
657
  PRIMARY KEY(`hit_id`),
669
  `hit_date` DATE NOT NULL,
670
  `hit_time` TIME NOT NULL
671
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
672
+
673
+
674
+ $sqlQueries[] = "
675
+ CREATE TABLE IF NOT EXISTS `ahc_settings` (
676
+ `set_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
677
+ `set_hits_days` int(10) unsigned NOT NULL DEFAULT '30',
678
+ `set_ajax_check` int(10) unsigned NOT NULL DEFAULT '10',
679
+ `set_ips` text DEFAULT NULL,
680
+ `set_google_map` varchar(100) NOT NULL DEFAULT 'today_visitors',
681
+
682
+ PRIMARY KEY (`set_id`)
683
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
684
+
685
+
686
+
687
+
688
+
689
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_browsers`
690
  (
691
  `bsr_id` INT(3) UNSIGNED NOT NULL,
692
  PRIMARY KEY(`bsr_id`),
694
  `bsr_icon` VARCHAR(50),
695
  `bsr_visits` INT(11) NOT NULL DEFAULT 0
696
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
697
+
698
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_search_engines`
699
  (
700
  `srh_id` INT(3) UNSIGNED NOT NULL AUTO_INCREMENT,
701
  PRIMARY KEY(`srh_id`),
704
  `srh_icon` VARCHAR(50),
705
  `srh_identifier` VARCHAR(50)
706
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
707
+
708
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_search_engine_crawlers`
709
  (
710
  `bot_name` VARCHAR(50) NOT NULL,
711
  `srh_id` INT(3) UNSIGNED NOT NULL
712
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
713
+
714
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_countries`
715
  (
716
  `ctr_id` INT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
717
  PRIMARY KEY(`ctr_id`),
722
  `ctr_visitors` INT(11) NOT NULL DEFAULT 0,
723
  `ctr_visits` INT(11) NOT NULL DEFAULT 0
724
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
725
+
726
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_visitors`
727
  (
728
  `vst_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
729
  PRIMARY KEY (`vst_id`),
731
  `vst_visitors` INT(11) UNSIGNED NULL DEFAULT 0,
732
  `vst_visits` INT(11) UNSIGNED NULL DEFAULT 0
733
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
734
+
735
+ $sqlQueries[] = "ALTER TABLE `ahc_visitors` CHANGE `vst_date` `vst_date` DATETIME NOT NULL";
736
+
737
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_daily_visitors_stats`
738
+ (
739
+ `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
740
+ PRIMARY KEY (`id`),
741
+ `vst_date` DATETIME NOT NULL,
742
+ `vst_visitors` INT(11) UNSIGNED NULL DEFAULT 0,
743
+ `vst_visits` INT(11) UNSIGNED NULL DEFAULT 0
744
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
745
+
746
+
747
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_searching_visits`
748
  (
749
  `vtsh_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
750
  PRIMARY KEY (`vtsh_id`),
752
  `vtsh_date` DATE NOT NULL,
753
  `vtsh_visits` INT(11) UNSIGNED NOT NULL DEFAULT 0
754
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
755
+
756
+ $sqlQueries[] = "ALTER TABLE `ahc_searching_visits` CHANGE `vtsh_date` `vtsh_date` DATETIME NOT NULL";
757
+
758
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_refering_sites`
759
  (
760
  `rfr_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
761
  PRIMARY KEY (`rfr_id`),
762
  `rfr_site_name` VARCHAR(100) NOT NULL,
763
  `rfr_visits` INT(11) UNSIGNED NULL DEFAULT 0
764
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
765
+
766
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_recent_visitors`
767
  (
768
  `vtr_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
769
  PRIMARY KEY (`vtr_id`),
775
  `vtr_date` DATE NOT NULL,
776
  `vtr_time` TIME NOT NULL
777
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
778
+
779
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_keywords`
780
  (
781
  `kwd_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
782
  PRIMARY KEY (`kwd_id`),
789
  `kwd_date` DATE NOT NULL,
790
  `kwd_time` TIME NOT NULL
791
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
792
+
793
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_title_traffic`
794
  (
795
  `til_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
796
  PRIMARY KEY (`til_id`),
798
  `til_page_title` VARCHAR(100),
799
  `til_hits` INT(11) UNSIGNED NOT NULL
800
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
801
+
802
+ $sqlQueries[] = "CREATE TABLE IF NOT EXISTS `ahc_visits_time`
803
  (
804
  `vtm_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
805
  PRIMARY KEY (`vtm_id`),
808
  `vtm_visitors` INT(11) UNSIGNED NOT NULL DEFAULT 0,
809
  `vtm_visits` INT(11) UNSIGNED NOT NULL DEFAULT 0
810
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8";
811
+
812
+
813
+ /* $sqlQueries[] = "alter table `ahc_recent_visitors` add COLUMN `ahc_city` varchar(230) NULL";
814
+
815
+ $sqlQueries[] = "alter table `ahc_recent_visitors` add COLUMN `ahc_region` varchar(230) NULL";
816
+ */
817
+
818
+
819
+ foreach ($sqlQueries as $sql) {
820
+ if ($wpdb->query($sql) === false) {
821
+ return false;
822
+ }
823
+ }
824
+ return true;
825
  }
826
+
827
  //--------------------------------------------
828
  /**
829
+ * Inserts countries into ahcfree_countroes table
830
  *
831
  * @uses wpdb::insert()
 
832
  *
833
+ * @param array $internetCountryCodes. internet codes and names of countries
834
+ * @param array $contriesLatLng. LatLng of countries
835
  * @return boolean
836
  */
837
+ function ahcfree_insert_countries_into_table($internetCountryCodes, $contriesLatLng) {
838
+ global $wpdb;
839
+ $c = 1;
840
+ $length = count($internetCountryCodes);
841
+ foreach ($internetCountryCodes as $internetCode => $countryName) {
842
+ $ctr_latitude = $ctr_longitude = NULL;
843
+ if (isset($contriesLatLng[$internetCode])) {
844
+ $ctr_latitude = $contriesLatLng[$internetCode][0];
845
+ $ctr_longitude = $contriesLatLng[$internetCode][1];
846
+ }
847
+ $result = $wpdb->insert('ahc_countries', array(
848
+ 'ctr_name' => $countryName,
849
+ 'ctr_internet_code' => $internetCode,
850
+ 'ctr_latitude' => $ctr_latitude,
851
+ 'ctr_longitude' => $ctr_longitude
852
+ ), array(
853
+ '%s', '%s', '%s', '%s'
854
+ )
855
+ );
856
+ if ($result === false) {
857
+ return false;
858
+ }
859
+ }
860
+ return true;
 
 
 
 
 
 
 
 
 
861
  }
862
+
863
  //--------------------------------------------
864
  /**
865
+ * Inserts search engines into ahc_search_engines table
866
  *
867
  * @uses wpdb::insert()
868
+ * @uses wpdb::$insert_id
869
  *
870
+ * @param array $searchEngines.
871
  * @return boolean
872
  */
873
+ function ahcfree_insert_search_engines_into_table($searchEngines) {
874
+ global $wpdb;
875
+ foreach ($searchEngines as $se) {
876
+ $result = $wpdb->insert('ahc_search_engines', array(
877
+ 'srh_name' => $se['srh_name'],
878
+ 'srh_query_parameter' => $se['srh_query_parameter'],
879
+ 'srh_icon' => $se['srh_icon'],
880
+ 'srh_identifier' => $se['srh_identifier']
881
+ ), array(
882
+ '%s', '%s', '%s', '%s'
883
+ )
884
+ );
885
+ if ($result !== false) {
886
+ $srh_id = $wpdb->insert_id;
887
+ foreach ($se['crawlers'] as $crawler) {
888
+ $result2 = $wpdb->insert('ahc_search_engine_crawlers', array(
889
+ 'bot_name' => $crawler,
890
+ 'srh_id' => $srh_id
891
+ ), array(
892
+ '%s', '%d'
893
+ )
894
+ );
895
+ if ($result2 === false) {
896
+ return false;
897
+ }
898
+ }
899
+ } else {
900
+ return false;
901
+ }
902
+ }
903
+ return true;
904
  }
905
 
906
+ //--------------------------------------------
907
  /**
908
+ * Inserts browsers into ahc_browsers table
909
  *
910
  * @uses wpdb::insert()
911
  *
912
+ * @param array $browsers
 
913
  * @return boolean
914
  */
915
+ function ahcfree_insert_browsers_into_table($browsers) {
916
+ global $wpdb;
917
+ foreach ($browsers as $browser) {
918
+ $result = $wpdb->insert('ahc_browsers', array(
919
+ 'bsr_id' => $browser['bsr_id'],
920
+ 'bsr_name' => $browser['bsr_name'],
921
+ 'bsr_icon' => $browser['bsr_icon']
922
+ ), array(
923
+ '%d', '%s', '%s'
924
+ )
925
+ );
926
+ if ($result === false) {
927
+ return false;
928
+ }
929
+ }
930
+ return true;
 
 
 
 
 
 
 
 
 
931
  }
932
 
933
  //--------------------------------------------
939
  * @param array $dayHours
940
  * @return boolean
941
  */
942
+ function ahcfree_insert_visit_times_into_table($dayHours) {
943
+ global $wpdb;
944
+ foreach ($dayHours as $t) {
945
+ $result = $wpdb->insert('ahc_visits_time', array(
946
+ 'vtm_time_from' => $t['vtm_time_from'],
947
+ 'vtm_time_to' => $t['vtm_time_to'],
948
+ 'vtm_visitors' => 0
949
+ ), array(
950
+ '%s', '%s', '%d'
951
+ )
952
+ );
953
+ if ($result === false) {
954
+ return false;
955
+ }
956
+ }
957
+ return true;
 
958
  }
959
+
960
  //--------------------------------------------
961
  /**
962
  * Returns the first and last days of the week of the date you pass
965
  * @param string $format Optional
966
  * @return array
967
  */
968
+ function ahcfree_get_week_limits($date, $format = 'Y-m-d') {
969
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
970
+ $beginingDay = new DateTime($date);
971
+ $custom_timezone = new DateTimeZone(ahcfree_get_timezone_string());
972
+ $endingDay = new DateTime($date);
973
+ $date = new DateTime($date);
974
+ switch ($date->format('w')) {
975
+ case 0: // sun
976
+ //$beginingDay->modify('-1 day');
977
+ $endingDay->modify('+6 day');
978
+ break;
979
+
980
+ case 1: // mon
981
+ $beginingDay->modify('-1 day');
982
+ $endingDay->modify('+5 day');
983
+ break;
984
+
985
+ case 2: // Tue
986
+ $beginingDay->modify('-2 day');
987
+ $endingDay->modify('+4 day');
988
+ break;
989
+
990
+ case 3: // Wed
991
+ $beginingDay->modify('-3 day');
992
+ $endingDay->modify('+3 day');
993
+ break;
994
+
995
+ case 4: // Thu
996
+ $beginingDay->modify('-4 day');
997
+ $endingDay->modify('+2 day');
998
+ break;
999
+
1000
+ case 6: // Fri
1001
+ $beginingDay->modify('-5 day');
1002
+ $endingDay->modify('+1 day');
1003
+ break;
1004
+ }
1005
+ $day = date('w');
1006
+
1007
+ $beginingDay->modify('-'.$day.' days');
1008
+ $endingDay->modify('+'.(6-$day).' days');
1009
+ return array(0 => $beginingDay->format($format), 1 => $endingDay->format($format));
1010
  }
1011
+
1012
  //--------------------------------------------
1013
  /**
1014
  * Return summary statistics of visitors and visits
1015
  *
1016
  * @return array
1017
  */
1018
+ function ahcfree_get_summary_statistics() {
1019
+ $arr = array();
1020
+ $arr['today'] = ahcfree_get_visitors_visits_in_period('today');
1021
+ $arr['yesterday'] = ahcfree_get_visitors_visits_in_period('yesterday');
1022
+ $arr['week'] = ahcfree_get_visitors_visits_in_period('week');
1023
+ $arr['month'] = ahcfree_get_visitors_visits_in_period('month');
1024
+ $arr['year'] = ahcfree_get_visitors_visits_in_period('year');
1025
+ $arr['total'] = ahcfree_get_visitors_visits_in_period();
1026
+ return $arr;
1027
  }
1028
+
1029
  //--------------------------------------------
1030
  /**
1031
  * Return counts visitors and visits in certain day (today|yesterday), certain period(last week, last month, last year) or total
1032
  *
1033
  * @uses wpdb::prepare()
1034
+ * @uses wpdb::get_results()
1035
+ *
1036
+ * @param string $period Optional
1037
+ * @return mixed
1038
+ */
1039
+ function ahcfree_get_visitors_visits_in_period($period = 'total') {
1040
+ global $wpdb;
1041
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
1042
+ $custom_timezone = new DateTimeZone(ahcfree_get_timezone_string());
1043
+ $date = new DateTime();
1044
+ $date->setTimezone($custom_timezone);
1045
+ $sql = "SELECT SUM(vst_visitors) AS vst_visitors, SUM(vst_visits) AS vst_visits
1046
+ FROM `ahc_visitors`
1047
+ WHERE 1 = 1";
1048
+ $results = false;
1049
+ switch ($period) {
1050
+ case 'today':
1051
+ $sql .= " AND DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) = '". date("Y-m-d") ."'";
1052
+ //$sql .= " AND DATE(vst_date) = DATE(NOW())";
1053
+ $results = $wpdb->get_results($sql, OBJECT);
1054
+ break;
1055
+
1056
+ case 'yesterday':
1057
+ $date->modify('-1 day');
1058
+ $sql .= " AND DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) = %s";
1059
+ $results = $wpdb->get_results($wpdb->prepare($sql, $date->format('Y-m-d')), OBJECT);
1060
+ break;
1061
+
1062
+ case 'week':
1063
+ $limits = ahcfree_get_week_limits($date->format('Y-m-d'));
1064
+ $sql .= " AND DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) >= %s AND DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) <= %s";
1065
+ $results = $wpdb->get_results($wpdb->prepare($sql, $limits[0], $limits[1]), OBJECT);
1066
+ break;
1067
+
1068
+ case 'month':
1069
+ $sql .= " AND DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) >= %s AND DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) <= %s";
1070
+ $results = $wpdb->get_results($wpdb->prepare($sql, $date->format('Y-m-01'), $date->format('Y-m-d')), OBJECT);
1071
+ break;
1072
+
1073
+ case 'year':
1074
+ $sql .= " AND DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) >= %s AND DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) <= %s";
1075
+ $results = $wpdb->get_results($wpdb->prepare($sql, $date->format('Y-01-01'), $date->format('Y-12-31')), OBJECT);
1076
+ break;
1077
+
1078
+ default:
1079
+ $results = $wpdb->get_results($sql, OBJECT);
1080
+ }
1081
+ //echo $wpdb->last_query.'<br />';
1082
+ if ($results !== false) {
1083
+ return array(
1084
+ 'visitors' => (empty($results[0]->vst_visitors) ? 0 : $results[0]->vst_visitors),
1085
+ 'visits' => (empty($results[0]->vst_visits) ? 0 : $results[0]->vst_visits)
1086
+ );
1087
+ } else {
1088
+ return false;
1089
+ }
1090
  }
1091
+
1092
  //--------------------------------------------
1093
  /**
1094
  * Return visits in a period from today
1098
  *
1099
  * @return array
1100
  */
1101
+ function ahcfree_get_visitors_visits_by_date() {
1102
  global $wpdb;
1103
  $lastDays = AHC_VISITORS_VISITS_LIMIT - 1;
1104
  $response = array();
1105
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
1106
+ $custom_timezone = new DateTimeZone(ahcfree_get_timezone_string());
1107
  $beginning = new DateTime();
1108
+ $beginning->setTimezone($custom_timezone);
1109
+ $beginning->modify('-' . $lastDays . ' day');
1110
+
1111
+ $sql = "SELECT DATE(CONVERT_TZ(vst_date,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) as vst_date, vst_visitors, vst_visits
1112
  FROM ahc_visitors
1113
+ WHERE DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) >= DATE(CONVERT_TZ(%s, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "'))";
1114
+
 
1115
  $results = $wpdb->get_results($wpdb->prepare($sql, $beginning->format('Y-m-d')), OBJECT);
1116
+ if ($results !== false) {
1117
  $response['success'] = true;
1118
  $response['date'] = array();
1119
+ for ($i = count($results); $i < $lastDays; $i++) {
1120
  $beginning->modify('+1 day');
1121
  $response['data']['dates'][] = $beginning->format('d/m');
1122
  $response['data']['visitors'][] = 0;
1123
  $response['data']['visits'][] = 0;
1124
  }
1125
+
1126
+ foreach ($results as $r) {
1127
  $hitDate = new DateTime($r->vst_date);
1128
+ //$hitDate->setTimezone($custom_timezone);
1129
  $response['data']['dates'][] = $hitDate->format('d/m');
1130
  $response['data']['visitors'][] = $r->vst_visitors;
1131
  $response['data']['visits'][] = $r->vst_visits;
1132
  }
1133
+ } else {
1134
  $response['success'] = false;
1135
  }
1136
  return $response;
1137
  }
1138
+
1139
+ function ahcfree_get_visitors_by_date() {
1140
+ global $wpdb;
1141
+ $lastDays = AHC_VISITORS_VISITS_LIMIT;
1142
+ $response = array();
1143
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
1144
+ $custom_timezone = new DateTimeZone(ahcfree_get_timezone_string());
1145
+ $beginning = new DateTime();
1146
+ $beginning->setTimezone($custom_timezone);
1147
+ $beginning->modify('-' . $lastDays . ' day');
1148
+
1149
+
1150
+ $sql = "SELECT DATE(CONVERT_TZ(vst_date,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) as vst_date, vst_visitors
1151
+ FROM ahc_visitors
1152
+ WHERE DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) >= DATE(CONVERT_TZ(%s, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "'))";
1153
+
1154
+ $results = $wpdb->get_results($wpdb->prepare($sql, $beginning->format('Y-m-d')), OBJECT);
1155
+
1156
+ if ($results !== false) {
1157
+ for ($i = count($results); $i < $lastDays; $i++) {
1158
+ $beginning->modify('+1 day');
1159
+ $xx .= "['" . $beginning->format('Y-m-d') . "', 0], ";
1160
+ }
1161
+ foreach ($results as $r) {
1162
+
1163
+ $hitDate = new DateTime($r->vst_date);
1164
+ //$hitDate->setTimezone($custom_timezone);
1165
+ $xx .= "['" . $hitDate->format('Y-m-d') . "', " . $r->vst_visitors . "], ";
1166
+ }
1167
+ }
1168
+ return '[' . $xx . ']';
1169
+ }
1170
+
1171
+ function ahcfree_get_visits_by_date() {
1172
+ global $wpdb;
1173
+ $lastDays = AHC_VISITORS_VISITS_LIMIT;
1174
+ $response = array();
1175
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
1176
+ $custom_timezone = new DateTimeZone(ahcfree_get_timezone_string());
1177
+ $beginning = new DateTime();
1178
+ $beginning->setTimezone($custom_timezone);
1179
+ $beginning->modify('-' . $lastDays . ' day');
1180
+
1181
+ $sql = "SELECT DATE(CONVERT_TZ(vst_date,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) as vst_date, vst_visits
1182
+ FROM ahc_visitors
1183
+ WHERE DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) >= DATE(CONVERT_TZ(%s, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "'))";
1184
+
1185
+
1186
+ $results = $wpdb->get_results($wpdb->prepare($sql, $beginning->format('Y-m-d')), OBJECT);
1187
+ if ($results !== false) {
1188
+ for ($i = count($results); $i < $lastDays; $i++) {
1189
+ $beginning->modify('+1 day');
1190
+ $x .= "['" . $beginning->format('Y-m-d') . "', 0], ";
1191
+ }
1192
+ foreach ($results as $r) {
1193
+ $hitDate = new DateTime($r->vst_date);
1194
+ //$hitDate->setTimezone($custom_timezone);
1195
+ $x .= "['" . $hitDate->format('Y-m-d') . "', " . $r->vst_visits . "], ";
1196
+ }
1197
+ }
1198
+ return '[' . $x . ']';
1199
  }
1200
+
1201
+
1202
+
1203
  //--------------------------------------------
1204
  /**
1205
  * Returns the total visits by search engines
1208
  *
1209
  * @return mixed
1210
  */
1211
+ function ahcfree_get_total_visits_by_search_engines() {
1212
+ global $wpdb;
1213
+ $result = $wpdb->get_results("SELECT SUM(vtsh_visits) AS total FROM ahc_searching_visits", OBJECT);
1214
+ if ($result !== false) {
1215
+ return $result[0]->total;
1216
+ }
1217
+ return false;
1218
  }
1219
+
1220
  //--------------------------------------------
1221
  /**
1222
  * Return counts visits happened by search engine result in certain day (today|yesterday), certain period(last week, last month, last year) or total
1227
  * @param string $period Optional
1228
  * @return mixed
1229
  */
1230
+ function ahcfree_get_hits_search_engines_referers($period = 'total') {
1231
+ global $wpdb;
1232
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
1233
+ $custom_timezone = new DateTimeZone(ahcfree_get_timezone_string());
1234
+ $date = new DateTime();
1235
+ $date->setTimezone($custom_timezone);
1236
+ $sql = "SELECT srh_id, vtsh_visits
1237
  FROM `ahc_searching_visits`";
1238
+ $results = false;
1239
+ switch ($period) {
1240
+ case 'today':
1241
+ $sql .= " WHERE DATE(CONVERT_TZ(vtsh_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) = DATE(CONVERT_TZ('". date('Y-m-d H:i:s') ."', '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "'))";
1242
+ $results = $wpdb->get_results($sql, OBJECT);
1243
+ break;
1244
+
1245
+ case 'yesterday':
1246
+ $date->modify('-1 day');
1247
+ $sql .= " WHERE DATE(CONVERT_TZ(vtsh_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) = DATE(CONVERT_TZ(%s, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "'))";
1248
+ $results = $wpdb->get_results($wpdb->prepare($sql, $date->format('Y-m-d')), OBJECT);
1249
+ break;
1250
+
1251
+ case 'week':
1252
+ $limits = ahcfree_get_week_limits($date->format('Y-m-d'));
1253
+ $sql .= " WHERE DATE(CONVERT_TZ(vtsh_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) >= DATE(CONVERT_TZ(%s, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) AND DATE(CONVERT_TZ(vtsh_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) <= DATE(CONVERT_TZ(%s, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "'))";
1254
+ $results = $wpdb->get_results($wpdb->prepare($sql, $limits[0], $limits[1]), OBJECT);
1255
+ break;
1256
+
1257
+ case 'month':
1258
+ $sql .= " WHERE DATE(CONVERT_TZ(vtsh_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) >= DATE(CONVERT_TZ('" . $date->format('Y-m-01') . "', '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) AND DATE(CONVERT_TZ(vtsh_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) <= DATE(CONVERT_TZ('" . $date->format('Y-m-t') . "', '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "'))";
1259
+ $results = $wpdb->get_results($wpdb->prepare($sql, $limits[0], $limits[1]), OBJECT);
1260
+ break;
1261
+
1262
+ case 'year':
1263
+ $sql .= " WHERE DATE(CONVERT_TZ(vtsh_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) >= DATE(CONVERT_TZ(%s, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) AND DATE(CONVERT_TZ(vtsh_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) <= DATE(CONVERT_TZ(%s, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "'))";
1264
+ $results = $wpdb->get_results($wpdb->prepare($sql, $date->format('Y-01-01'), $date->format('Y-12-31')), OBJECT);
1265
+ break;
1266
+
1267
+ default:
1268
+ }
1269
+
1270
+ $hitsReferers = array();
1271
+ if ($results !== false) {
1272
+ foreach ($results as $r) {
1273
+ $hitsReferers[$r->srh_id] = $r->vtsh_visits;
1274
+ }
1275
+ return $hitsReferers;
1276
+ }
1277
+ return false;
 
1278
  }
1279
+
1280
  //--------------------------------------------
1281
  /**
1282
  * Retrieves all search engines
1285
  *
1286
  * @return mixed
1287
  */
1288
+ function ahcfree_get_all_search_engines() {
1289
+ global $wpdb;
1290
+ $sql = "SELECT `srh_id`, `srh_name`, `srh_icon` FROM `ahc_search_engines`";
1291
+ $searchEngines = array();
1292
+ $c = 0;
1293
+ $results = $wpdb->get_results($sql, OBJECT);
1294
+ if ($results !== false) {
1295
+ foreach ($results as $re) {
1296
+ $searchEngines[$c]['srh_id'] = $re->srh_id;
1297
+ $searchEngines[$c]['srh_name'] = $re->srh_name;
1298
+ $searchEngines[$c]['srh_icon'] = $re->srh_icon;
1299
+ $c++;
1300
+ }
1301
+ return $searchEngines;
1302
+ }
1303
+ return false;
1304
  }
1305
+
1306
  //--------------------------------------------
1307
  /**
1308
  * Retrieves count of visits order by browsers
1311
  *
1312
  * @return array
1313
  */
1314
+ function ahcfree_get_browsers_hits_counts() {
1315
+ global $wpdb;
1316
+ $sql = "SELECT `bsr_id`, `bsr_name`, `bsr_visits`
1317
  FROM `ahc_browsers`
1318
  WHERE `bsr_visits` > 0";
1319
+ $results = $wpdb->get_results($sql, OBJECT);
1320
+ $response = array();
1321
+ if ($results !== false) {
1322
+ $response['success'] = true;
1323
+ $response['data'] = array();
1324
+ $c = 0;
1325
+ foreach ($results as $bsr) {
1326
+ $response['data'][$c]['bsr_id'] = $bsr->bsr_id;
1327
+ $response['data'][$c]['bsr_name'] = $bsr->bsr_name;
1328
+ $response['data'][$c]['hits'] = $bsr->bsr_visits;
1329
+ $c++;
1330
+ }
1331
+ } else {
1332
+ $response['success'] = false;
1333
+ }
1334
+ return $response;
1335
+ }
1336
+
1337
+ //--------------------------------------------
1338
+ /**
1339
+ * Return visitors visits that came from search engine in a period from today
1340
+ *
1341
+ * @uses wpdb::prepare()
1342
+ * @uses wpdb::get_results()
1343
+ *
1344
+ * @return array
1345
+ */
1346
+
1347
+
1348
+ function ahcfree_get_serch_visits_by_date() {
1349
+ global $wpdb;
1350
+
1351
+ $sql = "SELECT srh_name, sum(vtsh_visits) as vtsh_visits, ase.srh_id FROM ahc_searching_visits asv, ahc_search_engines ase where asv.srh_id = ase.srh_id group by ase.srh_id";
1352
+
1353
+
1354
+
1355
+ $results = $wpdb->get_results($sql, OBJECT);
1356
+ $response = array();
1357
+ if ($results !== false) {
1358
+ $response['success'] = true;
1359
+ $response['data'] = array();
1360
+ $c = 0;
1361
+ foreach ($results as $bsr) {
1362
+ $response['data'][$c]['bsr_id'] = $bsr->srh_id;
1363
+ $response['data'][$c]['bsr_name'] = $bsr->srh_name;
1364
+ $response['data'][$c]['hits'] = $bsr->vtsh_visits;
1365
+ $c++;
1366
+ }
1367
+ } else {
1368
+ $response['success'] = false;
1369
+ }
1370
+
1371
+ return $response;
1372
  }
1373
+
1374
  //--------------------------------------------
1375
  /**
1376
  * Retrieves top referring sites
1380
  *
1381
  * @return mixed
1382
  */
1383
+ function ahcfree_get_top_refering_sites() {
1384
+ global $wpdb;
1385
+ $sql = "SELECT rfr_site_name, rfr_visits
1386
  FROM `ahc_refering_sites`
1387
  ORDER BY rfr_visits DESC
1388
  LIMIT %d OFFSET 0";
1389
+ $results = $wpdb->get_results($wpdb->prepare($sql, AHCFREE_TOP_REFERING_SITES_LIMIT), OBJECT);
1390
+ if ($results !== false) {
1391
+ $arr = array();
1392
+ $c = 0;
1393
+ foreach ($results as $referer) {
1394
+ $arr[$c]['site_name'] = $referer->rfr_site_name;
1395
+ $arr[$c]['total_hits'] = $referer->rfr_visits;
1396
+ $c++;
1397
+ }
1398
+ return $arr;
1399
+ } else {
1400
+ return false;
1401
+ }
1402
+ }
1403
+
1404
+ //--------------------------------------------
1405
+ /**
1406
+ * Retrieves countries related to visits
1407
+ *
1408
+ * @uses wpdb::prepare()
1409
+ * @uses wpdb::get_results()
1410
+ *
1411
+ * @return mixed
1412
+ */
1413
+ function ahcfree_get_top_countries( $limit = 0 ) {
1414
+ global $wpdb;
1415
+ if( $limit == 0 ){
1416
+ $limit = AHCFREE_TOP_COUNTRIES_LIMIT;
1417
+ }
1418
+
1419
+ $sql = "SELECT ctr_name, ctr_internet_code, ctr_visitors, ctr_visits
1420
+ FROM `ahc_countries` WHERE ctr_visits > 0
1421
+ ORDER BY ctr_visitors DESC
1422
+ LIMIT %d OFFSET 0";
1423
+
1424
+ $results = $wpdb->get_results($wpdb->prepare($sql, $limit), OBJECT);
1425
+ $response = array();
1426
+ if ($results !== false) {
1427
+ $response['success'] = true;
1428
+ $response['data'] = array();
1429
+ $c = 0;
1430
+ foreach ($results as $ctr) {
1431
+ $response['data'][$c]['ctr_name'] = $ctr->ctr_name;
1432
+ $response['data'][$c]['ctr_internet_code'] = $ctr->ctr_internet_code;
1433
+ $response['data'][$c]['visitors'] = $ctr->ctr_visitors;
1434
+ $response['data'][$c]['visits'] = $ctr->ctr_visits;
1435
+ $c++;
1436
+ }
1437
+ } else {
1438
+ $response['success'] = false;
1439
+ }
1440
+
1441
+ return $response;
1442
  }
1443
+
1444
+ //--------------------------------------------
1445
+ /**
1446
+ * Retrieves countries related to visits
1447
+ *
1448
+ * @uses wpdb::prepare()
1449
+ * @uses wpdb::get_results()
1450
+ *
1451
+ * @return mixed
1452
+ */
1453
+ function ahcfree_get_vsitors_by_country() {
1454
+ global $wpdb;
1455
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
1456
+ $sql = "select tot.ctr_name, tot.ctr_internet_code, tot.total from (SELECT c.ctr_name, c.ctr_internet_code, count(1) as total
1457
+ FROM ahc_recent_visitors v, ahc_countries c where v.ctr_id = c.ctr_id and DATE(CONVERT_TZ(vtr_date,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) = DATE(CONVERT_TZ(NOW(),'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) group by ctr_name) as tot order by tot.total desc";
1458
+
1459
+ $results = $wpdb->get_results($wpdb->prepare($sql, AHCFREE_TOP_COUNTRIES_LIMIT), OBJECT);
1460
+ if ($results !== false) {
1461
+ $arr = array();
1462
+ $c = 0;
1463
+ foreach ($results as $ctr) {
1464
+ if ($ctr->total > 1) {
1465
+ $arr[$c]['ctr_name'] = $ctr->ctr_name;
1466
+ $arr[$c]['ctr_internet_code'] = $ctr->ctr_internet_code;
1467
+ $arr[$c]['total'] = $ctr->total;
1468
+ } else {
1469
+ $arr[9999]['ctr_name'] = 'others';
1470
+ $arr[9999]['ctr_internet_code'] = 'XX';
1471
+ $arr[9999]['total'] += 1;
1472
+ }
1473
+ $c++;
1474
+ }
1475
+ return $arr;
1476
+ } else {
1477
+ return false;
1478
+ }
1479
+ }
1480
+
1481
  //--------------------------------------------
1482
  /**
1483
  * Retrieves recent visitors
1487
  *
1488
  * @return mixed
1489
  */
1490
+ function ahcfree_get_recent_visitors() {
1491
+ global $wpdb, $_SERVER;
1492
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
1493
+ $sql_query = "SELECT v.vtr_id, v.vtr_ip_address, v.vtr_referer, DATE_FORMAT(CONVERT_TZ(CONCAT_WS(' ',v.vtr_date,v.vtr_time),'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "'), '%Y-%m-%d') as vtr_date, DATE_FORMAT(CONVERT_TZ(CONCAT_WS(' ',v.vtr_date,v.vtr_time),'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "'), '%H:%i:%s') as vtr_time, v.ahc_city, v.ahc_region,
1494
+ c.ctr_name, c.ctr_internet_code, b.bsr_name, b.bsr_icon
1495
  FROM `ahc_recent_visitors` AS v
1496
+ LEFT JOIN `ahc_countries` AS c ON v.ctr_id = c.ctr_id
1497
+ LEFT JOIN `ahc_browsers` AS b ON v.bsr_id = b.bsr_id
1498
  WHERE v.vtr_ip_address NOT LIKE 'UNKNOWN%%'
1499
+ ORDER BY v.vtr_id DESC
1500
+ LIMIT " . AHC_RECENT_VISITORS_LIMIT . " OFFSET 0";
1501
+
1502
+ /* $sql_query = "SELECT v.vtr_id, v.vtr_ip_address, v.vtr_referer, DATE_FORMAT(CONVERT_TZ(v.vtr_date,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "'), '%Y-%m-%d') as vtr_date, DATE_FORMAT(CONVERT_TZ(v.vtr_time,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "'), '%H:%i:%s') as vtr_time, v.ahc_city, v.ahc_region,
1503
+ c.ctr_name, c.ctr_internet_code, b.bsr_name, b.bsr_icon
1504
+ FROM `ahc_recent_visitors` AS v
1505
+ LEFT JOIN `ahc_countries` AS c ON v.ctr_id = c.ctr_id
1506
+ LEFT JOIN `ahc_browsers` AS b ON v.bsr_id = b.bsr_id
1507
+ WHERE v.vtr_ip_address NOT LIKE 'UNKNOWN%%'
1508
+ ORDER BY v.vtr_id DESC
1509
+ LIMIT " . AHC_RECENT_VISITORS_LIMIT . " OFFSET 0"; */
1510
+
1511
+ $results = $wpdb->get_results($sql_query);
1512
+ if ($results !== false) {
1513
+ $arr = array();
1514
+ $c = 0;
1515
+ if (is_array($results)) {
1516
+ foreach ($results as $hit) {
1517
+ if (strlen($hit->vtr_ip_address) < 17) {
1518
+ $arr[$c]['hit_id'] = $hit->vtr_id;
1519
+ $arr[$c]['hit_ip_address'] = $hit->vtr_ip_address;
1520
+ $arr[$c]['hit_referer'] = (parse_url($hit->vtr_referer, PHP_URL_HOST) == $_SERVER['SERVER_NAME']) ? '' : rawurldecode($hit->vtr_referer);
1521
+ $arr[$c]['hit_date'] = $hit->vtr_date;
1522
+ $arr[$c]['hit_time'] = $hit->vtr_time;
1523
+ $arr[$c]['ctr_name'] = $hit->ctr_name;
1524
+ $arr[$c]['ctr_internet_code'] = $hit->ctr_internet_code;
1525
+ $arr[$c]['bsr_name'] = $hit->bsr_name;
1526
+ $arr[$c]['bsr_icon'] = $hit->bsr_icon;
1527
+ $arr[$c]['ahc_city'] = $hit->ahc_city;
1528
+ $arr[$c]['ahc_region'] = $hit->ahc_region;
1529
+
1530
+ $c++;
1531
+ }
1532
+ }
1533
+ }
1534
+ return $arr;
1535
+ } else {
1536
+ return false;
1537
+ }
1538
  }
1539
+
1540
  //--------------------------------------------
1541
  /**
1542
  * Retrieves latest of key words used in search
1546
  *
1547
  * @return mixed
1548
  */
1549
+ function ahcfree_get_latest_search_key_words_used() {
1550
+ global $wpdb;
1551
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
1552
+ $sql = "SELECT k.kwd_ip_address, k.kwd_referer, k.kwd_keywords, CONVERT_TZ(CONCAT_WS(' ',k.kwd_date,k.kwd_time),'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "') as kwd_date, CONVERT_TZ(k.kwd_time,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "') as kwd_time, k.ctr_id,
1553
+ c.ctr_name, c.ctr_internet_code, b.bsr_name, b.bsr_icon, s.srh_name, s.srh_icon
1554
  FROM `ahc_keywords` AS k
1555
+ LEFT JOIN `ahc_countries` AS c ON k.ctr_id = c.ctr_id
1556
  JOIN `ahc_browsers` AS b ON k.bsr_id = b.bsr_id
1557
  JOIN `ahc_search_engines` AS s on k.srh_id = s.srh_id
1558
+ WHERE k.kwd_ip_address != 'UNKNOWN'
1559
  ORDER BY k.kwd_date DESC, k.kwd_time DESC
1560
  LIMIT %d OFFSET 0";
1561
+
1562
+ $results = $wpdb->get_results($wpdb->prepare($sql, AHCFREE_RECENT_KEYWORDS_LIMIT), OBJECT);
1563
+ if ($results !== false) {
1564
+ $arr = array();
1565
+ $c = 0;
1566
+ foreach ($results as $re) {
1567
+
1568
+ $arr[$c]['hit_referer'] = rawurldecode($re->kwd_referer);
1569
+ $arr[$c]['hit_search_words'] = $re->kwd_keywords;
1570
+ $arr[$c]['hit_date'] = $re->kwd_date;
1571
+ $arr[$c]['hit_time'] = $re->kwd_time;
1572
+ $arr[$c]['hit_ip_address'] = $re->kwd_ip_address;
1573
+ $arr[$c]['ctr_name'] = $re->ctr_name;
1574
+ $arr[$c]['ctr_internet_code'] = $re->ctr_internet_code;
1575
+ $arr[$c]['bsr_name'] = $re->bsr_name;
1576
+ $arr[$c]['bsr_icon'] = $re->bsr_icon;
1577
+ $arr[$c]['srh_name'] = $re->srh_name;
1578
+ $arr[$c]['srh_icon'] = $re->srh_icon;
1579
+ $c++;
1580
+ }
1581
+ return $arr;
1582
+ } else {
1583
+ return false;
1584
+ }
1585
  }
1586
+
1587
  //--------------------------------------------
1588
  /**
1589
  * Is in login page
1590
  *
1591
  * @return boolean
1592
  */
1593
+ function ahcfree_is_login_page() {
1594
+ global $Globalsahcfree;
1595
+
1596
+ return in_array($Globalsahcfree['pagenow'], array('wp-login.php', 'wp-register.php'));
1597
+ }
1598
+
1599
+ //--------------------------------------------
1600
+ /**
1601
+ * Retrieves today visitors data, for google map
1602
+ *
1603
+ * @uses wpdb::get_results()
1604
+ *
1605
+ * @return array
1606
+ */
1607
+ function ahcfree_get_today_visitors_for_map() {
1608
+ global $wpdb;
1609
+ $sql = "SELECT hits.visitors, hits.ctr_id,
1610
+ c.ctr_name, c.ctr_internet_code, c.ctr_latitude, c.ctr_longitude FROM (
1611
+ SELECT COUNT(v.visitor) AS visitors, v.ctr_id FROM (
1612
+ SELECT ctr_id, 1 AS visitor FROM `ahc_hits`
1613
+ WHERE ctr_id IS NOT NULL AND hit_ip_address NOT LIKE 'UNKNOWN%'
1614
+ GROUP BY hit_ip_address
1615
+ ) AS v
1616
+ GROUP BY ctr_id) AS hits
1617
+ JOIN `ahc_countries` AS c ON hits.ctr_id = c.ctr_id
1618
+ WHERE c.ctr_latitude IS NOT NULL AND c.ctr_latitude <> 0 AND c.ctr_longitude IS NOT NULL AND c.ctr_longitude <> 0";
1619
+
1620
+ $results = $wpdb->get_results($sql, OBJECT);
1621
+ $response = array();
1622
+ if ($results !== false) {
1623
+ $response['success'] = true;
1624
+ $response['data'] = array();
1625
+ if (is_array($results) && isset($results[0]->visitors) && !empty($results[0]->visitors)) {
1626
+ foreach ($results as $r) {
1627
+ $response['data'][$r->ctr_id]['visitors'] = $r->visitors;
1628
+ $response['data'][$r->ctr_id]['ctr_name'] = $r->ctr_name;
1629
+ $response['data'][$r->ctr_id]['ctr_internet_code'] = $r->ctr_internet_code;
1630
+ $response['data'][$r->ctr_id]['ctr_latitude'] = $r->ctr_latitude;
1631
+ $response['data'][$r->ctr_id]['ctr_longitude'] = $r->ctr_longitude;
1632
+ }
1633
+ }
1634
+ } else {
1635
+ $response['success'] = false;
1636
+ }
1637
+ return $response;
1638
+ }
1639
+
1640
+ /**
1641
+ * Retrieves online visitors data, for google map
1642
+ *
1643
+ * @uses wpdb::get_results()
1644
+ *
1645
+ * @return array
1646
+ */
1647
+ function ahcfree_get_online_visitors_for_map() {
1648
+ global $wpdb;
1649
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
1650
+ $sql = "SELECT hits.visitors, hits.ctr_id,
1651
+ c.ctr_name, c.ctr_internet_code, c.ctr_latitude, c.ctr_longitude FROM (
1652
+ SELECT COUNT(v.visitor) AS visitors, v.ctr_id FROM (
1653
+ SELECT ctr_id, 1 AS visitor FROM `ahc_hits`
1654
+ WHERE ctr_id IS NOT NULL AND hit_ip_address NOT LIKE 'UNKNOWN%' and hit_date = DATE( CONVERT_TZ( '". date("Y-m-d H:i:s") ."' ,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "') ) and TIME( CONVERT_TZ(hit_time,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "') ) between TIME(CONVERT_TZ('". date("Y-m-d H:i:s") ."','" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "') - INTERVAL 60 SECOND) and TIME( CONVERT_TZ('". date("Y-m-d H:i:s") ."','" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "') )
1655
+ GROUP BY hit_ip_address
1656
+ ) AS v
1657
+ GROUP BY ctr_id) AS hits
1658
+ JOIN `ahc_countries` AS c ON hits.ctr_id = c.ctr_id
1659
+ WHERE c.ctr_latitude IS NOT NULL AND c.ctr_latitude <> 0 AND c.ctr_longitude IS NOT NULL AND c.ctr_longitude <> 0 ";
1660
+
1661
+ $results = $wpdb->get_results($sql, OBJECT);
1662
+ $response = array();
1663
+ if ($results !== false) {
1664
+ $response['success'] = true;
1665
+ $response['data'] = array();
1666
+ if (is_array($results) && isset($results[0]->visitors) && !empty($results[0]->visitors)) {
1667
+ foreach ($results as $r) {
1668
+ $response['data'][$r->ctr_id]['visitors'] = $r->visitors;
1669
+ $response['data'][$r->ctr_id]['ctr_name'] = $r->ctr_name;
1670
+ $response['data'][$r->ctr_id]['ctr_internet_code'] = $r->ctr_internet_code;
1671
+ $response['data'][$r->ctr_id]['ctr_latitude'] = $r->ctr_latitude;
1672
+ $response['data'][$r->ctr_id]['ctr_longitude'] = $r->ctr_longitude;
1673
+ }
1674
+ }
1675
+ } else {
1676
+ $response['success'] = false;
1677
+ }
1678
+ return $response;
1679
  }
1680
+
1681
  //--------------------------------------------
1682
  /**
1683
  * Detect if the visitor is search engine bot
1685
  * @uses wpdb::get_results()
1686
  *
1687
  * @return boolean
1688
+ */
1689
+ function ahcfree_is_search_engine_bot() {
1690
+ global $wpdb, $_SERVER;
1691
+ $results = $wpdb->get_results("SELECT `bot_name` FROM `ahc_search_engine_crawlers`", OBJECT);
1692
+ foreach ($results as $crawler) {
1693
+ if (stripos($_SERVER['HTTP_USER_AGENT'], $crawler->bot_name) !== false) {
1694
+ return true;
1695
+ }
1696
+ }
1697
+
1698
+ if (stripos($_SERVER['REQUEST_URI'], 'robots.txt') !== false) {
1699
+ return true;
1700
+ }
1701
+
1702
+ if (stripos($_SERVER['REQUEST_URI'], 'Bot') !== false) {
1703
+ return true;
1704
+ }
1705
+
1706
+ if (stripos($_SERVER['REQUEST_URI'], 'bot') !== false) {
1707
+ return true;
1708
+ }
1709
+ return false;
1710
  }
1711
+
1712
  //--------------------------------------------
1713
  /**
1714
  * Detect if the visitor is WordPress bot
1715
  *
1716
  * @return boolean
1717
  */
1718
+ function ahcfree_is_wordpress_bot() {
1719
+ global $_SERVER;
1720
+ if (stripos($_SERVER['HTTP_USER_AGENT'], 'WordPress') !== false) {
1721
+ return true;
1722
+ }
1723
+ return false;
1724
  }
1725
+
1726
  //--------------------------------------------
1727
  /**
1728
  * Detects post id, post title and post type of current page
1733
  * @param object $query. this object is passed to the callback function of "parse_query" hooked action
1734
  * @return mixed
1735
  */
1736
+ function ahcfree_detect_requested_page($query) {
1737
+ global $wpdb;
1738
+ $vars = $query->query_vars;
1739
+ if (isset($vars['p']) && !empty($vars['p'])) {
1740
+ $result = $wpdb->get_results($wpdb->prepare("SELECT post_title FROM " . $wpdb->prefix . "posts WHERE ID = %d ", $vars['p']));
1741
+ if ($result !== false && $wpdb->num_rows > 0) {
1742
+ return array('page_id' => $vars['p'], 'page_title' => $result[0]->post_title, 'post_type' => 'post');
1743
+ }
1744
+ } else if (isset($vars['name']) && !empty($vars['name'])) {
1745
+ $result = $wpdb->get_results($wpdb->prepare("SELECT ID, post_title FROM " . $wpdb->prefix . "posts WHERE post_name = %s ", $vars['name']));
1746
+ if ($result !== false && $wpdb->num_rows > 0) {
1747
+ return array('page_id' => $result[0]->ID, 'page_title' => $result[0]->post_title, 'post_type' => 'post');
1748
+ }
1749
+ } else if (isset($vars['pagename']) && !empty($vars['pagename'])) {
1750
+ $result = $wpdb->get_results($wpdb->prepare("SELECT ID, post_title FROM " . $wpdb->prefix . "posts WHERE post_name = %s AND post_type = %s", ahcfree_get_subpage_name($vars['pagename']), 'page'));
1751
+ if ($result !== false && $wpdb->num_rows > 0) {
1752
+ return array('page_id' => $result[0]->ID, 'page_title' => $result[0]->post_title, 'post_type' => 'page');
1753
+ }
1754
+ } else if (isset($vars['page_id']) && !empty($vars['page_id'])) {
1755
+ $result = $wpdb->get_results($wpdb->prepare("SELECT post_title FROM " . $wpdb->prefix . "posts WHERE ID = %s AND post_type = %s", $vars['page_id'], 'page'));
1756
+ if ($result !== false && $wpdb->num_rows > 0) {
1757
+ return array('page_id' => $page_id, 'page_title' => $result[0]->post_title, 'post_type' => 'page');
1758
+ }
1759
+ } else {
1760
+ return array('page_id' => 'HOMEPAGE', 'page_title' => NULL, 'post_type' => NULL);
1761
+ }
 
 
 
 
 
 
 
 
 
1762
  }
1763
 
1764
+ function ahcfree_get_subpage_name($page_name) {
1765
+ $sub_name = strrchr($page_name, '/');
1766
+ if (!$sub_name) {
1767
+ return $page_name;
1768
+ }
1769
+ return substr($sub_name, 1);
1770
  }
1771
+
1772
  //--------------------------------------------
1773
+ function ahcfree_sanitizing($unsafe_val,$type='text')
1774
+ {
1775
+
1776
+
1777
+ switch ($type) {
1778
+ case 'text': return sanitize_text_field($unsafe_val);
1779
+ break;
1780
+
1781
+ case 'int': return intval($unsafe_val);
1782
+ break;
1783
+
1784
+ case 'email': return sanitize_email($unsafe_val);
1785
+ break;
1786
+
1787
+ case 'filename': return sanitize_file_name($unsafe_val);
1788
+ break;
1789
+
1790
+ case 'title': return sanitize_title($unsafe_val);
1791
+ break;
1792
+
1793
+ case 'url': return esc_url($unsafe_val);
1794
+ break;
1795
+
1796
+ default:
1797
+ return sanitize_text_field($unsafe_val);
1798
+
1799
+ }
1800
+ }
1801
+
1802
+
1803
+ function ahcfree_track_visitor()
1804
+ {
1805
+ $exclude_ips = AHCFREE_EXCLUDE_IPS;
1806
+ if ($exclude_ips == '' or $exclude_ips == '') {
1807
+ $exclude_ips = array();
1808
+ }
1809
+ if (AHCFREE_EXCLUDE_IPS != NULL && AHCFREE_EXCLUDE_IPS != '') {
1810
+ $exclude_ips = explode("\n", $exclude_ips);
1811
+ }
1812
+
1813
+ if (ahcfree_should_track_visitor() && !ahcfree_is_login_page() && !ahcfree_is_search_engine_bot() && !ahcfree_is_wordpress_bot()) {
1814
+ if (!in_array(ahcfree_get_client_ip_address(), $exclude_ips)) {
1815
+
1816
+ $page_id = ahcfree_sanitizing($_POST['page_id'], 'int');
1817
+ $page_title = ahcfree_sanitizing($_POST['page_title']);
1818
+ $post_type = ahcfree_sanitizing($_POST['post_type']);
1819
+ $_SERVER['HTTP_REFERER'] = ahcfree_sanitizing($_POST['referer']);
1820
+ $_SERVER['HTTP_USER_AGENT'] = ahcfree_sanitizing($_POST['useragent']);
1821
+ $_SERVER['SERVER_NAME'] = ahcfree_sanitizing($_POST['servername']);
1822
+ $_SERVER['HTTP_HOST'] = ahcfree_sanitizing($_POST['hostname']);
1823
+ $_SERVER['REQUEST_URI'] = ahcfree_sanitizing($_POST['request_uri']);
1824
+
1825
+ $hitsCounter = new AHCFree_WPHitsCounterPro($page_id, $page_title, $post_type);
1826
+ $hitsCounter->traceVisitorHit();
1827
+ }
1828
+ }
1829
+
1830
+ die;
1831
  }
1832
+
1833
+
1834
+
1835
  //--------------------------------------------
1836
  /**
1837
  * Ceil for decimal numbers with precision
1841
  * @param string $separator
1842
  * @return float
1843
  */
1844
+ function ahcfree_ceil_dec($number, $precision, $separator) {
1845
+ if (strpos($number, '.') !== false) {
1846
+ $numberpart = explode($separator, $number);
1847
+ $numberpart[1] = substr_replace($numberpart[1], $separator, $precision, 0);
1848
+ if ($numberpart[0] >= 0) {
1849
+ $numberpart[1] = ceil($numberpart[1]);
1850
+ } else {
1851
+ $numberpart[1] = floor($numberpart[1]);
1852
+ }
1853
+
1854
+ $ceil_number = array($numberpart[0], $numberpart[1]);
1855
+ return implode($separator, $ceil_number);
1856
+ }
1857
+ return $number;
1858
  }
1859
+
1860
  //--------------------------------------------
1861
  /**
1862
  * Retrieve sum visits by post title
1866
  *
1867
  * @return mixed
1868
  */
1869
+ function ahcfree_get_traffic_by_title() {
1870
+ global $wpdb;
1871
+ $sql1 = "SELECT SUM(hits) AS sm FROM (
1872
  SELECT SUM(til_hits) AS hits
1873
  FROM ahc_title_traffic
1874
  GROUP BY til_page_id
1875
  ) myTable";
1876
+
1877
+ $sql2 = "SELECT til_page_id, til_page_title, til_hits
1878
  FROM ahc_title_traffic
1879
  GROUP BY til_page_id
1880
  ORDER BY til_hits DESC
1881
  LIMIT %d OFFSET 0";
1882
+
1883
+ $result1 = $wpdb->get_results($sql1);
1884
+ if ($result1 !== false) {
1885
+ $total = $result1[0]->sm;
1886
+ $result2 = $wpdb->get_results($wpdb->prepare($sql2, AHCFREE_TRAFFIC_BY_TITLE_LIMIT));
1887
+ if ($result2 !== false) {
1888
+ $arr = array();
1889
+ if ($wpdb->num_rows > 0) {
1890
+ $c = 0;
1891
+ foreach ($result2 as $r) {
1892
+ $arr[$c]['rank'] = $c + 1;
1893
+ $arr[$c]['til_page_id'] = $r->til_page_id;
1894
+ $arr[$c]['til_page_title'] = $r->til_page_title;
1895
+ $arr[$c]['til_hits'] = $r->til_hits;
1896
+ $arr[$c]['percent'] = ($total > 0) ? ahcfree_ceil_dec((($r->til_hits / $total) * 100), 2, ".") . ' %' : 0;
1897
+ $c++;
1898
+ }
1899
+ }
1900
+ return $arr;
1901
+ }
1902
+ }
1903
+ return false;
1904
  }
1905
+
1906
  //--------------------------------------------
1907
  /**
1908
  * Retrieves sum of visits order by time
1911
  *
1912
  * @return mixed
1913
  */
1914
+ function ahcfree_get_time_visits() {
1915
+ global $wpdb;
1916
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
1917
+
1918
+ $vst_date = "CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')";
1919
+ $sql1 = "SELECT SUM(vtm_visitors) AS sm FROM ahc_visits_time WHERE DATE($vst_date) = '".date('Y-m-d')."'";
1920
+ $sql2 = "SELECT hour($vst_date) AS hour, SUM(vst_visitors) AS vst_visitors, SUM(vst_visits) AS vst_visits FROM `ahc_visitors`
1921
+ WHERE DATE($vst_date) = '".date('Y-m-d')."' GROUP BY hour($vst_date) ";
1922
+ //$result1 = $wpdb->get_results($sql1);
1923
+ //if ($result1 !== false) {
1924
+ $total = 0;
1925
+ $result2 = $wpdb->get_results($sql2);
1926
+ //asort($result2);
1927
+ $utc_data = array();
1928
+
1929
+ if ($result2 !== false) {
1930
+ $arr = array();
1931
+ $hourDetails = array();
1932
+ foreach ($result2 as $r) {
1933
+ $hourDetails[ $r->hour ] = array(
1934
+ 'visitor' => $r->vst_visitors,
1935
+ 'visits' => $r->vst_visits,
1936
+ );
1937
+ $total += $r->vst_visitors;
1938
+ }
1939
+ for( $i = 0; $i < 24; $i++ ){
1940
+ $vtm_visitors = 0;
1941
+ $vtm_visits = 0;
1942
+ if( isset( $hourDetails[$i] ) ){
1943
+ $vtm_visitors = $hourDetails[$i]['visitor'];
1944
+ $vtm_visits = $hourDetails[$i]['visits'];
1945
+ }
1946
+ if( $i < 10 ){
1947
+ $timeTo = $timeFrom = '0'.$i;
1948
+ }else{
1949
+ $timeTo = $timeFrom = $i;
1950
+ }
1951
+ $arr[$i]['vtm_time_from'] = $timeFrom.':00';
1952
+ $arr[$i]['vtm_time_to'] = $timeTo.':59';
1953
+ $arr[$i]['vtm_visitors'] = $vtm_visitors;
1954
+ $arr[$i]['vtm_visits'] = $vtm_visits;
1955
+ $arr[$i]['percent'] = ($total > 0) ? ahcfree_ceil_dec((($vtm_visitors / $total) * 100), 2, ".") : 0;
1956
  }
1957
+ return $arr;
1958
+ }
1959
+ //}
1960
+ return false;
1961
+
1962
+ }
1963
+
1964
+ function ahcfree_advanced_get_link($url, $followRedirects = true) {
1965
+ $url_parsed = @parse_url($url);
1966
+ $header = '';
1967
+ $body = '';
1968
+
1969
+ if (empty($url_parsed['scheme'])) {
1970
+ $url_parsed = @parse_url($url);
1971
+ }
1972
+ $rtn['url'] = $url_parsed;
1973
+
1974
+ $port = $url_parsed["port"];
1975
+ if (!$port) {
1976
+ $port = 80;
1977
+ }
1978
+ $rtn['url']['port'] = $port;
1979
+
1980
+ $path = $url_parsed["path"];
1981
+ if (empty($path)) {
1982
+ $path = "/";
1983
+ }
1984
+ if (!empty($url_parsed["query"])) {
1985
+ $path .= "?" . $url_parsed["query"];
1986
+ }
1987
+ $rtn['url']['path'] = $path;
1988
+
1989
+ $host = $url_parsed["host"];
1990
+ $foundBody = false;
1991
+
1992
+ $out = "GET $path HTTP/1.0\r\n";
1993
+ $out .= "Host: $host\r\n";
1994
+ $out .= "Connection: Close\r\n\r\n";
1995
+
1996
+ if (!$fp = @fsockopen($host, $port, $errno, $errstr, 30)) {
1997
+ $rtn['errornumber'] = $errno;
1998
+ $rtn['errorstring'] = $errstr;
1999
+ return $rtn;
2000
+ }
2001
+ fwrite($fp, $out);
2002
+ while (!feof($fp)) {
2003
+ $s = fgets($fp, 128);
2004
+ if ($s == "\r\n") {
2005
+ $foundBody = true;
2006
+ continue;
2007
+ }
2008
+ if ($foundBody) {
2009
+ $body .= $s;
2010
+ } else {
2011
+ if (($followRedirects) && (stristr($s, "location:") != false)) {
2012
+ $redirect = preg_replace("/location:/i", "", $s);
2013
+ return ffl_HttpGet(trim($redirect));
2014
+ }
2015
+ $header .= $s;
2016
+ }
2017
+ }
2018
+ fclose($fp);
2019
+
2020
+ $rtn['header'] = trim($header);
2021
+ $rtn['body'] = trim($body);
2022
+ return $rtn;
2023
  }
2024
+
2025
  //--------------------------------------------
2026
  /**
2027
  * Returns client IP address
2028
  *
2029
  * @return string
2030
  */
2031
+ function ahcfree_get_client_ip_address() {
2032
+ global $_SERVER;
2033
+ $ipAddress = '';
2034
+ if (isset($_SERVER['REMOTE_ADDR']) && !empty($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR']!='127.0.0.1') {
2035
+ $ipAddress = $_SERVER['REMOTE_ADDR'];
2036
+ }else if (isset($_SERVER['HTTP_CLIENT_IP']) && !empty($_SERVER['HTTP_CLIENT_IP']) && $_SERVER['HTTP_CLIENT_IP']!='127.0.0.1') {
2037
  $ipAddress = $_SERVER['HTTP_CLIENT_IP'];
2038
+ } else if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR']!='127.0.0.1') {
 
2039
  $ipAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
2040
+ } else if (isset($_SERVER['HTTP_X_FORWARDED']) && !empty($_SERVER['HTTP_X_FORWARDED']) && $_SERVER['HTTP_X_FORWARDED']!='127.0.0.1') {
 
2041
  $ipAddress = $_SERVER['HTTP_X_FORWARDED'];
2042
+ } else if (isset($_SERVER['HTTP_FORWARDED_FOR']) && !empty($_SERVER['HTTP_FORWARDED_FOR']) && $_SERVER['HTTP_FORWARDED_FOR']!='127.0.0.1') {
 
2043
  $ipAddress = $_SERVER['HTTP_FORWARDED_FOR'];
2044
+ } else if (isset($_SERVER['HTTP_FORWARDED']) && !empty($_SERVER['HTTP_FORWARDED']) && $_SERVER['HTTP_FORWARDED']!='127.0.0.1') {
 
2045
  $ipAddress = $_SERVER['HTTP_FORWARDED'];
2046
+ } else {
 
 
 
 
2047
  $ipAddress = 'UNKNOWN';
2048
+ }
2049
+
2050
+ $ipAddress = explode(',', $ipAddress);
2051
+
2052
+ return $ipAddress[0];
2053
  }
2054
+
2055
  //--------------------------------------------
2056
  /**
2057
  * To include scripts and styles tags into the head
2063
  *
2064
  * @return void
2065
  */
2066
+ function ahcfree_include_scripts() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2067
 
2068
 
2069
+ wp_register_style('ahcfree_lang_css', plugins_url('/css/engl_css.css', AHCFREE_PLUGIN_MAIN_FILE));
2070
+ wp_enqueue_style('ahcfree_lang_css');
2071
+
2072
+ if(get_locale() == 'ar')
2073
+ {
2074
+ wp_register_style('ahcfree_bootstrap_ar_css', plugins_url('/lib/bootstrap/css/bootstrap-rtl.min.css',AHCFREE_PLUGIN_MAIN_FILE));
2075
+ wp_enqueue_style('ahcfree_bootstrap_ar_css');
2076
+ }else{
2077
+ wp_register_style('ahcfree_bootstrap_css', plugins_url('/lib/bootstrap/css/bootstrap.min.css',AHCFREE_PLUGIN_MAIN_FILE));
2078
+ wp_enqueue_style('ahcfree_bootstrap_css');
2079
+ }
2080
+
2081
+ wp_enqueue_script( 'ahc_slimselect_js', 'https://cdnjs.cloudflare.com/ajax/libs/slim-select/1.25.0/slimselect.min.js', false, '1.0.0', false);
2082
+ wp_register_style('ahc_slimselect_css', 'https://cdnjs.cloudflare.com/ajax/libs/slim-select/1.25.0/slimselect.min.css', false, '1.0.0' );
2083
+ wp_enqueue_style('ahc_slimselect_css');
2084
+ wp_enqueue_script('jquery');
2085
+
2086
+ wp_register_script('ahcfree_bootstrap_js', plugins_url('/lib/bootstrap/js/bootstrap.min.js',AHCFREE_PLUGIN_MAIN_FILE));
2087
+ wp_enqueue_script('ahcfree_bootstrap_js');
2088
+
2089
+ wp_register_script('ahcfree_lang_js', plugins_url('/lang/js/' . Globalsahcfree::$lang . '_lang.js', AHCFREE_PLUGIN_MAIN_FILE));
2090
+ wp_enqueue_script('ahcfree_lang_js');
2091
+
2092
+ wp_register_script('ahcfree_main_js', plugins_url('/js/ahc_jqscripts.js', AHCFREE_PLUGIN_MAIN_FILE), false, '1.19');
2093
+ wp_enqueue_script('ahcfree_main_js');
2094
+
2095
+ wp_localize_script('ahcfree_main_js', 'ahcfree_ajax', array('ajax_url' => admin_url('admin-ajax.php')));
2096
+
2097
+ wp_register_script('ahcfree_Chart_js', plugins_url('/lib/Chart_js/Chart.min.js', AHCFREE_PLUGIN_MAIN_FILE));
2098
+ wp_enqueue_script('ahcfree_Chart_js');
2099
+
2100
+ wp_register_script('utils_js', plugins_url('/lib/Chart_js/utils.js', AHCFREE_PLUGIN_MAIN_FILE));
2101
+ wp_enqueue_script('utils_js');
2102
+
2103
+
2104
+ /* wp_register_script('ahcfree_GoogleChart_js', 'https://www.gstatic.com/charts/loader.js');
2105
+ wp_enqueue_script('ahcfree_GoogleChart_js');
2106
+
2107
+ */
2108
+ // jqplot
2109
+ wp_register_style('jqueryjqplotmincss', plugins_url('/css/jquery.jqplot.min.css?ver=1.0.8', AHCFREE_PLUGIN_MAIN_FILE));
2110
+ wp_enqueue_style('jqueryjqplotmincss');
2111
+
2112
+ wp_register_script('jqueryjqplotmin', plugins_url('/js/jquery.jqplot.min.js?ver=0.8.3', AHCFREE_PLUGIN_MAIN_FILE));
2113
+ wp_enqueue_script('jqueryjqplotmin');
2114
+
2115
+ wp_register_script('jqplotdateAxisRenderermin', plugins_url('/js/jqplot.dateAxisRenderer.min.js?ver=0.8.3', AHCFREE_PLUGIN_MAIN_FILE));
2116
+ wp_enqueue_script('jqplotdateAxisRenderermin');
2117
+
2118
+ wp_register_script('jqplotcanvasAxisTickRenderermin', plugins_url('/js/jqplot.canvasAxisTickRenderer.min.js?ver=0.8.3', AHCFREE_PLUGIN_MAIN_FILE));
2119
+ wp_enqueue_script('jqplotcanvasAxisTickRenderermin');
2120
+
2121
+ wp_register_script('jqplotcanvasAxisLabelRenderermin', plugins_url('/js/jqplot.canvasAxisLabelRenderer.min.js?ver=0.8.3', AHCFREE_PLUGIN_MAIN_FILE));
2122
+ wp_enqueue_script('jqplotcanvasAxisLabelRenderermin');
2123
+
2124
+ wp_register_script('jqplot.canvasTextRenderer.min', plugins_url('/js/jqplot.canvasTextRenderer.min.js?ver=0.8.3', AHCFREE_PLUGIN_MAIN_FILE));
2125
+ wp_enqueue_script('jqplot.canvasTextRenderer.min');
2126
+
2127
+
2128
 
2129
+ wp_register_script('jqplothighlightermin', plugins_url('/js/jqplot.highlighter.min.js?ver=0.8.3', AHCFREE_PLUGIN_MAIN_FILE));
2130
+ wp_enqueue_script('jqplothighlightermin');
2131
 
2132
+ wp_register_script('jqplot.pieRenderer.min', plugins_url('/js/jqplot.pieRenderer.min.js?ver=0.8.3', AHCFREE_PLUGIN_MAIN_FILE));
2133
+ wp_enqueue_script('jqplot.pieRenderer.min');
2134
 
2135
+ wp_register_script('jqplot.enhancedLegendRenderer.min', plugins_url('/js/jqplot.enhancedLegendRenderer.min.js?ver=0.8.3', AHCFREE_PLUGIN_MAIN_FILE));
2136
+ wp_enqueue_script('jqplot.enhancedLegendRenderer.min');
2137
+
2138
+ wp_enqueue_script('sweetalert', plugins_url('/js/sweetalert.min.js', AHCFREE_PLUGIN_MAIN_FILE));
2139
+ wp_enqueue_style( 'sweetalert', plugins_url('/css/sweetalerts.css', AHCFREE_PLUGIN_MAIN_FILE));
2140
+
2141
+
2142
+
2143
+
2144
+ }
2145
+
2146
+ //--------------------------------------------
2147
  //---------------------------------------------Add button to the admin bar
2148
+ function ahcfree_vtrts_add_items($admin_bar) {
2149
+ global $pluginsurl;
 
2150
 
2151
+ $wccpadminurl = get_admin_url();
2152
  //The properties of the new item. Read More about the missing 'parent' parameter below
2153
  $args = array(
2154
+ 'id' => 'visitorstraffic',
2155
+ 'title' => __('<img src="' . plugins_url('/images/vtrtspro.png', AHCFREE_PLUGIN_MAIN_FILE) . '" style="vertical-align:middle;margin-right:5px;" alt="visitor traffic" title="visitor traffic" />'),
2156
+ 'href' => $wccpadminurl . 'admin.php?page=ahc_hits_counter_menu_free',
2157
+ 'meta' => array('title' => __('Visitor Traffic Real Time Statistics'),)
2158
+ );
2159
+
2160
  //This is where the magic works.
2161
+ $admin_bar->add_menu($args);
2162
  }
2163
+
2164
  //---------------------------------------- Add plugin settings link to Plugins page
2165
+ function ahcfree_vtrtsp_plugin_add_settings_link($links) {
2166
+ $settings_link = '<a href="admin.php?page=ahc_hits_counter_menu_pro">' . __('visitor traffic') . '</a>';
2167
+ array_push($links, $settings_link);
2168
+ return $links;
2169
  }
2170
+
2171
  //------------------------------------------------------------------------
2172
+ // --------------------------------------- Create front-end widget
2173
+ // Creating the widget
2174
+ class vtrtsfree_widget extends WP_Widget {
2175
 
2176
+ function __construct() {
2177
+ parent::__construct(
2178
+ // Base ID of your widget
2179
+ 'vtrtsfree_widget',
2180
+ // Widget name will appear in UI
2181
+ __('Visitor Traffic', 'wpb_widget_domain'),
2182
+ // Widget description
2183
+ array('description' => __('Display your site statistics', 'wpb_widget_domain'),)
2184
+ );
2185
+ }
2186
 
2187
+ // Creating widget front-end
2188
+ // This is where the action happens
2189
+ public function widget($args, $instance) {
2190
+ $title = apply_filters('widget_title', $instance['title']);
2191
+ // before and after widget arguments are defined by themes
2192
+ echo $args['before_widget'];
2193
+ if (!empty($title))
2194
+ echo $args['before_title'] . $title . $args['after_title'];
2195
 
2196
 
2197
+ $ahcfree_sum_stats = ahcfree_get_summary_statistics();
2198
+
2199
+
2200
+ // This is where you run the code and display the output
2201
+ echo '<ul style="list-style:none; ' . $instance['fontTypeCombo'] . '; font-size:' . $instance['fontSizeCombo'] . 'px">';
2202
+ if ($instance['display_onlineusers'] == 1 or $instance['display_onlineusers'] == '1') {
2203
+ $online_img_path = plugins_url('/images/live.gif', AHCFREE_PLUGIN_MAIN_FILE);
2204
+ echo '<li><b style="color:#' . $instance['display_titlecolor'] . '">Users online: </b><span style="color:#' . $instance['display_valuescolor'] . '">' . ahcfree_countOnlineusers() . '</span>&nbsp;<img src="' . $online_img_path . '" /></li>';
2205
+ }
2206
+ if ($instance['display_visitorstoday'] == 1 or $instance['display_visitorstoday'] == '1') {
2207
+ echo '<li><b style="color:#' . $instance['display_titlecolor'] . '">Visitors today : </b><span style="color:#' . $instance['display_valuescolor'] . '">' . ahcfree_free_NumFormat($ahcfree_sum_stats['today']['visitors']) . '</span></li>';
2208
+ }
2209
+ if ($instance['display_pageviewtoday'] == 1 or $instance['display_pageviewtoday'] == '1') {
2210
+ echo '<li><b style="color:#' . $instance['display_titlecolor'] . '">Page views today : </b><span style="color:#' . $instance['display_valuescolor'] . '">' . ahcfree_free_NumFormat($ahcfree_sum_stats['today']['visits']) . '</span></li>';
2211
+ }
2212
+
2213
+ if ($instance['display_totalvisitors'] == 1 or $instance['display_totalvisitors'] == '1') {
2214
+ echo '<li><b style="color:#' . $instance['display_titlecolor'] . '">Total visitors : </b><span style="color:#' . $instance['display_valuescolor'] . '">' . ahcfree_free_NumFormat($ahcfree_sum_stats['total']['visitors']) . '</span></li>';
2215
+ }
2216
+
2217
+ if ($instance['display_totalpageview'] == 1 or $instance['display_totalpageview'] == '1') {
2218
+ echo '<li><b style="color:#' . $instance['display_titlecolor'] . '">Total page view: </b><span style="color:#' . $instance['display_valuescolor'] . '">' . ahcfree_free_NumFormat($ahcfree_sum_stats['total']['visits']) . '</span></li>';
2219
+ }
2220
+
2221
+
2222
+ echo '</ul>';
2223
+ echo $args['after_widget'];
2224
+ }
2225
+
2226
+ // Widget Backend
2227
+ public function form($instance) {
2228
+ extract($instance);
2229
+
2230
+ if (isset($instance['title'])) {
2231
+ $title = $instance['title'];
2232
+ } else {
2233
+ $title = __('Site Statistics', 'wpb_widget_domain');
2234
+ }
2235
+ // Widget admin form
2236
+ ?>
2237
+
2238
+
2239
+ <p>
2240
+ <label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Widget Title:'); ?></label>
2241
+ <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo (isset($title) ? esc_attr($title) : ''); ?>" />
2242
+ </p>
2243
+
2244
+ <p>
2245
+ <label for="<?php echo $this->get_field_id('display_titlecolor'); ?>"><?php _e('Title Color:'); ?></label>
2246
+ <input class="color widefat" id="<?php echo $this->get_field_id('display_titlecolor'); ?>" name="<?php echo $this->get_field_name('display_titlecolor'); ?>" style="border:#CCC solid 1px" value="<?php echo (isset($display_titlecolor) ? esc_attr($display_titlecolor) : ''); ?>" >
2247
+ </p>
2248
+
2249
+ <p>
2250
+ <label for="<?php echo $this->get_field_id('display_valuescolor'); ?>"><?php _e('Value Color:'); ?></label>
2251
+ <input class="color widefat" style="border:#CCC solid 1px" id="<?php echo $this->get_field_id('display_valuescolor'); ?>" name="<?php echo $this->get_field_name('display_valuescolor'); ?>" value="<?php echo (isset($display_valuescolor) ? esc_attr($display_valuescolor) : ''); ?>" >
2252
+ </p>
2253
+
2254
+
2255
+ <p>
2256
+ <label for="<?php echo $this->get_field_id('fontTypeCombo'); ?>"><?php _e('Font Type:'); ?></label>
2257
+ <select class="widefat" id="<?php echo $this->get_field_id('fontTypeCombo'); ?>" name="<?php echo $this->get_field_name('fontTypeCombo'); ?>">
2258
+ <optgroup class='verdana'>
2259
+ <option <?php selected($fontTypeCombo, 'font-family:Verdana, Geneva, sans-serif'); ?> value="font-family:Verdana, Geneva, sans-serif">Verdana</option>
2260
+ </optgroup>
2261
+
2262
+ <optgroup class='TimesNew'>
2263
+ <option <?php selected($fontTypeCombo, "font-family:'Times New Roman', Times, serif"); ?> value="font-family:'Times New Roman', Times, serif">Times New Roman</option>
2264
+ </optgroup>
2265
+
2266
+ <optgroup class='Arial'>
2267
+ <option <?php selected($fontTypeCombo, "font-family:Arial, Helvetica, sans-serif"); ?> value="font-family:Arial, Helvetica, sans-serif">Arial</option>
2268
+ </optgroup>
2269
+
2270
+ <optgroup class='Tahoma'>
2271
+ <option <?php selected($fontTypeCombo, "font-family:Tahoma, Geneva, sans-serif"); ?> value="font-family:Tahoma, Geneva, sans-serif">Tahoma</option>
2272
+ </optgroup>
2273
+
2274
+ <optgroup class='Courier'>
2275
+ <option <?php selected($fontTypeCombo, "font-family:'Courier New', Courier, monospace"); ?> value="font-family:'Courier New', Courier, monospace">Courier</option>
2276
+ </optgroup>
2277
+
2278
+ <optgroup class='TrebuchetMS'>
2279
+ <option <?php selected($fontTypeCombo, "font-family:'Trebuchet MS', Arial, Helvetica, sans-serif"); ?> value="font-family:'Trebuchet MS', Arial, Helvetica, sans-serif">Trebuchet MS</option>
2280
+ </optgroup>
2281
+
2282
+
2283
+ </select>
2284
+
2285
+ </p>
2286
+ <label for="<?php echo $this->get_field_id('fontSizeCombo'); ?>"><?php _e('Font Size:'); ?></label>
2287
+ <select class="widefat" id="<?php echo $this->get_field_id('fontSizeCombo'); ?>" name="<?php echo $this->get_field_name('fontSizeCombo'); ?>">
2288
+ <?php
2289
+ for ($fs = 8; $fs <= 22; $fs++) {
2290
+ ?>
2291
+ <option value="<?php echo $fs ?>" <?php selected($fontSizeCombo, $fs); ?>><?php echo $fs; ?>px</option>
2292
+ <?php } ?>
2293
+ </select>
2294
+ <p>
2295
+
2296
+ </p>
2297
+
2298
+ <p><em>Display :</em></p>
2299
+
2300
+
2301
+ <p>
2302
+ <input class="widefat" id="<?php echo $this->get_field_id('display_onlineusers'); ?>" name="<?php echo $this->get_field_name('display_onlineusers'); ?>" type="checkbox" value="1" <?php isset($display_onlineusers) ? checked($display_onlineusers, '1') : ''; ?> />&nbsp;<label for="<?php echo $this->get_field_id('display_onlineusers'); ?>">Users Online</label>
2303
+ </p>
2304
+ <p>
2305
+ <input class="widefat" id="<?php echo $this->get_field_id('display_visitorstoday'); ?>" name="<?php echo $this->get_field_name('display_visitorstoday'); ?>" type="checkbox" value="1" <?php isset($display_onlineusers) ? checked($display_visitorstoday, '1') : ''; ?>/>&nbsp;<label for="<?php echo $this->get_field_id('display_visitorstoday'); ?>">Visitors Today</label>
2306
+ </p>
2307
+ <p>
2308
+ <input class="widefat" id="<?php echo $this->get_field_id('display_pageviewtoday'); ?>" name="<?php echo $this->get_field_name('display_pageviewtoday'); ?>" type="checkbox" value="1" <?php isset($display_onlineusers) ? checked($display_pageviewtoday, '1') : ''; ?>/>&nbsp;<label for="<?php echo $this->get_field_id('display_pageviewtoday'); ?>">Page Views Today</label>
2309
+ </p>
2310
+ <p>
2311
+ <input class="widefat" id="<?php echo $this->get_field_id('display_totalpageview'); ?>" name="<?php echo $this->get_field_name('display_totalpageview'); ?>" type="checkbox" value="1" <?php isset($display_onlineusers) ? checked($display_totalpageview, '1') : ''; ?> />&nbsp;<label for="<?php echo $this->get_field_id('display_totalpageview'); ?>">Total Page Views</label>
2312
+ </p>
2313
+ <p>
2314
+ <input class="widefat" id="<?php echo $this->get_field_id('display_totalvisitors'); ?>" name="<?php echo $this->get_field_name('display_totalvisitors'); ?>" type="checkbox" value="1" <?php isset($display_onlineusers) ? checked($display_totalvisitors, '1') : ''; ?>/>&nbsp;<label for="<?php echo $this->get_field_id('display_totalvisitors'); ?>">Total Visitors</label>
2315
+ </p>
2316
+ </p>
2317
+ <?php
2318
+ }
2319
+
2320
+ // Updating widget replacing old instances with new
2321
+ public function update($new_instance, $old_instance) {
2322
+
2323
+ return $new_instance;
2324
+ }
2325
+
2326
+ }
2327
+
2328
+ // Class vtrtsfree_widget ends here
2329
+ // Register and load the widget
2330
+ function ahcfree_wpb_load_widget() {
2331
+ register_widget('vtrtsfree_widget');
2332
+ }
2333
+
2334
+ add_action('widgets_init', 'ahcfree_wpb_load_widget');
2335
+
2336
+ function ahcfree_get_hits_by_custom_duration_callback(){
2337
+ $hits_duration = $_POST['hits_duration'];
2338
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
2339
+ $custom_timezone = new DateTimeZone(ahcfree_get_timezone_string());
2340
+
2341
+ $myend_date = new DateTime();
2342
+ $myend_date->setTimezone($custom_timezone);
2343
+
2344
+ $end_date = $myend_date->format('Y-m-d');
2345
+ $full_end_date = $myend_date->format('Y-m-d 23:59:59');
2346
+
2347
+ $mystart_date = new DateTime();
2348
+ $mystart_date->setTimezone($custom_timezone);
2349
+ $stat = '';
2350
+ switch ($hits_duration){
2351
+
2352
+ case '7':
2353
+ $mystart_date->modify('-7 days');
2354
+ $start_date = $mystart_date->format('Y-m-d');
2355
+ $full_start_date = $mystart_date->format('Y-m-d 00:00:00');
2356
+ $interval = '1 day';
2357
+
2358
+ break;
2359
+
2360
+ case 'current_month':
2361
+ //$mystart_date->modify('0:00 first day of curent month');
2362
+ $start_date = $mystart_date->format('Y-m-01');
2363
+ $end_date = $mystart_date->format('Y-m-t');
2364
+ $full_start_date = $mystart_date->format('Y-m-01');
2365
+ $full_end_date = $mystart_date->format('Y-m-t');
2366
+ $interval = '1 day';
2367
+ $stat = 'current_month';
2368
+ break;
2369
+
2370
+ case 'last_month':
2371
+ $mystart_date->modify('0:00 first day of previous month');
2372
+ $start_date = $mystart_date->format('Y-m-d');
2373
+ $end_date = $mystart_date->format('Y-m-t');
2374
+ $full_start_date = $mystart_date->format('Y-m-d');
2375
+ $full_end_date = $mystart_date->format('Y-m-t');
2376
+ $interval = '1 day';
2377
+ $stat = 'last_month';
2378
+ break;
2379
+
2380
+ case '30':
2381
+ /*$mystart_date->modify('first day of previous month');
2382
+ $start_date = $mystart_date->format('Y-m-d');
2383
+ $full_start_date = $mystart_date->format('Y-m-d H:i:s');
2384
+
2385
+ $myend_date->modify('last day of previous month');
2386
+ $end_date = $myend_date->format('Y-m-d');
2387
+ $full_end_date = $myend_date->format('Y-m-d H:i:s');*/
2388
+
2389
+ $mystart_date->modify('-30 days');
2390
+ $start_date = $mystart_date->format('Y-m-d');
2391
+ $full_start_date = $mystart_date->format('Y-m-d 00:00:00');
2392
+
2393
+ $interval = '1 week';
2394
+ break;
2395
+
2396
+ /* case '365':
2397
+ //$mystart_date->modify(' - 1 year');
2398
+ $start_date = (new DateTime(date("Y")."-01-01"))->format('Y-m-d');
2399
+ $full_start_date = (new DateTime(date("Y")."-01-01"))->format('Y-m-d 00:00:00');
2400
+ $end_date = $mystart_date->format('Y-m-t');
2401
+ $full_end_date = $mystart_date->format('Y-m-t 23:59:59');
2402
+ $interval = '1 month';
2403
+ $stat = 'year';
2404
+ break;
2405
+ */
2406
+
2407
+ case '0':
2408
+ $full_start_date = $full_end_date = '';
2409
+ $stat = 'all';
2410
+ break;
2411
+
2412
+ default :
2413
+ $mystart_date->modify(' - ' . (AHC_VISITORS_VISITS_LIMIT - 1) . ' days');
2414
+ $start_date = $mystart_date->format('Y-m-d');
2415
+ $full_start_date = $mystart_date->format('Y-m-d 00:00:00');
2416
+ $interval = '1 day';
2417
+ break;
2418
+ }
2419
+
2420
+ $visits_visitors_data = ahcfree_get_visits_by_custom_duration_callback($full_start_date,$full_end_date,$stat);
2421
+ //print_r($visits_visitors_data);
2422
+ $response = array( 'mystart_date' => $start_date,
2423
+ 'myend_date' => $end_date,
2424
+ 'full_start_date' => $full_start_date,
2425
+ 'full_end_date' => $full_end_date,
2426
+ 'interval' => $interval,
2427
+ 'visitors_data' => json_encode($visits_visitors_data['visitors']),
2428
+ 'visits_data' => json_encode($visits_visitors_data['visits'])
2429
+ );
2430
+
2431
+ echo json_encode( $response );
2432
+ die;
2433
+ }
2434
+
2435
+
2436
+ function ahcfree_get_visits_by_custom_duration_callback( $start_date,$end_date,$stat){
2437
+ global $wpdb;
2438
+ $visits_arr = array();
2439
+ $custom_timezone_offset = ahcfree_get_current_timezone_offset();
2440
+ $custom_timezone = new DateTimeZone(ahcfree_get_timezone_string());
2441
+
2442
+ $results = false;
2443
+
2444
+ $mystart_date = new DateTime($start_date);
2445
+ $myend_date = new DateTime($end_date);
2446
+
2447
+ $total_days = date_diff( $mystart_date, $myend_date );
2448
+ $total_days = $total_days->format("%a");
2449
+
2450
+ $cond = "DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) >= DATE('". $start_date ." 00:00:00') AND DATE(CONVERT_TZ(vst_date, '" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "')) <= DATE('". $end_date ." 23:59:59')";
2451
+
2452
+ if($stat == 'year')
2453
+ {
2454
+ $sql = "SELECT DATE_FORMAT(CONVERT_TZ(vst_date,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "'),'%Y-%m') as group_date,DATE_FORMAT(CONVERT_TZ(vst_date,'".AHCFREE_SERVER_CURRENT_TIMEZONE."','".$custom_timezone_offset."'),'%Y-%m-01') as vst_date,SUM(vst_visitors) as vst_visitors,SUM(vst_visits) as vst_visits FROM ahc_visitors WHERE ". $cond." GROUP BY group_date";
2455
+ }
2456
+ if($stat == 'all')
2457
+ {
2458
+ $sql = "SELECT DATE_FORMAT(CONVERT_TZ(vst_date,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "', '" . $custom_timezone_offset . "'),'%Y-%m') as group_date,DATE_FORMAT(CONVERT_TZ(vst_date,'".AHCFREE_SERVER_CURRENT_TIMEZONE."','".$custom_timezone_offset."'),'%Y-%m-01') as vst_date,SUM(vst_visitors) as vst_visitors,SUM(vst_visits) as vst_visits FROM ahc_visitors GROUP BY group_date ORDER BY vst_date ASC";
2459
+
2460
+ }
2461
+ if($stat == '' || $stat == 'current_month' || $stat == 'last_month' )
2462
+ {
2463
+ $sql = "SELECT DATE(CONVERT_TZ(vst_date,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "')) as vst_date, SUM(vst_visits) AS vst_visits,SUM(vst_visitors) as vst_visitors FROM ahc_visitors WHERE ". $cond ." GROUP BY DATE(CONVERT_TZ(vst_date,'" . AHCFREE_SERVER_CURRENT_TIMEZONE . "','" . $custom_timezone_offset . "'))";
2464
+ }
2465
+ //echo $sql;
2466
+ $results = $wpdb->get_results($sql, OBJECT);
2467
+ if ($results !== false) {
2468
+
2469
+ if($stat == 'year')
2470
+ {
2471
+ for ($i = 1; $i <= date('n'); $i++) {
2472
+ $month = $mystart_date->format('m');
2473
+ $year = $mystart_date->format('Y');
2474
+ $total_days = cal_days_in_month(CAL_GREGORIAN, $month ,$year);
2475
 
2476
+ $visits_arr['visits'][] = array($mystart_date->format('Y-m-d'), 0);
2477
+ $visits_arr['visitors'][] = array($mystart_date->format('Y-m-d'), 0);
2478
+ $mystart_date->modify( '+'.$total_days.' days' );
2479
+ }
2480
+ }
2481
+ elseif($stat == 'all')
2482
+ {
2483
+ foreach($results as $key =>$element) {
2484
+ reset($results);
2485
+ if ($key === key($results)){
2486
+ $first_date = $element->vst_date;
2487
+ }
2488
+
2489
+ end($results);
2490
+ if ($key === key($results)){
2491
+ $last_date = $element->vst_date;
2492
+ }
2493
+ }
2494
+
2495
+ $d1 = new DateTime($first_date);
2496
+ $d2 = new DateTime($last_date);
2497
+
2498
+ if(count($results) == 1 )
2499
+ {
2500
+ $pre_d1 = new DateTime($first_date);
2501
+ $pre_d1->modify( 'first day of previous month' );
2502
+ $visits_arr['visits'][] = array($pre_d1->format( 'Y-m-d' ), 0);
2503
+ $visits_arr['visitors'][] = array($pre_d1->format( 'Y-m-d' ), 0);
2504
+ }
2505
+
2506
+ $diff = $d1->diff($d2)->m + 1;
2507
+
2508
+ for ($i = 1; $i <= $diff; $i++) {
2509
+ $visits_arr['visits'][] = array($d1->format('Y-m-d'), 0);
2510
+ $visits_arr['visitors'][] = array($d1->format('Y-m-d'), 0);
2511
+ $d1->modify( '+1 Month' );
 
 
 
 
 
2512
  }
2513
+ }
2514
+ else
2515
+ {
2516
+ if($stat == 'current_month'){
2517
+ $total_days = date('t');
2518
+ $total_days--;
2519
+ }
2520
+ if($stat == 'last_month'){
2521
+ $total_days = date('t', strtotime('first day of previous month'));
2522
+ $total_days--;
2523
+ }
2524
+ $visits_arr['visits'][] = array($mystart_date->format('Y-m-d'), 0);
2525
+ $visits_arr['visitors'][] = array($mystart_date->format('Y-m-d'), 0);
2526
+ for ($i = 1; $i <= $total_days; $i++) {
2527
+ $mystart_date->modify( '+1 Day' );
2528
+ $visits_arr['visits'][] = array($mystart_date->format('Y-m-d'), 0);
2529
+ $visits_arr['visitors'][] = array($mystart_date->format('Y-m-d'), 0);
2530
+ }
2531
+ }
2532
+ //print_r($visits_arr['visits']);
2533
+ foreach( $visits_arr['visits'] as $key=>$visits ){
2534
+ foreach ($results as $r) {
2535
+ if( $visits[0] == $r->vst_date )
2536
+ {
2537
+ $visits_arr['visits'][$key][1] = $r->vst_visits;
2538
+ }
2539
+ }
2540
+ }
2541
+
2542
+ foreach( $visits_arr['visitors'] as $key=>$visits ){
2543
+ foreach ($results as $r) {
2544
+ if( $visits[0] == $r->vst_date )
2545
+ {
2546
+ $visits_arr['visitors'][$key][1] = $r->vst_visitors;
2547
+ }
2548
+ }
2549
+ }
2550
+ }
2551
+ //echo $wpdb->last_query;
2552
+ return $visits_arr;
2553
+
2554
+ }
2555
+ function ahcfree_admin_notice_to_set_timezone(){
2556
+ $class = 'notice notice-error';
2557
+ $name = 'Visitor Traffic Real Time Statistics free';
2558
+ $message = sprintf( __( 'Please set timezone from <a href="%s">here</a>' ), site_url('wp-admin/admin.php?page=ahc_hits_counter_settings') );
2559
+
2560
+ printf( '<div class="%1$s"><h3>%2$s</h3><p>%3$s</p></div>', esc_attr( $class ), $name, $message );
2561
+
2562
+ }
2563
+ ?>
images/247.png ADDED
Binary file
images/24_7.ico ADDED
Binary file
images/Icon-user.png ADDED
Binary file
images/Spinner-1s-200px.svg ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <svg class="lds-spinner" width="200px" height="200px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" style="background: none;"><g transform="rotate(0 50 50)">
2
+ <rect x="47" y="24" rx="9.4" ry="4.8" width="6" height="12" fill="#1d0e0b">
3
+ <animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="1s" begin="-0.9166666666666666s" repeatCount="indefinite"></animate>
4
+ </rect>
5
+ </g><g transform="rotate(30 50 50)">
6
+ <rect x="47" y="24" rx="9.4" ry="4.8" width="6" height="12" fill="#1d0e0b">
7
+ <animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="1s" begin="-0.8333333333333334s" repeatCount="indefinite"></animate>
8
+ </rect>
9
+ </g><g transform="rotate(60 50 50)">
10
+ <rect x="47" y="24" rx="9.4" ry="4.8" width="6" height="12" fill="#1d0e0b">
11
+ <animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="1s" begin="-0.75s" repeatCount="indefinite"></animate>
12
+ </rect>
13
+ </g><g transform="rotate(90 50 50)">
14
+ <rect x="47" y="24" rx="9.4" ry="4.8" width="6" height="12" fill="#1d0e0b">
15
+ <animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="1s" begin="-0.6666666666666666s" repeatCount="indefinite"></animate>
16
+ </rect>
17
+ </g><g transform="rotate(120 50 50)">
18
+ <rect x="47" y="24" rx="9.4" ry="4.8" width="6" height="12" fill="#1d0e0b">
19
+ <animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="1s" begin="-0.5833333333333334s" repeatCount="indefinite"></animate>
20
+ </rect>
21
+ </g><g transform="rotate(150 50 50)">
22
+ <rect x="47" y="24" rx="9.4" ry="4.8" width="6" height="12" fill="#1d0e0b">
23
+ <animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="1s" begin="-0.5s" repeatCount="indefinite"></animate>
24
+ </rect>
25
+ </g><g transform="rotate(180 50 50)">
26
+ <rect x="47" y="24" rx="9.4" ry="4.8" width="6" height="12" fill="#1d0e0b">
27
+ <animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="1s" begin="-0.4166666666666667s" repeatCount="indefinite"></animate>
28
+ </rect>
29
+ </g><g transform="rotate(210 50 50)">
30
+ <rect x="47" y="24" rx="9.4" ry="4.8" width="6" height="12" fill="#1d0e0b">
31
+ <animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="1s" begin="-0.3333333333333333s" repeatCount="indefinite"></animate>
32
+ </rect>
33
+ </g><g transform="rotate(240 50 50)">
34
+ <rect x="47" y="24" rx="9.4" ry="4.8" width="6" height="12" fill="#1d0e0b">
35
+ <animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="1s" begin="-0.25s" repeatCount="indefinite"></animate>
36
+ </rect>
37
+ </g><g transform="rotate(270 50 50)">
38
+ <rect x="47" y="24" rx="9.4" ry="4.8" width="6" height="12" fill="#1d0e0b">
39
+ <animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="1s" begin="-0.16666666666666666s" repeatCount="indefinite"></animate>
40
+ </rect>
41
+ </g><g transform="rotate(300 50 50)">
42
+ <rect x="47" y="24" rx="9.4" ry="4.8" width="6" height="12" fill="#1d0e0b">
43
+ <animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="1s" begin="-0.08333333333333333s" repeatCount="indefinite"></animate>
44
+ </rect>
45
+ </g><g transform="rotate(330 50 50)">
46
+ <rect x="47" y="24" rx="9.4" ry="4.8" width="6" height="12" fill="#1d0e0b">
47
+ <animate attributeName="opacity" values="1;0" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animate>
48
+ </rect>
49
+ </g></svg>
images/VisualEditor_-_Icon_-_Search.svg.png ADDED
Binary file
images/browsers_nodata.png DELETED
Binary file
images/contact-center-reporting-icon.png DELETED
Binary file
images/decrease.png ADDED
Binary file
images/down.png ADDED
Binary file
images/increase.png ADDED
Binary file
images/latestwords_nodata.png DELETED
Binary file
images/live.gif ADDED
Binary file
images/logo.png ADDED
Binary file
images/myheaderbg.png DELETED
Binary file
images/new_ticket_title.jpg ADDED
Binary file
images/newticket.png ADDED
Binary file
images/online.png ADDED
Binary file
images/openW.jpg ADDED
Binary file
images/openW.png ADDED
Binary file
images/output_ZD6GUg-1-2.gif ADDED
Binary file
images/plugin-1.png ADDED
Binary file
images/plugin-2.png ADDED
Binary file
images/plugin-3.png ADDED
Binary file
images/plugin-4.png ADDED
Binary file
images/plugin-5.png ADDED
Binary file
images/plugin-6.png ADDED
Binary file
images/recent_nodata.png DELETED
Binary file
images/se_nodata.png DELETED
Binary file
images/searchengin.png ADDED
Binary file
images/searchengins.png ADDED
Binary file
images/settings.jpg ADDED
Binary file
images/stats.png ADDED
Binary file
images/stats2.png ADDED
Binary file
images/stats2.psd ADDED
Binary file
images/stats3.png ADDED
Binary file
images/topref_nodata.png DELETED
Binary file
images/up.png ADDED
Binary file
images/upgrade.png DELETED
Binary file
images/visitors.png ADDED
Binary file
images/visits.png ADDED
Binary file
images/vtrts.png CHANGED
Binary file
images/vtrts_ads.gif DELETED
Binary file
images/wordpress-plugins.png ADDED
Binary file
init.php CHANGED
@@ -1,15 +1,24 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
2
 
3
- define('AHC_DS', DIRECTORY_SEPARATOR);
4
- define('AHC_PLUGIN_SUPDIRE_FILE', dirname(__FILE__).'WP_Stats_Plus.php');
5
 
6
- require_once("settings.php");
7
  require_once("WPHitsCounter.php");
8
 
9
- register_activation_hook(AHC_PLUGIN_MAIN_FILE, 'ahc_set_default_options');
10
- register_deactivation_hook(AHC_PLUGIN_MAIN_FILE, 'ahc_unset_default_options');
 
 
11
 
12
- class Globals{
13
 
14
  static $plugin_options = array();
15
  static $lang = NULL;
@@ -18,32 +27,53 @@ class Globals{
18
  static $page_title = NULL;
19
  }
20
 
21
- Globals::$plugin_options = get_option('ahc_wp_hits_counter_options');
22
- Globals::$lang = 'en';
23
 
24
 
 
25
 
26
-
27
-
28
- $admincore = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  if (isset($_GET['page'])) $admincore = $_GET['page'];
30
- if( is_admin() && $admincore == 'ahc_hits_counter_menu')
31
  {
32
- add_action('admin_enqueue_scripts', 'ahc_include_scripts');
33
  }
34
 
35
- //add_action('admin_bar_menu', 'vtrts_add_items', 90);
36
- //$plugin = plugin_basename( __FILE__ );
37
- //add_filter( "plugin_action_links_$plugin", 'vtrtsp_plugin_add_settings_link' );
38
-
39
 
 
 
40
 
41
- add_action('parse_request', 'ahc_track_visitor', 1);
42
- add_action('admin_menu', 'ahc_create_admin_menu_link');
43
-
44
- // creating Ajax call for WordPress
45
- add_action( 'wp_ajax_nopriv_ahc_HideMessageAjaxFunction', 'ahc_HideMessageAjaxFunction' );
46
- add_action( 'wp_ajax_ahc_HideMessageAjaxFunction', 'ahc_HideMessageAjaxFunction' );
47
-
48
 
49
- ?>
 
 
 
 
1
  <?php
2
+ define('AHC_RECENT_VISITORS_LIMIT', 20);
3
+ define('AHCFREE_RECENT_KEYWORDS_LIMIT', 20);
4
+
5
+ define('AHCFREE_TOP_REFERING_SITES_LIMIT', 20); // used in ahcfree_get_top_refering_sites
6
+ define('AHCFREE_TOP_COUNTRIES_LIMIT', 20); // used in ahcfree_get_top_countries
7
+
8
+ define('AHCFREE_TRAFFIC_BY_TITLE_LIMIT', 20);
9
+ define('IS_DEMO', true);
10
+ define('AHCFREE_DS', DIRECTORY_SEPARATOR);
11
+ define('AHCFREE_PLUGIN_SUPDIRE_FILE', dirname(__FILE__).'visitors-traffic-real-time-statistics.php');
12
 
 
 
13
 
 
14
  require_once("WPHitsCounter.php");
15
 
16
+ register_activation_hook(AHCFREE_PLUGIN_MAIN_FILE, 'ahcfree_set_default_options');
17
+ register_deactivation_hook(AHCFREE_PLUGIN_MAIN_FILE, 'ahcfree_unset_default_options');
18
+
19
+
20
 
21
+ class Globalsahcfree{
22
 
23
  static $plugin_options = array();
24
  static $lang = NULL;
27
  static $page_title = NULL;
28
  }
29
 
30
+ Globalsahcfree::$plugin_options = get_option('ahcfree_wp_hits_counter_options');
31
+ Globalsahcfree::$lang = 'en';
32
 
33
 
34
+ $ahcfree_get_save_settings = ahcfree_get_save_settings();
35
 
36
+ if($ahcfree_get_save_settings == false or empty($ahcfree_get_save_settings))
37
+ {
38
+ ahcfree_add_settings();
39
+ }
40
+
41
+ if(isset($ahcfree_get_save_settings[0]))
42
+ {
43
+ $hits_days = $ahcfree_get_save_settings[0]->set_hits_days;
44
+ $ajax_check = ($ahcfree_get_save_settings[0]->set_ajax_check * 1000);
45
+ $set_ips = $ahcfree_get_save_settings[0]->set_ips;
46
+ $set_google_map = $ahcfree_get_save_settings[0]->set_google_map;
47
+ }else{
48
+ $hits_days = 14;
49
+ $ajax_check = 15;
50
+ $set_ips = '';
51
+ $set_google_map = 'today_visitors';
52
+ }
53
+
54
+ define('AHC_VISITORS_VISITS_LIMIT', $hits_days );
55
+ define('AHCFREE_AJAX_CHECK', $ajax_check);
56
+ define('AHCFREE_EXCLUDE_IPS', $set_ips);
57
+
58
+
59
+
60
+ $admincore = '';
61
  if (isset($_GET['page'])) $admincore = $_GET['page'];
62
+ if( is_admin() && $admincore == 'ahc_hits_counter_menu_free')
63
  {
64
+ add_action('admin_enqueue_scripts', 'ahcfree_include_scripts');
65
  }
66
 
 
 
 
 
67
 
68
+ add_action('admin_menu', 'ahcfree_create_admin_menu_link');
69
+ add_action('wp_ajax_ahcfree_get_hits_by_custom_duration','ahcfree_get_hits_by_custom_duration_callback');
70
 
71
+ define('AHCFREE_SERVER_CURRENT_TIMEZONE','+00:00');
72
+ $stats_current_timezone = get_option('ahcfree_custom_timezone');
73
+ $stats_current_timezone = !empty($stats_current_timezone) ? $stats_current_timezone : ahcfree_GetWPTimezoneString();
 
 
 
 
74
 
75
+ /*
76
+ if($stats_current_timezone !='')
77
+ date_default_timezone_set($stats_current_timezone);
78
+ */
79
+ ?>
js/ahc_jqscripts.js ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var colors = ['#DB6946', '#C14543', '#445060', '#395953', '#6C8C80', '#829AB5', '#BF807A', '#BF0000', '#006BB7', '#EC732C', '#BF3D27', '#A6375F',
2
+ '#8C6D46', '#326149', '#802B35', '#8A3842', '#366D73', '#4D6173', '#4A4659', '#C9D65B', '#F45552', '#F3CC5E', '#F29B88', '#D96941',
3
+ '#484F73', '#C9AB81', '#F5655C', '#F0C480'];
4
+
5
+
6
+ var $ = jQuery;
7
+ var save_method; //for save method string
8
+ var host=window.location.hostname;
9
+ var fullpath=window.location.pathname;
10
+ var fullparam=window.location.search.split('&');
11
+
12
+ var firstparam=fullparam[0];
13
+ var secoundparam=fullparam[1];
14
+
15
+
16
+ function checkTime(i) {
17
+ if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
18
+ return i;
19
+ }
20
+
21
+
22
+ jQuery(document).ready(function () {
23
+
24
+
25
+ setInterval(function(){
26
+
27
+ var now = new Date();
28
+ var year = now.getFullYear();
29
+ var month = now.getMonth()+1;
30
+ var day = now.getDate();
31
+ var hour = now.getHours();
32
+ var minute = now.getMinutes();
33
+ var second = now.getSeconds();
34
+ if(month.toString().length == 1) {
35
+ month = '0'+month;
36
+ }
37
+ if(day.toString().length == 1) {
38
+ day = '0'+day;
39
+ }
40
+ if(hour.toString().length == 1) {
41
+ hour = '0'+hour;
42
+ }
43
+ if(minute.toString().length == 1) {
44
+ minute = '0'+minute;
45
+ }
46
+ if(second.toString().length == 1) {
47
+ second = '0'+second;
48
+ }
49
+ var dateTime = year+'/'+month+'/'+day+' '+hour+':'+minute+':'+second;
50
+
51
+ jQuery('#ahcfree_currenttime').html(dateTime); }, 500);
52
+
53
+
54
+
55
+ jQuery(document).on('click', '.SwalBtn1', function() {
56
+ swal.clickConfirm();
57
+ });
58
+ jQuery(document).on('click', '.SwalBtn2', function() {
59
+ window.open(
60
+ "https://www.wp-buy.com/product/visitors-traffic-real-time-statistics-pro/?popup=1",
61
+ '_blank'
62
+ );
63
+
64
+ swal.clickConfirm();
65
+ });
66
+ jQuery(document).on('click', '.SwalBtn3', function() {
67
+ localStorage.setItem("ahcfreemsg", "1");
68
+ swal.clickConfirm();
69
+ });
70
+
71
+ if(localStorage && (firstparam=="?page=ahc_hits_counter_menu_free"))
72
+ {
73
+
74
+
75
+ if (!localStorage.getItem("ahcfreemsg")==true)
76
+ {
77
+
78
+ swal({
79
+ title: '',
80
+ text: '',
81
+ imageUrl: 'https://www.wp-buy.com/wp-content/uploads/2018/10/output_ZD6GUg-1-2.gif',
82
+ imageWidth: 'auto',
83
+ imageHeight: 'auto',
84
+ imageAlt: 'Need more statistics, GEO locations & online counter?',
85
+ animation: true,
86
+ customClass: 'swal-noscroll',
87
+ allowEscapeKey:true,
88
+ showCancelButton: false,
89
+ showConfirmButton: false,
90
+ html: '<center><button type="button" role="button" class="confirm btn btn-lg btn-success SwalBtn2">' + 'Upgrade to pro' + '</button>&nbsp;&nbsp;' +
91
+ '<button type="button" role="button" class="cancel btn btn-info SwalBtn1">' + 'Close' + '</button>&nbsp;&nbsp;'+
92
+ '<button type="button" role="button" class="confirm btn btn-warning SwalBtn3">' + "Dismiss" + '</button></center>'
93
+ });
94
+
95
+
96
+
97
+
98
+
99
+ }
100
+ }
101
+
102
+
103
+
104
+
105
+
106
+ });
107
+
108
+
109
+
110
+
111
+ //------------------------------------------------------------------------------
112
+ function convertToNumeric(data){
113
+ if(data instanceof Array){
114
+ for(var index in data){
115
+ data[index] = Number(data[index]);
116
+ }
117
+ } else{
118
+ data = Number(data);
119
+ }
120
+ return data;
121
+ }
122
+ //------------------------------------------------------------------------------
123
+ function getRandomElementFromArray(array){
124
+ var ranIndex = Math.floor(Math.random() * array.length);
125
+ return array[ranIndex];
126
+ }
127
+ //------------------------------------------------------------------------------
128
+ function drawVisitsLineChart(visitsData){
129
+ var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
130
+
131
+ var barChartData = {
132
+ labels : visitsData.data.dates,
133
+ datasets : [
134
+ {
135
+ label: "Visitors",
136
+ barShowStroke: false,
137
+ fillColor : "rgba(75,178,1970,.5)",
138
+ strokeColor : "rgba(75,178,1970,.5)",
139
+ highlightFill: "rgba(220,220,220,0.75)",
140
+ highlightStroke: "rgba(220,220,220,1)",
141
+ data : visitsData.data.visitors
142
+ },
143
+ {
144
+ label: "Visits",
145
+ barShowStroke: false,
146
+ fillColor : "rgba(234,162,40,0.5)",
147
+ strokeColor : "rgba(234,162,40,0.5)",
148
+ highlightFill : "rgba(151,187,205,0.75)",
149
+ highlightStroke : "rgba(151,187,205,1)",
150
+ data : visitsData.data.visits
151
+ }
152
+ ]
153
+
154
+ }
155
+ var ctx = document.getElementById("visitorsVisitsChart").getContext("2d");
156
+ window.myBar = new Chart(ctx).Bar(barChartData, {
157
+ responsive : true
158
+ });
159
+ }
160
+ //------------------------------------------------------------------------------
161
+
162
+
163
+ function drawBrowsersBieChart(browsersData){
164
+
165
+
166
+ if(browsersData.length > 0)
167
+ {
168
+
169
+ var brsBieChartData = [];
170
+ var brsBieChartDataLables = [];
171
+ brsBieChartDataLables[0] = '';
172
+ brsBieChartDataLables[1] = '';
173
+ brsBieChartDataLables[2] = '';
174
+ brsBieChartDataLables[3] = '';
175
+ brsBieChartDataLables[4] = '';
176
+
177
+ for(var i = 0; i < browsersData.length; i++){
178
+ var color = getRandomElementFromArray(colors);
179
+ var value = Number(browsersData[i].hits);
180
+ brsBieChartData[i] = value;
181
+ brsBieChartDataLables[i] = browsersData[i].bsr_name;
182
+
183
+
184
+
185
+ }
186
+
187
+
188
+
189
+
190
+
191
+
192
+ var config = {
193
+ type: 'pie',
194
+ data: {
195
+ datasets: [{
196
+ data: [
197
+ brsBieChartData[0],
198
+ brsBieChartData[1],
199
+ brsBieChartData[2],
200
+ brsBieChartData[3],
201
+ brsBieChartData[4]
202
+
203
+ ],
204
+ backgroundColor: [
205
+ window.chartColors.red,
206
+ window.chartColors.orange,
207
+ window.chartColors.yellow,
208
+ window.chartColors.green,
209
+ window.chartColors.blue,
210
+ ],
211
+ label: 'Browser'
212
+ }],
213
+ labels: [
214
+
215
+ brsBieChartDataLables[0],
216
+ brsBieChartDataLables[1],
217
+ brsBieChartDataLables[2],
218
+ brsBieChartDataLables[3],
219
+ brsBieChartDataLables[4],
220
+
221
+
222
+ ]
223
+ },
224
+ options: {
225
+ responsive: true
226
+ }
227
+ };
228
+
229
+ window.onload = function() {
230
+ var ctx = document.getElementById('brsBiechartContainer').getContext('2d');
231
+ window.myPie = new Chart(ctx, config);
232
+ };
233
+
234
+ }else{
235
+
236
+ document.getElementById('brsBiechartContainer_msg').innerHTML = '<center>No data to display</center>';
237
+ }
238
+
239
+
240
+
241
+ }
242
+
243
+
244
+ //------------------------------------------------------------------------------
245
+ function drawSrhEngVstLineChart(srhEngVisitsData){
246
+
247
+
248
+ if(srhEngVisitsData.length > 0)
249
+ {
250
+ var srhBieChartData = [];
251
+ var srhBieChartDataLables = [];
252
+ srhBieChartDataLables[0] = '';
253
+ srhBieChartDataLables[1] = '';
254
+ srhBieChartDataLables[2] = '';
255
+ srhBieChartDataLables[3] = '';
256
+ srhBieChartDataLables[4] = '';
257
+
258
+ for(var i = 0; i < srhEngVisitsData.length; i++){
259
+ var color = getRandomElementFromArray(colors);
260
+ var value = Number(srhEngVisitsData[i].hits);
261
+ srhBieChartData[i] = value;
262
+ srhBieChartDataLables[i] = srhEngVisitsData[i].bsr_name;
263
+
264
+
265
+ }
266
+
267
+
268
+
269
+
270
+
271
+
272
+ var config = {
273
+ type: 'pie',
274
+ data: {
275
+ datasets: [{
276
+ data: [
277
+ srhBieChartData[0],
278
+ srhBieChartData[1],
279
+ srhBieChartData[2],
280
+ srhBieChartData[3],
281
+ srhBieChartData[4]
282
+
283
+ ],
284
+ backgroundColor: [
285
+ window.chartColors.yellow,
286
+ window.chartColors.green,
287
+ window.chartColors.blue,
288
+ window.chartColors.red,
289
+ window.chartColors.orange,
290
+
291
+ ],
292
+ label: 'Search Engine'
293
+ }],
294
+ labels: [
295
+
296
+ srhBieChartDataLables[0],
297
+ srhBieChartDataLables[1],
298
+ srhBieChartDataLables[2],
299
+ srhBieChartDataLables[3],
300
+ srhBieChartDataLables[4],
301
+
302
+
303
+ ]
304
+ },
305
+ options: {
306
+ responsive: true
307
+ }
308
+ };
309
+
310
+ var ctx2 = document.getElementById('srhEngBieChartContainer').getContext('2d');
311
+ window.myPie = new Chart(ctx2, config);
312
+ window.myPie = new Chart(ctx2, config);
313
+ }else{
314
+
315
+ document.getElementById('srhEngBieChartContainer_msg').innerHTML = '<center>No data to display</center>';
316
+ }
317
+ }
318
+
319
+
320
+ function isEmpty(val){
321
+ return (val == null || val == 0 || val == '' || val == '0');
322
+ }
323
+
324
+ //------------------------------------------------------------------------------
325
+ function countVisits(arr){
326
+ var count = 0;
327
+ for(var i = 0; i < arr.length; i++){
328
+ count += Number(arr[i]);
329
+ }
330
+ return count;
331
+ }
332
+ //------------------------------------------------------------------------------
333
+
334
+ jQuery(document).ready(function () {
335
+
336
+
337
+ if(typeof browsersData !== 'undefined')
338
+ {
339
+
340
+ //------------------------------------------
341
+ //if(visitsData.success && typeof visitsData.data != 'undefined'){
342
+ var duration = jQuery('#hits-duration').val();
343
+ drawVisitsLineChart( mystart_date, myend_date, '1 day', visitors_data, visits_data, duration );
344
+ //}
345
+ //------------------------------------------
346
+ if (browsersData.success && typeof browsersData.data != 'undefined' && typeof drawBrowsersBieChart === "function") {
347
+ drawBrowsersBieChart(browsersData.data);
348
+ }
349
+ //------------------------------------------
350
+ if (srhEngVisitsData.success && typeof srhEngVisitsData.data != 'undefined' && typeof drawSrhEngVstLineChart === "function") {
351
+
352
+ drawSrhEngVstLineChart(srhEngVisitsData.data);
353
+ }
354
+ //------------------------------------------
355
+
356
+ //------------------------------------------
357
+ }
358
+ });
js/front.js ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var pageid = ahcfree_ajax_front.page_id;
2
+ var page_id = (pageid.length > 0) ? pageid : '';
3
+ var pagetitle = ahcfree_ajax_front.page_title;
4
+ var page_title = (pagetitle.length > 0) ? pagetitle : '';
5
+ var posttype = ahcfree_ajax_front.post_type;
6
+ var post_type = (posttype.length > 0) ? posttype : '';
7
+ var referer = document.referrer;
8
+ var useragent = window.navigator.userAgent;
9
+ var servername = location.hostname;
10
+ var hostname = location.host;
11
+ var request_uri = location.pathname.substring(1);
12
+
13
+ var xhttp = new XMLHttpRequest();
14
+
15
+ xhttp.open("POST", ahcfree_ajax_front.ajax_url, true);
16
+ xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
17
+ xhttp.send("action=ahcfree_track_visitor&page_id="+ page_id +"&page_title="+ page_title + "&post_type="+ post_type + "&referer="+ referer +"&useragent="+ useragent +"&servername="+ servername +"&hostname="+ hostname +"&request_uri="+request_uri);
18
+ /*
19
+
20
+ jQuery(document).ready(function ()
21
+ {
22
+ var pageid = ahcfree_ajax_front.page_id;
23
+ var page_id = (pageid.length > 0) ? pageid : '';
24
+ var pagetitle = ahcfree_ajax_front.page_title;
25
+ var page_title = (pagetitle.length > 0) ? pagetitle : '';
26
+ var posttype = ahcfree_ajax_front.post_type;
27
+ var post_type = (posttype.length > 0) ? posttype : '';
28
+ var referer = document.referrer;
29
+ var useragent = window.navigator.userAgent;
30
+ var servername = location.hostname;
31
+ var hostname = location.host;
32
+ var request_uri = location.pathname.substring(1);
33
+
34
+ jQuery.ajax({
35
+ type: 'POST',
36
+ url : ahcfree_ajax_front.ajax_url,
37
+ data: {
38
+ 'action': 'ahcfree_track_visitor',
39
+ 'page_id': page_id,
40
+ 'page_title': page_title,
41
+ 'post_type': post_type,
42
+ 'referer': referer,
43
+ 'useragent':useragent,
44
+ 'servername':servername,
45
+ 'hostname':hostname,
46
+ 'request_uri':request_uri
47
+ },
48
+ success: function(data){
49
+ console.log(data);
50
+ },
51
+ error: function(data)
52
+ {
53
+ console.log(data);
54
+ }
55
+ });
56
+ });
57
+ */
58
+
59
+
js/jqplot.canvasAxisLabelRenderer.min.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com
2
+ jsDate | (c) 2010-2013 Chris Leonello
3
+ */(function(a){a.jqplot.CanvasAxisLabelRenderer=function(b){this.angle=0;this.axis;this.show=true;this.showLabel=true;this.label="";this.fontFamily='"Trebuchet MS", Arial, Helvetica, sans-serif';this.fontSize="11pt";this.fontWeight="normal";this.fontStretch=1;this.textColor="#666666";this.enableFontSupport=true;this.pt2px=null;this._elem;this._ctx;this._plotWidth;this._plotHeight;this._plotDimensions={height:null,width:null};a.extend(true,this,b);if(b.angle==null&&this.axis!="xaxis"&&this.axis!="x2axis"){this.angle=-90}var c={fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily};if(this.pt2px){c.pt2px=this.pt2px}if(this.enableFontSupport){if(a.jqplot.support_canvas_text()){this._textRenderer=new a.jqplot.CanvasFontRenderer(c)}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}};a.jqplot.CanvasAxisLabelRenderer.prototype.init=function(b){a.extend(true,this,b);this._textRenderer.init({fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily})};a.jqplot.CanvasAxisLabelRenderer.prototype.getWidth=function(d){if(this._elem){return this._elem.outerWidth(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.sin(f.angle)*e)+Math.abs(Math.cos(f.angle)*c);return b}};a.jqplot.CanvasAxisLabelRenderer.prototype.getHeight=function(d){if(this._elem){return this._elem.outerHeight(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.cos(f.angle)*e)+Math.abs(Math.sin(f.angle)*c);return b}};a.jqplot.CanvasAxisLabelRenderer.prototype.getAngleRad=function(){var b=this.angle*Math.PI/180;return b};a.jqplot.CanvasAxisLabelRenderer.prototype.draw=function(c,f){if(this._elem){if(a.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==undefined){window.G_vmlCanvasManager.uninitElement(this._elem.get(0))}this._elem.emptyForce();this._elem=null}var e=f.canvasManager.getCanvas();this._textRenderer.setText(this.label,c);var b=this.getWidth(c);var d=this.getHeight(c);e.width=b;e.height=d;e.style.width=b;e.style.height=d;e=f.canvasManager.initCanvas(e);this._elem=a(e);this._elem.css({position:"absolute"});this._elem.addClass("jqplot-"+this.axis+"-label");e=null;return this._elem};a.jqplot.CanvasAxisLabelRenderer.prototype.pack=function(){this._textRenderer.draw(this._elem.get(0).getContext("2d"),this.label)}})(jQuery);
js/jqplot.canvasAxisTickRenderer.min.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com
2
+ jsDate | (c) 2010-2013 Chris Leonello
3
+ */(function(a){a.jqplot.CanvasAxisTickRenderer=function(b){this.mark="outside";this.showMark=true;this.showGridline=true;this.isMinorTick=false;this.angle=0;this.markSize=4;this.show=true;this.showLabel=true;this.labelPosition="auto";this.label="";this.value=null;this._styles={};this.formatter=a.jqplot.DefaultTickFormatter;this.formatString="";this.prefix="";this.fontFamily='"Trebuchet MS", Arial, Helvetica, sans-serif';this.fontSize="10pt";this.fontWeight="normal";this.fontStretch=1;this.textColor="#666666";this.enableFontSupport=true;this.pt2px=null;this._elem;this._ctx;this._plotWidth;this._plotHeight;this._plotDimensions={height:null,width:null};a.extend(true,this,b);var c={fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily};if(this.pt2px){c.pt2px=this.pt2px}if(this.enableFontSupport){if(a.jqplot.support_canvas_text()){this._textRenderer=new a.jqplot.CanvasFontRenderer(c)}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}};a.jqplot.CanvasAxisTickRenderer.prototype.init=function(b){a.extend(true,this,b);this._textRenderer.init({fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily})};a.jqplot.CanvasAxisTickRenderer.prototype.getWidth=function(d){if(this._elem){return this._elem.outerWidth(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.sin(f.angle)*e)+Math.abs(Math.cos(f.angle)*c);return b}};a.jqplot.CanvasAxisTickRenderer.prototype.getHeight=function(d){if(this._elem){return this._elem.outerHeight(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.cos(f.angle)*e)+Math.abs(Math.sin(f.angle)*c);return b}};a.jqplot.CanvasAxisTickRenderer.prototype.getTop=function(b){if(this._elem){return this._elem.position().top}else{return null}};a.jqplot.CanvasAxisTickRenderer.prototype.getAngleRad=function(){var b=this.angle*Math.PI/180;return b};a.jqplot.CanvasAxisTickRenderer.prototype.setTick=function(b,d,c){this.value=b;if(c){this.isMinorTick=true}return this};a.jqplot.CanvasAxisTickRenderer.prototype.draw=function(c,f){if(!this.label){this.label=this.prefix+this.formatter(this.formatString,this.value)}if(this._elem){if(a.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==undefined){window.G_vmlCanvasManager.uninitElement(this._elem.get(0))}this._elem.emptyForce();this._elem=null}var e=f.canvasManager.getCanvas();this._textRenderer.setText(this.label,c);var b=this.getWidth(c);var d=this.getHeight(c);e.width=b;e.height=d;e.style.width=b;e.style.height=d;e.style.textAlign="left";e.style.position="absolute";e=f.canvasManager.initCanvas(e);this._elem=a(e);this._elem.css(this._styles);this._elem.addClass("jqplot-"+this.axis+"-tick");e=null;return this._elem};a.jqplot.CanvasAxisTickRenderer.prototype.pack=function(){this._textRenderer.draw(this._elem.get(0).getContext("2d"),this.label)}})(jQuery);
js/jqplot.canvasTextRenderer.min.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com
2
+ jsDate | (c) 2010-2013 Chris Leonello
3
+ */(function(a){a.jqplot.CanvasTextRenderer=function(b){this.fontStyle="normal";this.fontVariant="normal";this.fontWeight="normal";this.fontSize="10px";this.fontFamily="sans-serif";this.fontStretch=1;this.fillStyle="#666666";this.angle=0;this.textAlign="start";this.textBaseline="alphabetic";this.text;this.width;this.height;this.pt2px=1.28;a.extend(true,this,b);this.normalizedFontSize=this.normalizeFontSize(this.fontSize);this.setHeight()};a.jqplot.CanvasTextRenderer.prototype.init=function(b){a.extend(true,this,b);this.normalizedFontSize=this.normalizeFontSize(this.fontSize);this.setHeight()};a.jqplot.CanvasTextRenderer.prototype.normalizeFontSize=function(b){b=String(b);var c=parseFloat(b);if(b.indexOf("px")>-1){return c/this.pt2px}else{if(b.indexOf("pt")>-1){return c}else{if(b.indexOf("em")>-1){return c*12}else{if(b.indexOf("%")>-1){return c*12/100}else{return c/this.pt2px}}}}};a.jqplot.CanvasTextRenderer.prototype.fontWeight2Float=function(b){if(Number(b)){return b/400}else{switch(b){case"normal":return 1;break;case"bold":return 1.75;break;case"bolder":return 2.25;break;case"lighter":return 0.75;break;default:return 1;break}}};a.jqplot.CanvasTextRenderer.prototype.getText=function(){return this.text};a.jqplot.CanvasTextRenderer.prototype.setText=function(c,b){this.text=c;this.setWidth(b);return this};a.jqplot.CanvasTextRenderer.prototype.getWidth=function(b){return this.width};a.jqplot.CanvasTextRenderer.prototype.setWidth=function(c,b){if(!b){this.width=this.measure(c,this.text)}else{this.width=b}return this};a.jqplot.CanvasTextRenderer.prototype.getHeight=function(b){return this.height};a.jqplot.CanvasTextRenderer.prototype.setHeight=function(b){if(!b){this.height=this.normalizedFontSize*this.pt2px}else{this.height=b}return this};a.jqplot.CanvasTextRenderer.prototype.letter=function(b){return this.letters[b]};a.jqplot.CanvasTextRenderer.prototype.ascent=function(){return this.normalizedFontSize};a.jqplot.CanvasTextRenderer.prototype.descent=function(){return 7*this.normalizedFontSize/25};a.jqplot.CanvasTextRenderer.prototype.measure=function(d,g){var f=0;var b=g.length;for(var e=0;e<b;e++){var h=this.letter(g.charAt(e));if(h){f+=h.width*this.normalizedFontSize/25*this.fontStretch}}return f};a.jqplot.CanvasTextRenderer.prototype.draw=function(s,n){var r=0;var o=this.height*0.72;var p=0;var l=n.length;var k=this.normalizedFontSize/25;s.save();var h,f;if((-Math.PI/2<=this.angle&&this.angle<=0)||(Math.PI*3/2<=this.angle&&this.angle<=Math.PI*2)){h=0;f=-Math.sin(this.angle)*this.width}else{if((0<this.angle&&this.angle<=Math.PI/2)||(-Math.PI*2<=this.angle&&this.angle<=-Math.PI*3/2)){h=Math.sin(this.angle)*this.height;f=0}else{if((-Math.PI<this.angle&&this.angle<-Math.PI/2)||(Math.PI<=this.angle&&this.angle<=Math.PI*3/2)){h=-Math.cos(this.angle)*this.width;f=-Math.sin(this.angle)*this.width-Math.cos(this.angle)*this.height}else{if((-Math.PI*3/2<this.angle&&this.angle<Math.PI)||(Math.PI/2<this.angle&&this.angle<Math.PI)){h=Math.sin(this.angle)*this.height-Math.cos(this.angle)*this.width;f=-Math.cos(this.angle)*this.height}}}}s.strokeStyle=this.fillStyle;s.fillStyle=this.fillStyle;s.translate(h,f);s.rotate(this.angle);s.lineCap="round";var t=(this.normalizedFontSize>30)?2:2+(30-this.normalizedFontSize)/20;s.lineWidth=t*k*this.fontWeight2Float(this.fontWeight);for(var g=0;g<l;g++){var m=this.letter(n.charAt(g));if(!m){continue}s.beginPath();var e=1;var b=0;for(var d=0;d<m.points.length;d++){var q=m.points[d];if(q[0]==-1&&q[1]==-1){e=1;continue}if(e){s.moveTo(r+q[0]*k*this.fontStretch,o-q[1]*k);e=false}else{s.lineTo(r+q[0]*k*this.fontStretch,o-q[1]*k)}}s.stroke();r+=m.width*k*this.fontStretch}s.restore();return p};a.jqplot.CanvasTextRenderer.prototype.letters={" ":{width:16,points:[]},"!":{width:10,points:[[5,21],[5,7],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]]},'"':{width:16,points:[[4,21],[4,14],[-1,-1],[12,21],[12,14]]},"#":{width:21,points:[[11,25],[4,-7],[-1,-1],[17,25],[10,-7],[-1,-1],[4,12],[18,12],[-1,-1],[3,6],[17,6]]},"$":{width:20,points:[[8,25],[8,-4],[-1,-1],[12,25],[12,-4],[-1,-1],[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]]},"%":{width:24,points:[[21,21],[3,0],[-1,-1],[8,21],[10,19],[10,17],[9,15],[7,14],[5,14],[3,16],[3,18],[4,20],[6,21],[8,21],[10,20],[13,19],[16,19],[19,20],[21,21],[-1,-1],[17,7],[15,6],[14,4],[14,2],[16,0],[18,0],[20,1],[21,3],[21,5],[19,7],[17,7]]},"&":{width:26,points:[[23,12],[23,13],[22,14],[21,14],[20,13],[19,11],[17,6],[15,3],[13,1],[11,0],[7,0],[5,1],[4,2],[3,4],[3,6],[4,8],[5,9],[12,13],[13,14],[14,16],[14,18],[13,20],[11,21],[9,20],[8,18],[8,16],[9,13],[11,10],[16,3],[18,1],[20,0],[22,0],[23,1],[23,2]]},"'":{width:10,points:[[5,19],[4,20],[5,21],[6,20],[6,18],[5,16],[4,15]]},"(":{width:14,points:[[11,25],[9,23],[7,20],[5,16],[4,11],[4,7],[5,2],[7,-2],[9,-5],[11,-7]]},")":{width:14,points:[[3,25],[5,23],[7,20],[9,16],[10,11],[10,7],[9,2],[7,-2],[5,-5],[3,-7]]},"*":{width:16,points:[[8,21],[8,9],[-1,-1],[3,18],[13,12],[-1,-1],[13,18],[3,12]]},"+":{width:26,points:[[13,18],[13,0],[-1,-1],[4,9],[22,9]]},",":{width:10,points:[[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]]},"-":{width:18,points:[[6,9],[12,9]]},".":{width:10,points:[[5,2],[4,1],[5,0],[6,1],[5,2]]},"/":{width:22,points:[[20,25],[2,-7]]},"0":{width:20,points:[[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]]},"1":{width:20,points:[[6,17],[8,18],[11,21],[11,0]]},"2":{width:20,points:[[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]]},"3":{width:20,points:[[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]]},"4":{width:20,points:[[13,21],[3,7],[18,7],[-1,-1],[13,21],[13,0]]},"5":{width:20,points:[[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]]},"6":{width:20,points:[[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]]},"7":{width:20,points:[[17,21],[7,0],[-1,-1],[3,21],[17,21]]},"8":{width:20,points:[[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]]},"9":{width:20,points:[[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]]},":":{width:10,points:[[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]]},";":{width:10,points:[[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]]},"<":{width:24,points:[[20,18],[4,9],[20,0]]},"=":{width:26,points:[[4,12],[22,12],[-1,-1],[4,6],[22,6]]},">":{width:24,points:[[4,18],[20,9],[4,0]]},"?":{width:18,points:[[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],[-1,-1],[9,2],[8,1],[9,0],[10,1],[9,2]]},"@":{width:27,points:[[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],[-1,-1],[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],[-1,-1],[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],[-1,-1],[19,16],[18,8],[18,6],[19,5]]},A:{width:18,points:[[9,21],[1,0],[-1,-1],[9,21],[17,0],[-1,-1],[4,7],[14,7]]},B:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[-1,-1],[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]]},C:{width:21,points:[[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]]},D:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]]},E:{width:19,points:[[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11],[-1,-1],[4,0],[17,0]]},F:{width:18,points:[[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11]]},G:{width:21,points:[[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],[-1,-1],[13,8],[18,8]]},H:{width:22,points:[[4,21],[4,0],[-1,-1],[18,21],[18,0],[-1,-1],[4,11],[18,11]]},I:{width:8,points:[[4,21],[4,0]]},J:{width:16,points:[[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]]},K:{width:21,points:[[4,21],[4,0],[-1,-1],[18,21],[4,7],[-1,-1],[9,12],[18,0]]},L:{width:17,points:[[4,21],[4,0],[-1,-1],[4,0],[16,0]]},M:{width:24,points:[[4,21],[4,0],[-1,-1],[4,21],[12,0],[-1,-1],[20,21],[12,0],[-1,-1],[20,21],[20,0]]},N:{width:22,points:[[4,21],[4,0],[-1,-1],[4,21],[18,0],[-1,-1],[18,21],[18,0]]},O:{width:22,points:[[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]]},P:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]]},Q:{width:22,points:[[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],[-1,-1],[12,4],[18,-2]]},R:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],[-1,-1],[11,11],[18,0]]},S:{width:20,points:[[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]]},T:{width:16,points:[[8,21],[8,0],[-1,-1],[1,21],[15,21]]},U:{width:22,points:[[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]]},V:{width:18,points:[[1,21],[9,0],[-1,-1],[17,21],[9,0]]},W:{width:24,points:[[2,21],[7,0],[-1,-1],[12,21],[7,0],[-1,-1],[12,21],[17,0],[-1,-1],[22,21],[17,0]]},X:{width:20,points:[[3,21],[17,0],[-1,-1],[17,21],[3,0]]},Y:{width:18,points:[[1,21],[9,11],[9,0],[-1,-1],[17,21],[9,11]]},Z:{width:20,points:[[17,21],[3,0],[-1,-1],[3,21],[17,21],[-1,-1],[3,0],[17,0]]},"[":{width:14,points:[[4,25],[4,-7],[-1,-1],[5,25],[5,-7],[-1,-1],[4,25],[11,25],[-1,-1],[4,-7],[11,-7]]},"\\":{width:14,points:[[0,21],[14,-3]]},"]":{width:14,points:[[9,25],[9,-7],[-1,-1],[10,25],[10,-7],[-1,-1],[3,25],[10,25],[-1,-1],[3,-7],[10,-7]]},"^":{width:16,points:[[6,15],[8,18],[10,15],[-1,-1],[3,12],[8,17],[13,12],[-1,-1],[8,17],[8,0]]},_:{width:16,points:[[0,-2],[16,-2]]},"`":{width:10,points:[[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]]},a:{width:19,points:[[15,14],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},b:{width:19,points:[[4,21],[4,0],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]]},c:{width:18,points:[[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},d:{width:19,points:[[15,21],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},e:{width:18,points:[[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},f:{width:12,points:[[10,21],[8,21],[6,20],[5,17],[5,0],[-1,-1],[2,14],[9,14]]},g:{width:19,points:[[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},h:{width:19,points:[[4,21],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]]},i:{width:8,points:[[3,21],[4,20],[5,21],[4,22],[3,21],[-1,-1],[4,14],[4,0]]},j:{width:10,points:[[5,21],[6,20],[7,21],[6,22],[5,21],[-1,-1],[6,14],[6,-3],[5,-6],[3,-7],[1,-7]]},k:{width:17,points:[[4,21],[4,0],[-1,-1],[14,14],[4,4],[-1,-1],[8,8],[15,0]]},l:{width:8,points:[[4,21],[4,0]]},m:{width:30,points:[[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],[-1,-1],[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]]},n:{width:19,points:[[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]]},o:{width:19,points:[[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]]},p:{width:19,points:[[4,14],[4,-7],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]]},q:{width:19,points:[[15,14],[15,-7],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},r:{width:13,points:[[4,14],[4,0],[-1,-1],[4,8],[5,11],[7,13],[9,14],[12,14]]},s:{width:17,points:[[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]]},t:{width:12,points:[[5,21],[5,4],[6,1],[8,0],[10,0],[-1,-1],[2,14],[9,14]]},u:{width:19,points:[[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],[-1,-1],[15,14],[15,0]]},v:{width:16,points:[[2,14],[8,0],[-1,-1],[14,14],[8,0]]},w:{width:22,points:[[3,14],[7,0],[-1,-1],[11,14],[7,0],[-1,-1],[11,14],[15,0],[-1,-1],[19,14],[15,0]]},x:{width:17,points:[[3,14],[14,0],[-1,-1],[14,14],[3,0]]},y:{width:16,points:[[2,14],[8,0],[-1,-1],[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]]},z:{width:17,points:[[14,14],[3,0],[-1,-1],[3,14],[14,14],[-1,-1],[3,0],[14,0]]},"{":{width:14,points:[[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],[-1,-1],[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],[-1,-1],[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]]},"|":{width:8,points:[[4,25],[4,-7]]},"}":{width:14,points:[[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],[-1,-1],[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],[-1,-1],[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]]},"~":{width:24,points:[[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],[-1,-1],[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]]}};a.jqplot.CanvasFontRenderer=function(b){b=b||{};if(!b.pt2px){b.pt2px=1.5}a.jqplot.CanvasTextRenderer.call(this,b)};a.jqplot.CanvasFontRenderer.prototype=new a.jqplot.CanvasTextRenderer({});a.jqplot.CanvasFontRenderer.prototype.constructor=a.jqplot.CanvasFontRenderer;a.jqplot.CanvasFontRenderer.prototype.measure=function(c,e){var d=this.fontSize+" "+this.fontFamily;c.save();c.font=d;var b=c.measureText(e).width;c.restore();return b};a.jqplot.CanvasFontRenderer.prototype.draw=function(e,g){var c=0;var h=this.height*0.72;e.save();var d,b;if((-Math.PI/2<=this.angle&&this.angle<=0)||(Math.PI*3/2<=this.angle&&this.angle<=Math.PI*2)){d=0;b=-Math.sin(this.angle)*this.width}else{if((0<this.angle&&this.angle<=Math.PI/2)||(-Math.PI*2<=this.angle&&this.angle<=-Math.PI*3/2)){d=Math.sin(this.angle)*this.height;b=0}else{if((-Math.PI<this.angle&&this.angle<-Math.PI/2)||(Math.PI<=this.angle&&this.angle<=Math.PI*3/2)){d=-Math.cos(this.angle)*this.width;b=-Math.sin(this.angle)*this.width-Math.cos(this.angle)*this.height}else{if((-Math.PI*3/2<this.angle&&this.angle<Math.PI)||(Math.PI/2<this.angle&&this.angle<Math.PI)){d=Math.sin(this.angle)*this.height-Math.cos(this.angle)*this.width;b=-Math.cos(this.angle)*this.height}}}}e.strokeStyle=this.fillStyle;e.fillStyle=this.fillStyle;var f=this.fontSize+" "+this.fontFamily;e.font=f;e.translate(d,b);e.rotate(this.angle);e.fillText(g,c,h);e.restore()}})(jQuery);
js/jqplot.dateAxisRenderer.min.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com
2
+ jsDate | (c) 2010-2013 Chris Leonello
3
+ */(function(h){h.jqplot.DateAxisRenderer=function(){h.jqplot.LinearAxisRenderer.call(this);this.date=new h.jsDate()};var c=1000;var e=60*c;var f=60*e;var l=24*f;var b=7*l;var j=30.4368499*l;var k=365.242199*l;var g=[31,28,31,30,31,30,31,30,31,30,31,30];var i=["%M:%S.%#N","%M:%S.%#N","%M:%S.%#N","%M:%S","%M:%S","%M:%S","%M:%S","%H:%M:%S","%H:%M:%S","%H:%M","%H:%M","%H:%M","%H:%M","%H:%M","%H:%M","%a %H:%M","%a %H:%M","%b %e %H:%M","%b %e %H:%M","%b %e %H:%M","%b %e %H:%M","%v","%v","%v","%v","%v","%v","%v"];var m=[0.1*c,0.2*c,0.5*c,c,2*c,5*c,10*c,15*c,30*c,e,2*e,5*e,10*e,15*e,30*e,f,2*f,4*f,6*f,8*f,12*f,l,2*l,3*l,4*l,5*l,b,2*b];var d=[];function a(p,s,t){var o=Number.MAX_VALUE;var u,r,v;for(var q=0,n=m.length;q<n;q++){u=Math.abs(t-m[q]);if(u<o){o=u;r=m[q];v=i[q]}}return[r,v]}h.jqplot.DateAxisRenderer.prototype=new h.jqplot.LinearAxisRenderer();h.jqplot.DateAxisRenderer.prototype.constructor=h.jqplot.DateAxisRenderer;h.jqplot.DateTickFormatter=function(n,o){if(!n){n="%Y/%m/%d"}return h.jsDate.strftime(o,n)};h.jqplot.DateAxisRenderer.prototype.init=function(E){this.tickOptions.formatter=h.jqplot.DateTickFormatter;this.tickInset=0;this.drawBaseline=true;this.baselineWidth=null;this.baselineColor=null;this.daTickInterval=null;this._daTickInterval=null;h.extend(true,this,E);var C=this._dataBounds,u,x,D,y,A,z,o;for(var t=0;t<this._series.length;t++){u={intervals:[],frequencies:{},sortedIntervals:[],min:null,max:null,mean:null};x=0;D=this._series[t];y=D.data;A=D._plotData;z=D._stackData;o=0;for(var r=0;r<y.length;r++){if(this.name=="xaxis"||this.name=="x2axis"){y[r][0]=new h.jsDate(y[r][0]).getTime();A[r][0]=new h.jsDate(y[r][0]).getTime();z[r][0]=new h.jsDate(y[r][0]).getTime();if((y[r][0]!=null&&y[r][0]<C.min)||C.min==null){C.min=y[r][0]}if((y[r][0]!=null&&y[r][0]>C.max)||C.max==null){C.max=y[r][0]}if(r>0){o=Math.abs(y[r][0]-y[r-1][0]);u.intervals.push(o);if(u.frequencies.hasOwnProperty(o)){u.frequencies[o]+=1}else{u.frequencies[o]=1}}x+=o}else{y[r][1]=new h.jsDate(y[r][1]).getTime();A[r][1]=new h.jsDate(y[r][1]).getTime();z[r][1]=new h.jsDate(y[r][1]).getTime();if((y[r][1]!=null&&y[r][1]<C.min)||C.min==null){C.min=y[r][1]}if((y[r][1]!=null&&y[r][1]>C.max)||C.max==null){C.max=y[r][1]}if(r>0){o=Math.abs(y[r][1]-y[r-1][1]);u.intervals.push(o);if(u.frequencies.hasOwnProperty(o)){u.frequencies[o]+=1}else{u.frequencies[o]=1}}}x+=o}if(D.renderer.bands){if(D.renderer.bands.hiData.length){var w=D.renderer.bands.hiData;for(var r=0,q=w.length;r<q;r++){if(this.name==="xaxis"||this.name==="x2axis"){w[r][0]=new h.jsDate(w[r][0]).getTime();if((w[r][0]!=null&&w[r][0]>C.max)||C.max==null){C.max=w[r][0]}}else{w[r][1]=new h.jsDate(w[r][1]).getTime();if((w[r][1]!=null&&w[r][1]>C.max)||C.max==null){C.max=w[r][1]}}}}if(D.renderer.bands.lowData.length){var w=D.renderer.bands.lowData;for(var r=0,q=w.length;r<q;r++){if(this.name==="xaxis"||this.name==="x2axis"){w[r][0]=new h.jsDate(w[r][0]).getTime();if((w[r][0]!=null&&w[r][0]<C.min)||C.min==null){C.min=w[r][0]}}else{w[r][1]=new h.jsDate(w[r][1]).getTime();if((w[r][1]!=null&&w[r][1]<C.min)||C.min==null){C.min=w[r][1]}}}}}var B=0,v=0;for(var p in u.frequencies){u.sortedIntervals.push({interval:p,frequency:u.frequencies[p]})}u.sortedIntervals.sort(function(s,n){return n.frequency-s.frequency});u.min=h.jqplot.arrayMin(u.intervals);u.max=h.jqplot.arrayMax(u.intervals);u.mean=x/y.length;this._intervalStats.push(u);u=x=D=y=A=z=null}C=null};h.jqplot.DateAxisRenderer.prototype.reset=function(){this.min=this._options.min;this.max=this._options.max;this.tickInterval=this._options.tickInterval;this.numberTicks=this._options.numberTicks;this._autoFormatString="";if(this._overrideFormatString&&this.tickOptions&&this.tickOptions.formatString){this.tickOptions.formatString=""}this.daTickInterval=this._daTickInterval};h.jqplot.DateAxisRenderer.prototype.createTicks=function(p){var X=this._ticks;var L=this.ticks;var F=this.name;var H=this._dataBounds;var M=this._intervalStats;var n=(this.name.charAt(0)==="x")?this._plotDimensions.width:this._plotDimensions.height;var w;var ae,J;var y,x;var ad,aa;var s=30;var O=1;var U=null;if(this.tickInterval!=null){if(Number(this.tickInterval)){U=[Number(this.tickInterval),"seconds"]}else{if(typeof this.tickInterval=="string"){var ac=this.tickInterval.split(" ");if(ac.length==1){U=[1,ac[0]]}else{if(ac.length==2){U=[ac[0],ac[1]]}}}}}var v=this.tickInterval;ae=new h.jsDate((this.min!=null)?this.min:H.min).getTime();J=new h.jsDate((this.max!=null)?this.max:H.max).getTime();var A=p.plugins.cursor;if(A&&A._zoom&&A._zoom.zooming){this.min=null;this.max=null}var B=J-ae;if(this.tickOptions==null||!this.tickOptions.formatString){this._overrideFormatString=true}if(L.length){for(aa=0;aa<L.length;aa++){var P=L[aa];var Y=new this.tickRenderer(this.tickOptions);if(P.constructor==Array){Y.value=new h.jsDate(P[0]).getTime();Y.label=P[1];if(!this.showTicks){Y.showLabel=false;Y.showMark=false}else{if(!this.showTickMarks){Y.showMark=false}}Y.setTick(Y.value,this.name);this._ticks.push(Y)}else{Y.value=new h.jsDate(P).getTime();if(!this.showTicks){Y.showLabel=false;Y.showMark=false}else{if(!this.showTickMarks){Y.showMark=false}}Y.setTick(Y.value,this.name);this._ticks.push(Y)}}this.numberTicks=L.length;this.min=this._ticks[0].value;this.max=this._ticks[this.numberTicks-1].value;this.daTickInterval=[(this.max-this.min)/(this.numberTicks-1)/1000,"seconds"]}else{if(this.min==null&&this.max==null&&H.min==H.max){var E=h.extend(true,{},this.tickOptions,{name:this.name,value:null});var T=300000;this.min=H.min-T;this.max=H.max+T;this.numberTicks=3;for(var aa=this.min;aa<=this.max;aa+=T){E.value=aa;var Y=new this.tickRenderer(E);if(this._overrideFormatString&&this._autoFormatString!=""){Y.formatString=this._autoFormatString}Y.showLabel=false;Y.showMark=false;this._ticks.push(Y)}if(this.showTicks){this._ticks[1].showLabel=true}if(this.showTickMarks){this._ticks[1].showTickMarks=true}}else{if(this.min==null&&this.max==null){var N=h.extend(true,{},this.tickOptions,{name:this.name,value:null});var ab,I;if(!this.tickInterval&&!this.numberTicks){var R=Math.max(n,s+1);var Z=115;if(this.tickRenderer===h.jqplot.CanvasAxisTickRenderer&&this.tickOptions.angle){Z=115-40*Math.abs(Math.sin(this.tickOptions.angle/180*Math.PI))}ab=Math.ceil((R-s)/Z+1);I=(J-ae)/(ab-1)}else{if(this.tickInterval){I=new h.jsDate(0).add(U[0],U[1]).getTime()}else{if(this.numberTicks){ab=this.numberTicks;I=(J-ae)/(ab-1)}}}if(I<=19*l){var Q=a(ae,J,I);var r=Q[0];this._autoFormatString=Q[1];ae=new h.jsDate(ae);ae=Math.floor((ae.getTime()-ae.getUtcOffset())/r)*r+ae.getUtcOffset();ab=Math.ceil((J-ae)/r)+1;this.min=ae;this.max=ae+(ab-1)*r;if(this.max<J){this.max+=r;ab+=1}this.tickInterval=r;this.numberTicks=ab;for(var aa=0;aa<ab;aa++){N.value=this.min+aa*r;Y=new this.tickRenderer(N);if(this._overrideFormatString&&this._autoFormatString!=""){Y.formatString=this._autoFormatString}if(!this.showTicks){Y.showLabel=false;Y.showMark=false}else{if(!this.showTickMarks){Y.showMark=false}}this._ticks.push(Y)}O=this.tickInterval}else{if(I<=9*j){this._autoFormatString="%v";var D=Math.round(I/j);if(D<1){D=1}else{if(D>6){D=6}}var V=new h.jsDate(ae).setDate(1).setHours(0,0,0,0);var q=new h.jsDate(J);var z=new h.jsDate(J).setDate(1).setHours(0,0,0,0);if(q.getTime()!==z.getTime()){z=z.add(1,"month")}var S=z.diff(V,"month");ab=Math.ceil(S/D)+1;this.min=V.getTime();this.max=V.clone().add((ab-1)*D,"month").getTime();this.numberTicks=ab;for(var aa=0;aa<ab;aa++){if(aa===0){N.value=V.getTime()}else{N.value=V.add(D,"month").getTime()}Y=new this.tickRenderer(N);if(this._overrideFormatString&&this._autoFormatString!=""){Y.formatString=this._autoFormatString}if(!this.showTicks){Y.showLabel=false;Y.showMark=false}else{if(!this.showTickMarks){Y.showMark=false}}this._ticks.push(Y)}O=D*j}else{this._autoFormatString="%v";var D=Math.round(I/k);if(D<1){D=1}var V=new h.jsDate(ae).setMonth(0,1).setHours(0,0,0,0);var z=new h.jsDate(J).add(1,"year").setMonth(0,1).setHours(0,0,0,0);var K=z.diff(V,"year");ab=Math.ceil(K/D)+1;this.min=V.getTime();this.max=V.clone().add((ab-1)*D,"year").getTime();this.numberTicks=ab;for(var aa=0;aa<ab;aa++){if(aa===0){N.value=V.getTime()}else{N.value=V.add(D,"year").getTime()}Y=new this.tickRenderer(N);if(this._overrideFormatString&&this._autoFormatString!=""){Y.formatString=this._autoFormatString}if(!this.showTicks){Y.showLabel=false;Y.showMark=false}else{if(!this.showTickMarks){Y.showMark=false}}this._ticks.push(Y)}O=D*k}}}else{if(F=="xaxis"||F=="x2axis"){n=this._plotDimensions.width}else{n=this._plotDimensions.height}if(this.min!=null&&this.max!=null&&this.numberTicks!=null){this.tickInterval=null}if(this.tickInterval!=null&&U!=null){this.daTickInterval=U}if(ae==J){var o=24*60*60*500;ae-=o;J+=o}B=J-ae;var G=2+parseInt(Math.max(0,n-100)/100,10);var W,C;W=(this.min!=null)?new h.jsDate(this.min).getTime():ae-B/2*(this.padMin-1);C=(this.max!=null)?new h.jsDate(this.max).getTime():J+B/2*(this.padMax-1);this.min=W;this.max=C;B=this.max-this.min;if(this.numberTicks==null){if(this.daTickInterval!=null){var u=new h.jsDate(this.max).diff(this.min,this.daTickInterval[1],true);this.numberTicks=Math.ceil(u/this.daTickInterval[0])+1;this.max=new h.jsDate(this.min).add((this.numberTicks-1)*this.daTickInterval[0],this.daTickInterval[1]).getTime()}else{if(n>200){this.numberTicks=parseInt(3+(n-200)/100,10)}else{this.numberTicks=2}}}O=B/(this.numberTicks-1)/1000;if(this.daTickInterval==null){this.daTickInterval=[O,"seconds"]}for(var aa=0;aa<this.numberTicks;aa++){var ae=new h.jsDate(this.min);ad=ae.add(aa*this.daTickInterval[0],this.daTickInterval[1]).getTime();var Y=new this.tickRenderer(this.tickOptions);if(!this.showTicks){Y.showLabel=false;Y.showMark=false}else{if(!this.showTickMarks){Y.showMark=false}}Y.setTick(ad,this.name);this._ticks.push(Y)}}}}if(this.tickInset){this.min=this.min-this.tickInset*O;this.max=this.max+this.tickInset*O}if(this._daTickInterval==null){this._daTickInterval=this.daTickInterval}X=null}})(jQuery);
js/jqplot.enhancedLegendRenderer.min.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com
2
+ jsDate | (c) 2010-2013 Chris Leonello
3
+ */(function(c){c.jqplot.EnhancedLegendRenderer=function(){c.jqplot.TableLegendRenderer.call(this)};c.jqplot.EnhancedLegendRenderer.prototype=new c.jqplot.TableLegendRenderer();c.jqplot.EnhancedLegendRenderer.prototype.constructor=c.jqplot.EnhancedLegendRenderer;c.jqplot.EnhancedLegendRenderer.prototype.init=function(d){this.numberRows=null;this.numberColumns=null;this.seriesToggle="normal";this.seriesToggleReplot=false;this.disableIEFading=true;c.extend(true,this,d);if(this.seriesToggle){c.jqplot.postDrawHooks.push(b)}};c.jqplot.EnhancedLegendRenderer.prototype.draw=function(m,y){var f=this;if(this.show){var r=this._series;var u;var w="position:absolute;";w+=(this.background)?"background:"+this.background+";":"";w+=(this.border)?"border:"+this.border+";":"";w+=(this.fontSize)?"font-size:"+this.fontSize+";":"";w+=(this.fontFamily)?"font-family:"+this.fontFamily+";":"";w+=(this.textColor)?"color:"+this.textColor+";":"";w+=(this.marginTop!=null)?"margin-top:"+this.marginTop+";":"";w+=(this.marginBottom!=null)?"margin-bottom:"+this.marginBottom+";":"";w+=(this.marginLeft!=null)?"margin-left:"+this.marginLeft+";":"";w+=(this.marginRight!=null)?"margin-right:"+this.marginRight+";":"";this._elem=c('<table class="jqplot-table-legend" style="'+w+'"></table>');if(this.seriesToggle){this._elem.css("z-index","3")}var C=false,q=false,d,o;if(this.numberRows){d=this.numberRows;if(!this.numberColumns){o=Math.ceil(r.length/d)}else{o=this.numberColumns}}else{if(this.numberColumns){o=this.numberColumns;d=Math.ceil(r.length/this.numberColumns)}else{d=r.length;o=1}}var B,z,e,l,k,n,p,t,h,g;var v=0;for(B=r.length-1;B>=0;B--){if(o==1&&r[B]._stack||r[B].renderer.constructor==c.jqplot.BezierCurveRenderer){q=true}}for(B=0;B<d;B++){e=c(document.createElement("tr"));e.addClass("jqplot-table-legend");if(q){e.prependTo(this._elem)}else{e.appendTo(this._elem)}for(z=0;z<o;z++){if(v<r.length&&(r[v].show||r[v].showLabel)){u=r[v];n=this.labels[v]||u.label.toString();if(n){var x=u.color;if(!q){if(B>0){C=true}else{C=false}}else{if(B==d-1){C=false}else{C=true}}p=(C)?this.rowSpacing:"0";l=c(document.createElement("td"));l.addClass("jqplot-table-legend jqplot-table-legend-swatch");l.css({textAlign:"center",paddingTop:p});h=c(document.createElement("div"));h.addClass("jqplot-table-legend-swatch-outline");g=c(document.createElement("div"));g.addClass("jqplot-table-legend-swatch");g.css({backgroundColor:x,borderColor:x});l.append(h.append(g));k=c(document.createElement("td"));k.addClass("jqplot-table-legend jqplot-table-legend-label");k.css("paddingTop",p);if(this.escapeHtml){k.text(n)}else{k.html(n)}if(q){if(this.showLabels){k.prependTo(e)}if(this.showSwatches){l.prependTo(e)}}else{if(this.showSwatches){l.appendTo(e)}if(this.showLabels){k.appendTo(e)}}if(this.seriesToggle){var A;if(typeof(this.seriesToggle)==="string"||typeof(this.seriesToggle)==="number"){if(!c.jqplot.use_excanvas||!this.disableIEFading){A=this.seriesToggle}}if(this.showSwatches){l.bind("click",{series:u,speed:A,plot:y,replot:this.seriesToggleReplot},a);l.addClass("jqplot-seriesToggle")}if(this.showLabels){k.bind("click",{series:u,speed:A,plot:y,replot:this.seriesToggleReplot},a);k.addClass("jqplot-seriesToggle")}if(!u.show&&u.showLabel){l.addClass("jqplot-series-hidden");k.addClass("jqplot-series-hidden")}}C=true}}v++}l=k=h=g=null}}return this._elem};var a=function(j){var i=j.data,m=i.series,k=i.replot,h=i.plot,f=i.speed,l=m.index,g=false;if(m.canvas._elem.is(":hidden")||!m.show){g=true}var e=function(){if(k){var n={};if(c.isPlainObject(k)){c.extend(true,n,k)}h.replot(n);if(g&&f){var d=h.series[l];if(d.shadowCanvas._elem){d.shadowCanvas._elem.hide().fadeIn(f)}d.canvas._elem.hide().fadeIn(f);d.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+d.index).hide().fadeIn(f)}}else{var d=h.series[l];if(d.canvas._elem.is(":hidden")||!d.show){if(typeof h.options.legend.showSwatches==="undefined"||h.options.legend.showSwatches===true){h.legend._elem.find("td").eq(l*2).addClass("jqplot-series-hidden")}if(typeof h.options.legend.showLabels==="undefined"||h.options.legend.showLabels===true){h.legend._elem.find("td").eq((l*2)+1).addClass("jqplot-series-hidden")}}else{if(typeof h.options.legend.showSwatches==="undefined"||h.options.legend.showSwatches===true){h.legend._elem.find("td").eq(l*2).removeClass("jqplot-series-hidden")}if(typeof h.options.legend.showLabels==="undefined"||h.options.legend.showLabels===true){h.legend._elem.find("td").eq((l*2)+1).removeClass("jqplot-series-hidden")}}}};m.toggleDisplay(j,e)};var b=function(){if(this.legend.renderer.constructor==c.jqplot.EnhancedLegendRenderer&&this.legend.seriesToggle){var d=this.legend._elem.detach();this.eventCanvas._elem.after(d)}}})(jQuery);
js/jqplot.highlighter.min.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com
2
+ jsDate | (c) 2010-2013 Chris Leonello
3
+ */(function(d){d.jqplot.eventListenerHooks.push(["jqplotMouseMove",f]);d.jqplot.Highlighter=function(h){this.show=d.jqplot.config.enablePlugins;this.markerRenderer=new d.jqplot.MarkerRenderer({shadow:false});this.showMarker=true;this.lineWidthAdjust=2.5;this.sizeAdjust=5;this.showTooltip=true;this.tooltipLocation="nw";this.fadeTooltip=true;this.tooltipFadeSpeed="fast";this.tooltipOffset=2;this.tooltipAxes="both";this.tooltipSeparator=", ";this.tooltipContentEditor=null;this.useAxesFormatters=true;this.tooltipFormatString="%.5P";this.formatString=null;this.yvalues=1;this.bringSeriesToFront=false;this._tooltipElem;this.isHighlighting=false;this.currentNeighbor=null;d.extend(true,this,h)};var b=["nw","n","ne","e","se","s","sw","w"];var e={nw:0,n:1,ne:2,e:3,se:4,s:5,sw:6,w:7};var c=["se","s","sw","w","nw","n","ne","e"];d.jqplot.Highlighter.init=function(k,j,i){var h=i||{};this.plugins.highlighter=new d.jqplot.Highlighter(h.highlighter)};d.jqplot.Highlighter.parseOptions=function(i,h){this.showHighlight=true};d.jqplot.Highlighter.postPlotDraw=function(){if(this.plugins.highlighter&&this.plugins.highlighter.highlightCanvas){this.plugins.highlighter.highlightCanvas.resetCanvas();this.plugins.highlighter.highlightCanvas=null}if(this.plugins.highlighter&&this.plugins.highlighter._tooltipElem){this.plugins.highlighter._tooltipElem.emptyForce();this.plugins.highlighter._tooltipElem=null}this.plugins.highlighter.highlightCanvas=new d.jqplot.GenericCanvas();this.eventCanvas._elem.before(this.plugins.highlighter.highlightCanvas.createElement(this._gridPadding,"jqplot-highlight-canvas",this._plotDimensions,this));this.plugins.highlighter.highlightCanvas.setContext();var h=document.createElement("div");this.plugins.highlighter._tooltipElem=d(h);h=null;this.plugins.highlighter._tooltipElem.addClass("jqplot-highlighter-tooltip");this.plugins.highlighter._tooltipElem.css({position:"absolute",display:"none"});this.eventCanvas._elem.before(this.plugins.highlighter._tooltipElem)};d.jqplot.preInitHooks.push(d.jqplot.Highlighter.init);d.jqplot.preParseSeriesOptionsHooks.push(d.jqplot.Highlighter.parseOptions);d.jqplot.postDrawHooks.push(d.jqplot.Highlighter.postPlotDraw);function a(m,o){var j=m.plugins.highlighter;var p=m.series[o.seriesIndex];var h=p.markerRenderer;var i=j.markerRenderer;i.style=h.style;i.lineWidth=h.lineWidth+j.lineWidthAdjust;i.size=h.size+j.sizeAdjust;var l=d.jqplot.getColorComponents(h.color);var n=[l[0],l[1],l[2]];var k=(l[3]>=0.6)?l[3]*0.6:l[3]*(2-l[3]);i.color="rgba("+n[0]+","+n[1]+","+n[2]+","+k+")";i.init();i.draw(p.gridData[o.pointIndex][0],p.gridData[o.pointIndex][1],j.highlightCanvas._ctx)}function g(A,q,m){var k=A.plugins.highlighter;var D=k._tooltipElem;var r=q.highlighter||{};var t=d.extend(true,{},k,r);if(t.useAxesFormatters){var w=q._xaxis._ticks[0].formatter;var h=q._yaxis._ticks[0].formatter;var E=q._xaxis._ticks[0].formatString;var s=q._yaxis._ticks[0].formatString;var z;var u=w(E,m.data[0]);var l=[];for(var B=1;B<t.yvalues+1;B++){l.push(h(s,m.data[B]))}if(typeof t.formatString==="string"){switch(t.tooltipAxes){case"both":case"xy":l.unshift(u);l.unshift(t.formatString);z=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break;case"yx":l.push(u);l.unshift(t.formatString);z=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break;case"x":z=d.jqplot.sprintf.apply(d.jqplot.sprintf,[t.formatString,u]);break;case"y":l.unshift(t.formatString);z=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break;default:l.unshift(u);l.unshift(t.formatString);z=d.jqplot.sprintf.apply(d.jqplot.sprintf,l);break}}else{switch(t.tooltipAxes){case"both":case"xy":z=u;for(var B=0;B<l.length;B++){z+=t.tooltipSeparator+l[B]}break;case"yx":z="";for(var B=0;B<l.length;B++){z+=l[B]+t.tooltipSeparator}z+=u;break;case"x":z=u;break;case"y":z=l.join(t.tooltipSeparator);break;default:z=u;for(var B=0;B<l.length;B++){z+=t.tooltipSeparator+l[B]}break}}}else{var z;if(typeof t.formatString==="string"){z=d.jqplot.sprintf.apply(d.jqplot.sprintf,[t.formatString].concat(m.data))}else{if(t.tooltipAxes=="both"||t.tooltipAxes=="xy"){z=d.jqplot.sprintf(t.tooltipFormatString,m.data[0])+t.tooltipSeparator+d.jqplot.sprintf(t.tooltipFormatString,m.data[1])}else{if(t.tooltipAxes=="yx"){z=d.jqplot.sprintf(t.tooltipFormatString,m.data[1])+t.tooltipSeparator+d.jqplot.sprintf(t.tooltipFormatString,m.data[0])}else{if(t.tooltipAxes=="x"){z=d.jqplot.sprintf(t.tooltipFormatString,m.data[0])}else{if(t.tooltipAxes=="y"){z=d.jqplot.sprintf(t.tooltipFormatString,m.data[1])}}}}}}if(d.isFunction(t.tooltipContentEditor)){z=t.tooltipContentEditor(z,m.seriesIndex,m.pointIndex,A)}D.html(z);var C={x:m.gridData[0],y:m.gridData[1]};var v=0;var j=0.707;if(q.markerRenderer.show==true){v=(q.markerRenderer.size+t.sizeAdjust)/2}var o=b;if(q.fillToZero&&q.fill&&m.data[1]<0){o=c}switch(o[e[t.tooltipLocation]]){case"nw":var p=C.x+A._gridPadding.left-D.outerWidth(true)-t.tooltipOffset-j*v;var n=C.y+A._gridPadding.top-t.tooltipOffset-D.outerHeight(true)-j*v;break;case"n":var p=C.x+A._gridPadding.left-D.outerWidth(true)/2;var n=C.y+A._gridPadding.top-t.tooltipOffset-D.outerHeight(true)-v;break;case"ne":var p=C.x+A._gridPadding.left+t.tooltipOffset+j*v;var n=C.y+A._gridPadding.top-t.tooltipOffset-D.outerHeight(true)-j*v;break;case"e":var p=C.x+A._gridPadding.left+t.tooltipOffset+v;var n=C.y+A._gridPadding.top-D.outerHeight(true)/2;break;case"se":var p=C.x+A._gridPadding.left+t.tooltipOffset+j*v;var n=C.y+A._gridPadding.top+t.tooltipOffset+j*v;break;case"s":var p=C.x+A._gridPadding.left-D.outerWidth(true)/2;var n=C.y+A._gridPadding.top+t.tooltipOffset+v;break;case"sw":var p=C.x+A._gridPadding.left-D.outerWidth(true)-t.tooltipOffset-j*v;var n=C.y+A._gridPadding.top+t.tooltipOffset+j*v;break;case"w":var p=C.x+A._gridPadding.left-D.outerWidth(true)-t.tooltipOffset-v;var n=C.y+A._gridPadding.top-D.outerHeight(true)/2;break;default:var p=C.x+A._gridPadding.left-D.outerWidth(true)-t.tooltipOffset-j*v;var n=C.y+A._gridPadding.top-t.tooltipOffset-D.outerHeight(true)-j*v;break}D.css("left",p);D.css("top",n);if(t.fadeTooltip){D.stop(true,true).fadeIn(t.tooltipFadeSpeed)}else{D.show()}D=null}function f(n,j,i,p,l){var h=l.plugins.highlighter;var m=l.plugins.cursor;if(h.show){if(p==null&&h.isHighlighting){var o=jQuery.Event("jqplotHighlighterUnhighlight");l.target.trigger(o);var q=h.highlightCanvas._ctx;q.clearRect(0,0,q.canvas.width,q.canvas.height);if(h.fadeTooltip){h._tooltipElem.fadeOut(h.tooltipFadeSpeed)}else{h._tooltipElem.hide()}if(h.bringSeriesToFront){l.restorePreviousSeriesOrder()}h.isHighlighting=false;h.currentNeighbor=null;q=null}else{if(p!=null&&l.series[p.seriesIndex].showHighlight&&!h.isHighlighting){var o=jQuery.Event("jqplotHighlighterHighlight");o.which=n.which;o.pageX=n.pageX;o.pageY=n.pageY;var k=[p.seriesIndex,p.pointIndex,p.data,l];l.target.trigger(o,k);h.isHighlighting=true;h.currentNeighbor=p;if(h.showMarker){a(l,p)}if(l.series[p.seriesIndex].show&&h.showTooltip&&(!m||!m._zoom.started)){g(l,l.series[p.seriesIndex],p)}if(h.bringSeriesToFront){l.moveSeriesToFront(p.seriesIndex)}}else{if(p!=null&&h.isHighlighting&&h.currentNeighbor!=p){if(l.series[p.seriesIndex].showHighlight){var q=h.highlightCanvas._ctx;q.clearRect(0,0,q.canvas.width,q.canvas.height);h.isHighlighting=true;h.currentNeighbor=p;if(h.showMarker){a(l,p)}if(l.series[p.seriesIndex].show&&h.showTooltip&&(!m||!m._zoom.started)){g(l,l.series[p.seriesIndex],p)}if(h.bringSeriesToFront){l.moveSeriesToFront(p.seriesIndex)}}}}}}}})(jQuery);
js/jqplot.pieRenderer.min.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com
2
+ jsDate | (c) 2010-2013 Chris Leonello
3
+ */(function(e){e.jqplot.PieRenderer=function(){e.jqplot.LineRenderer.call(this)};e.jqplot.PieRenderer.prototype=new e.jqplot.LineRenderer();e.jqplot.PieRenderer.prototype.constructor=e.jqplot.PieRenderer;e.jqplot.PieRenderer.prototype.init=function(q,u){this.diameter=null;this.padding=20;this.sliceMargin=0;this.fill=true;this.shadowOffset=2;this.shadowAlpha=0.07;this.shadowDepth=5;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];this.dataLabels="percent";this.showDataLabels=false;this.dataLabelFormatString=null;this.dataLabelThreshold=3;this.dataLabelPositionFactor=0.52;this.dataLabelNudge=2;this.dataLabelCenterOn=true;this.startAngle=0;this.tickRenderer=e.jqplot.PieTickRenderer;this._drawData=true;this._type="pie";if(q.highlightMouseDown&&q.highlightMouseOver==null){q.highlightMouseOver=false}e.extend(true,this,q);if(this.sliceMargin<0){this.sliceMargin=0}this._diameter=null;this._radius=null;this._sliceAngles=[];this._highlightedPoint=null;if(this.highlightColors.length==0){for(var s=0;s<this.seriesColors.length;s++){var r=e.jqplot.getColorComponents(this.seriesColors[s]);var o=[r[0],r[1],r[2]];var t=o[0]+o[1]+o[2];for(var p=0;p<3;p++){o[p]=(t>570)?o[p]*0.8:o[p]+0.3*(255-o[p]);o[p]=parseInt(o[p],10)}this.highlightColors.push("rgb("+o[0]+","+o[1]+","+o[2]+")")}}this.highlightColorGenerator=new e.jqplot.ColorGenerator(this.highlightColors);u.postParseOptionsHooks.addOnce(m);u.postInitHooks.addOnce(g);u.eventListenerHooks.addOnce("jqplotMouseMove",b);u.eventListenerHooks.addOnce("jqplotMouseDown",a);u.eventListenerHooks.addOnce("jqplotMouseUp",l);u.eventListenerHooks.addOnce("jqplotClick",f);u.eventListenerHooks.addOnce("jqplotRightClick",n);u.postDrawHooks.addOnce(i)};e.jqplot.PieRenderer.prototype.setGridData=function(t){var p=[];var u=[];var o=this.startAngle/180*Math.PI;var s=0;this._drawData=false;for(var r=0;r<this.data.length;r++){if(this.data[r][1]!=0){this._drawData=true}p.push(this.data[r][1]);u.push([this.data[r][0]]);if(r>0){p[r]+=p[r-1]}s+=this.data[r][1]}var q=Math.PI*2/p[p.length-1];for(var r=0;r<p.length;r++){u[r][1]=p[r]*q;u[r][2]=this.data[r][1]/s}this.gridData=u};e.jqplot.PieRenderer.prototype.makeGridData=function(t,u){var p=[];var v=[];var s=0;var o=this.startAngle/180*Math.PI;this._drawData=false;for(var r=0;r<t.length;r++){if(this.data[r][1]!=0){this._drawData=true}p.push(t[r][1]);v.push([t[r][0]]);if(r>0){p[r]+=p[r-1]}s+=t[r][1]}var q=Math.PI*2/p[p.length-1];for(var r=0;r<p.length;r++){v[r][1]=p[r]*q;v[r][2]=t[r][1]/s}return v};function h(o){return Math.sin((o-(o-Math.PI)/8/Math.PI)/2)}function j(u,t,o,v,r){var w=0;var q=t-u;var s=Math.abs(q);var p=o;if(v==false){p+=r}if(p>0&&s>0.01&&s<6.282){w=parseFloat(p)/2/h(q)}return w}e.jqplot.PieRenderer.prototype.drawSlice=function(B,z,y,u,w){if(this._drawData){var p=this._radius;var A=this.fill;var x=this.lineWidth;var s=this.sliceMargin;if(this.fill==false){s+=this.lineWidth}B.save();B.translate(this._center[0],this._center[1]);var D=j(z,y,this.sliceMargin,this.fill,this.lineWidth);var o=D*Math.cos((z+y)/2);var C=D*Math.sin((z+y)/2);if((y-z)<=Math.PI){p-=D}else{p+=D}B.translate(o,C);if(w){for(var v=0,t=this.shadowDepth;v<t;v++){B.save();B.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI),this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));q(p)}for(var v=0,t=this.shadowDepth;v<t;v++){B.restore()}}else{q(p)}B.restore()}function q(r){if(y>6.282+this.startAngle){y=6.282+this.startAngle;if(z>y){z=6.281+this.startAngle}}if(z>=y){return}B.beginPath();B.fillStyle=u;B.strokeStyle=u;B.lineWidth=x;B.arc(0,0,r,z,y,false);B.lineTo(0,0);B.closePath();if(A){B.fill()}else{B.stroke()}}};e.jqplot.PieRenderer.prototype.draw=function(B,z,E,o){var W;var H=(E!=undefined)?E:{};var t=0;var s=0;var N=1;var L=new e.jqplot.ColorGenerator(this.seriesColors);if(E.legendInfo&&E.legendInfo.placement=="insideGrid"){var J=E.legendInfo;switch(J.location){case"nw":t=J.width+J.xoffset;break;case"w":t=J.width+J.xoffset;break;case"sw":t=J.width+J.xoffset;break;case"ne":t=J.width+J.xoffset;N=-1;break;case"e":t=J.width+J.xoffset;N=-1;break;case"se":t=J.width+J.xoffset;N=-1;break;case"n":s=J.height+J.yoffset;break;case"s":s=J.height+J.yoffset;N=-1;break;default:break}}var K=(H.shadow!=undefined)?H.shadow:this.shadow;var A=(H.fill!=undefined)?H.fill:this.fill;var C=B.canvas.width;var I=B.canvas.height;var Q=C-t-2*this.padding;var X=I-s-2*this.padding;var M=Math.min(Q,X);var Y=M;this._sliceAngles=[];var v=this.sliceMargin;if(this.fill==false){v+=this.lineWidth}var q;var G=0;var R,aa,Z,ab;var D=this.startAngle/180*Math.PI;for(var W=0,V=z.length;W<V;W++){aa=(W==0)?D:z[W-1][1]+D;Z=z[W][1]+D;this._sliceAngles.push([aa,Z]);q=j(aa,Z,this.sliceMargin,this.fill,this.lineWidth);if(Math.abs(Z-aa)>Math.PI){G=Math.max(q,G)}}if(this.diameter!=null&&this.diameter>0){this._diameter=this.diameter-2*G}else{this._diameter=Y-2*G}if(this._diameter<6){e.jqplot.log("Diameter of pie too small, not rendering.");return}var S=this._radius=this._diameter/2;this._center=[(C-N*t)/2+N*t+G*Math.cos(D),(I-N*s)/2+N*s+G*Math.sin(D)];if(this.shadow){for(var W=0,V=z.length;W<V;W++){ab="rgba(0,0,0,"+this.shadowAlpha+")";this.renderer.drawSlice.call(this,B,this._sliceAngles[W][0],this._sliceAngles[W][1],ab,true)}}for(var W=0;W<z.length;W++){this.renderer.drawSlice.call(this,B,this._sliceAngles[W][0],this._sliceAngles[W][1],L.next(),false);if(this.showDataLabels&&z[W][2]*100>=this.dataLabelThreshold){var F,U=(this._sliceAngles[W][0]+this._sliceAngles[W][1])/2,T;if(this.dataLabels=="label"){F=this.dataLabelFormatString||"%s";T=e.jqplot.sprintf(F,z[W][0])}else{if(this.dataLabels=="value"){F=this.dataLabelFormatString||"%d";T=e.jqplot.sprintf(F,this.data[W][1])}else{if(this.dataLabels=="percent"){F=this.dataLabelFormatString||"%d%%";T=e.jqplot.sprintf(F,z[W][2]*100)}else{if(this.dataLabels.constructor==Array){F=this.dataLabelFormatString||"%s";T=e.jqplot.sprintf(F,this.dataLabels[W])}}}}var p=(this._radius)*this.dataLabelPositionFactor+this.sliceMargin+this.dataLabelNudge;var P=this._center[0]+Math.cos(U)*p+this.canvas._offsets.left;var O=this._center[1]+Math.sin(U)*p+this.canvas._offsets.top;var u=e('<div class="jqplot-pie-series jqplot-data-label" style="position:absolute;">'+T+"</div>").insertBefore(o.eventCanvas._elem);if(this.dataLabelCenterOn){P-=u.width()/2;O-=u.height()/2}else{P-=u.width()*Math.sin(U/2);O-=u.height()/2}P=Math.round(P);O=Math.round(O);u.css({left:P,top:O})}}};e.jqplot.PieAxisRenderer=function(){e.jqplot.LinearAxisRenderer.call(this)};e.jqplot.PieAxisRenderer.prototype=new e.jqplot.LinearAxisRenderer();e.jqplot.PieAxisRenderer.prototype.constructor=e.jqplot.PieAxisRenderer;e.jqplot.PieAxisRenderer.prototype.init=function(o){this.tickRenderer=e.jqplot.PieTickRenderer;e.extend(true,this,o);this._dataBounds={min:0,max:100};this.min=0;this.max=100;this.showTicks=false;this.ticks=[];this.showMark=false;this.show=false};e.jqplot.PieLegendRenderer=function(){e.jqplot.TableLegendRenderer.call(this)};e.jqplot.PieLegendRenderer.prototype=new e.jqplot.TableLegendRenderer();e.jqplot.PieLegendRenderer.prototype.constructor=e.jqplot.PieLegendRenderer;e.jqplot.PieLegendRenderer.prototype.init=function(o){this.numberRows=null;this.numberColumns=null;e.extend(true,this,o)};e.jqplot.PieLegendRenderer.prototype.draw=function(){var r=this;if(this.show){var B=this._series;this._elem=e(document.createElement("table"));this._elem.addClass("jqplot-table-legend");var E={position:"absolute"};if(this.background){E.background=this.background}if(this.border){E.border=this.border}if(this.fontSize){E.fontSize=this.fontSize}if(this.fontFamily){E.fontFamily=this.fontFamily}if(this.textColor){E.textColor=this.textColor}if(this.marginTop!=null){E.marginTop=this.marginTop}if(this.marginBottom!=null){E.marginBottom=this.marginBottom}if(this.marginLeft!=null){E.marginLeft=this.marginLeft}if(this.marginRight!=null){E.marginRight=this.marginRight}this._elem.css(E);var I=false,A=false,o,y;var C=B[0];var p=new e.jqplot.ColorGenerator(C.seriesColors);if(C.show){var J=C.data;if(this.numberRows){o=this.numberRows;if(!this.numberColumns){y=Math.ceil(J.length/o)}else{y=this.numberColumns}}else{if(this.numberColumns){y=this.numberColumns;o=Math.ceil(J.length/this.numberColumns)}else{o=J.length;y=1}}var H,G;var q,w,v;var x,z,F;var D=0;var u,t;for(H=0;H<o;H++){q=e(document.createElement("tr"));q.addClass("jqplot-table-legend");if(A){q.prependTo(this._elem)}else{q.appendTo(this._elem)}for(G=0;G<y;G++){if(D<J.length){x=this.labels[D]||J[D][0].toString();F=p.next();if(!A){if(H>0){I=true}else{I=false}}else{if(H==o-1){I=false}else{I=true}}z=(I)?this.rowSpacing:"0";w=e(document.createElement("td"));w.addClass("jqplot-table-legend jqplot-table-legend-swatch");w.css({textAlign:"center",paddingTop:z});u=e(document.createElement("div"));u.addClass("jqplot-table-legend-swatch-outline");t=e(document.createElement("div"));t.addClass("jqplot-table-legend-swatch");t.css({backgroundColor:F,borderColor:F});w.append(u.append(t));v=e(document.createElement("td"));v.addClass("jqplot-table-legend jqplot-table-legend-label");v.css("paddingTop",z);if(this.escapeHtml){v.text(x)}else{v.html(x)}if(A){v.prependTo(q);w.prependTo(q)}else{w.appendTo(q);v.appendTo(q)}I=true}D++}}}}return this._elem};e.jqplot.PieRenderer.prototype.handleMove=function(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];r.target.trigger("jqplotDataMouseOver",o);if(r.series[o[0]].highlightMouseOver&&!(o[0]==r.plugins.pieRenderer.highlightedSeriesIndex&&o[1]==r.series[o[0]]._highlightedPoint)){r.target.trigger("jqplotDataHighlight",o);d(r,o[0],o[1])}}else{if(s==null){k(r)}}};function c(s,r,p){p=p||{};p.axesDefaults=p.axesDefaults||{};p.legend=p.legend||{};p.seriesDefaults=p.seriesDefaults||{};var o=false;if(p.seriesDefaults.renderer==e.jqplot.PieRenderer){o=true}else{if(p.series){for(var q=0;q<p.series.length;q++){if(p.series[q].renderer==e.jqplot.PieRenderer){o=true}}}}if(o){p.axesDefaults.renderer=e.jqplot.PieAxisRenderer;p.legend.renderer=e.jqplot.PieLegendRenderer;p.legend.preDraw=true;p.seriesDefaults.pointLabels={show:false}}}function g(r,q,o){for(var p=0;p<this.series.length;p++){if(this.series[p].renderer.constructor==e.jqplot.PieRenderer){if(this.series[p].highlightMouseOver){this.series[p].highlightMouseDown=false}}}}function m(o){for(var p=0;p<this.series.length;p++){this.series[p].seriesColors=this.seriesColors;this.series[p].colorGenerator=e.jqplot.colorGenerator}}function d(t,r,q){var p=t.series[r];var o=t.plugins.pieRenderer.highlightCanvas;o._ctx.clearRect(0,0,o._ctx.canvas.width,o._ctx.canvas.height);p._highlightedPoint=q;t.plugins.pieRenderer.highlightedSeriesIndex=r;p.renderer.drawSlice.call(p,o._ctx,p._sliceAngles[q][0],p._sliceAngles[q][1],p.highlightColorGenerator.get(q),false)}function k(q){var o=q.plugins.pieRenderer.highlightCanvas;o._ctx.clearRect(0,0,o._ctx.canvas.width,o._ctx.canvas.height);for(var p=0;p<q.series.length;p++){q.series[p]._highlightedPoint=null}q.plugins.pieRenderer.highlightedSeriesIndex=null;q.target.trigger("jqplotDataUnhighlight")}function b(s,r,v,u,t){if(u){var q=[u.seriesIndex,u.pointIndex,u.data];var p=jQuery.Event("jqplotDataMouseOver");p.pageX=s.pageX;p.pageY=s.pageY;t.target.trigger(p,q);if(t.series[q[0]].highlightMouseOver&&!(q[0]==t.plugins.pieRenderer.highlightedSeriesIndex&&q[1]==t.series[q[0]]._highlightedPoint)){var o=jQuery.Event("jqplotDataHighlight");o.which=s.which;o.pageX=s.pageX;o.pageY=s.pageY;t.target.trigger(o,q);d(t,q[0],q[1])}}else{if(u==null){k(t)}}}function a(r,q,u,t,s){if(t){var p=[t.seriesIndex,t.pointIndex,t.data];if(s.series[p[0]].highlightMouseDown&&!(p[0]==s.plugins.pieRenderer.highlightedSeriesIndex&&p[1]==s.series[p[0]]._highlightedPoint)){var o=jQuery.Event("jqplotDataHighlight");o.which=r.which;o.pageX=r.pageX;o.pageY=r.pageY;s.target.trigger(o,p);d(s,p[0],p[1])}}else{if(t==null){k(s)}}}function l(q,p,t,s,r){var o=r.plugins.pieRenderer.highlightedSeriesIndex;if(o!=null&&r.series[o].highlightMouseDown){k(r)}}function f(r,q,u,t,s){if(t){var p=[t.seriesIndex,t.pointIndex,t.data];var o=jQuery.Event("jqplotDataClick");o.which=r.which;o.pageX=r.pageX;o.pageY=r.pageY;s.target.trigger(o,p)}}function n(s,r,v,u,t){if(u){var q=[u.seriesIndex,u.pointIndex,u.data];var o=t.plugins.pieRenderer.highlightedSeriesIndex;if(o!=null&&t.series[o].highlightMouseDown){k(t)}var p=jQuery.Event("jqplotDataRightClick");p.which=s.which;p.pageX=s.pageX;p.pageY=s.pageY;t.target.trigger(p,q)}}function i(){if(this.plugins.pieRenderer&&this.plugins.pieRenderer.highlightCanvas){this.plugins.pieRenderer.highlightCanvas.resetCanvas();this.plugins.pieRenderer.highlightCanvas=null}this.plugins.pieRenderer={highlightedSeriesIndex:null};this.plugins.pieRenderer.highlightCanvas=new e.jqplot.GenericCanvas();var p=e(this.targetId+" .jqplot-data-label");if(p.length){e(p[0]).before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-pieRenderer-highlight-canvas",this._plotDimensions,this))}else{this.eventCanvas._elem.before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-pieRenderer-highlight-canvas",this._plotDimensions,this))}var o=this.plugins.pieRenderer.highlightCanvas.setContext();this.eventCanvas._elem.bind("mouseleave",{plot:this},function(q){k(q.data.plot)})}e.jqplot.preInitHooks.push(c);e.jqplot.PieTickRenderer=function(){e.jqplot.AxisTickRenderer.call(this)};e.jqplot.PieTickRenderer.prototype=new e.jqplot.AxisTickRenderer();e.jqplot.PieTickRenderer.prototype.constructor=e.jqplot.PieTickRenderer})(jQuery);
js/jquery.jqplot.min.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ /* jqplot 1.0.9 | (c) 2009-2016 Chris Leonello | jplot.com
2
+ jsDate | (c) 2010-2016 Chris Leonello
3
+ */
4
+ !function(a){function b(b){a.jqplot.ElemContainer.call(this),this.name=b,this._series=[],this.show=!1,this.tickRenderer=a.jqplot.AxisTickRenderer,this.tickOptions={},this.labelRenderer=a.jqplot.AxisLabelRenderer,this.labelOptions={},this.label=null,this.showLabel=!0,this.min=null,this.max=null,this.autoscale=!1,this.pad=1.2,this.padMax=null,this.padMin=null,this.ticks=[],this.numberTicks,this.tickInterval,this.renderer=a.jqplot.LinearAxisRenderer,this.rendererOptions={},this.showTicks=!0,this.showTickMarks=!0,this.showMinorTicks=!0,this.drawMajorGridlines=!0,this.drawMinorGridlines=!1,this.drawMajorTickMarks=!0,this.drawMinorTickMarks=!0,this.useSeriesColor=!1,this.borderWidth=null,this.borderColor=null,this.scaleToHiddenSeries=!1,this._dataBounds={min:null,max:null},this._intervalStats=[],this._offsets={min:null,max:null},this._ticks=[],this._label=null,this.syncTicks=null,this.tickSpacing=75,this._min=null,this._max=null,this._tickInterval=null,this._numberTicks=null,this.__ticks=null,this._options={}}function c(b){a.jqplot.ElemContainer.call(this),this.show=!1,this.location="ne",this.labels=[],this.showLabels=!0,this.showSwatches=!0,this.placement="insideGrid",this.xoffset=0,this.yoffset=0,this.border,this.background,this.textColor,this.fontFamily,this.fontSize,this.rowSpacing="0.5em",this.renderer=a.jqplot.TableLegendRenderer,this.rendererOptions={},this.preDraw=!1,this.marginTop=null,this.marginRight=null,this.marginBottom=null,this.marginLeft=null,this.escapeHtml=!1,this._series=[],a.extend(!0,this,b)}function d(b){a.jqplot.ElemContainer.call(this),this.text=b,this.show=!0,this.fontFamily,this.fontSize,this.textAlign,this.textColor,this.renderer=a.jqplot.DivTitleRenderer,this.rendererOptions={},this.escapeHtml=!1}function e(b){b=b||{},a.jqplot.ElemContainer.call(this),this.show=!0,this.xaxis="xaxis",this._xaxis,this.yaxis="yaxis",this._yaxis,this.gridBorderWidth=2,this.renderer=a.jqplot.LineRenderer,this.rendererOptions={},this.data=[],this.gridData=[],this.label="",this.showLabel=!0,this.color,this.negativeColor,this.lineWidth=2.5,this.lineJoin="round",this.lineCap="round",this.linePattern="solid",this.shadow=!0,this.shadowAngle=45,this.shadowOffset=1.25,this.shadowDepth=3,this.shadowAlpha="0.1",this.breakOnNull=!1,this.markerRenderer=a.jqplot.MarkerRenderer,this.markerOptions={},this.showLine=!0,this.showMarker=!0,this.index,this.fill=!1,this.fillColor,this.fillAlpha,this.fillAndStroke=!1,this.disableStack=!1,this._stack=!1,this.neighborThreshold=4,this.fillToZero=!1,this.fillToValue=0,this.fillAxis="y",this.useNegativeColors=!0,this._stackData=[],this._plotData=[],this._plotValues={x:[],y:[]},this._intervals={x:{},y:{}},this._prevPlotData=[],this._prevGridData=[],this._stackAxis="y",this._primaryAxis="_xaxis",this.canvas=new a.jqplot.GenericCanvas,this.shadowCanvas=new a.jqplot.GenericCanvas,this.plugins={},this._sumy=0,this._sumx=0,this._type="",this.step=!1}function f(){a.jqplot.ElemContainer.call(this),this.drawGridlines=!0,this.gridLineColor="#cccccc",this.gridLineWidth=1,this.background="#fffdf6",this.borderColor="#999999",this.borderWidth=2,this.drawBorder=!0,this.shadow=!0,this.shadowAngle=45,this.shadowOffset=1.5,this.shadowWidth=3,this.shadowDepth=3,this.shadowColor=null,this.shadowAlpha="0.07",this._left,this._top,this._right,this._bottom,this._width,this._height,this._axes=[],this.renderer=a.jqplot.CanvasGridRenderer,this.rendererOptions={},this._offsets={top:null,bottom:null,left:null,right:null}}function g(){function h(a){for(var b,c=0;c<a.length;c++)for(var d,e=[a[c].data,a[c]._stackData,a[c]._plotData,a[c]._prevPlotData],f=0;4>f;f++)if(d=!0,b=e[f],"x"==a[c]._stackAxis){for(var g=0;g<b.length;g++)if("number"!=typeof b[g][1]){d=!1;break}d&&b.sort(function(a,b){return a[1]-b[1]})}else{for(var g=0;g<b.length;g++)if("number"!=typeof b[g][0]){d=!1;break}d&&b.sort(function(a,b){return a[0]-b[0]})}}function i(a){var b,c,d=a.data.plot,e=d.eventCanvas._elem.offset(),f={x:a.pageX-e.left,y:a.pageY-e.top},g={xaxis:null,yaxis:null,x2axis:null,y2axis:null,y3axis:null,y4axis:null,y5axis:null,y6axis:null,y7axis:null,y8axis:null,y9axis:null,yMidAxis:null},h=["xaxis","yaxis","x2axis","y2axis","y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis","yMidAxis"],i=d.axes;for(b=11;b>0;b--)c=h[b-1],i[c].show&&(g[c]=i[c].series_p2u(f[c.charAt(0)]));return{offsets:e,gridPos:f,dataPos:g}}function j(b,c){function d(a,b,c){var d=(b[1]-c[1])/(b[0]-c[0]),e=b[1]-d*b[0],f=a+b[1];return[(f-e)/d,f]}var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x=c.series;for(g=c.seriesStack.length-1;g>=0;g--)switch(e=c.seriesStack[g],h=x[e],u=h._highlightThreshold,h.renderer.constructor){case a.jqplot.BarRenderer:for(j=b.x,k=b.y,f=0;f<h._barPoints.length;f++)if(t=h._barPoints[f],s=h.gridData[f],j>t[0][0]&&j<t[2][0]&&(k>t[2][1]&&k<t[0][1]||k<t[2][1]&&k>t[0][1]))return{seriesIndex:h.index,pointIndex:f,gridData:s,data:h.data[f],points:h._barPoints[f]};break;case a.jqplot.PyramidRenderer:for(j=b.x,k=b.y,f=0;f<h._barPoints.length;f++)if(t=h._barPoints[f],s=h.gridData[f],j>t[0][0]+u[0][0]&&j<t[2][0]+u[2][0]&&k>t[2][1]&&k<t[0][1])return{seriesIndex:h.index,pointIndex:f,gridData:s,data:h.data[f],points:h._barPoints[f]};break;case a.jqplot.DonutRenderer:if(n=h.startAngle/180*Math.PI,j=b.x-h._center[0],k=b.y-h._center[1],i=Math.sqrt(Math.pow(j,2)+Math.pow(k,2)),j>0&&-k>=0?l=2*Math.PI-Math.atan(-k/j):j>0&&0>-k?l=-Math.atan(-k/j):0>j?l=Math.PI-Math.atan(-k/j):0==j&&-k>0?l=3*Math.PI/2:0==j&&0>-k?l=Math.PI/2:0==j&&0==k&&(l=0),n&&(l-=n,0>l?l+=2*Math.PI:l>2*Math.PI&&(l-=2*Math.PI)),m=h.sliceMargin/180*Math.PI,i<h._radius&&i>h._innerRadius)for(f=0;f<h.gridData.length;f++)if(o=f>0?h.gridData[f-1][1]+m:m,p=h.gridData[f][1],l>o&&p>l)return{seriesIndex:h.index,pointIndex:f,gridData:[b.x,b.y],data:h.data[f]};break;case a.jqplot.PieRenderer:if(n=h.startAngle/180*Math.PI,j=b.x-h._center[0],k=b.y-h._center[1],i=Math.sqrt(Math.pow(j,2)+Math.pow(k,2)),j>0&&-k>=0?l=2*Math.PI-Math.atan(-k/j):j>0&&0>-k?l=-Math.atan(-k/j):0>j?l=Math.PI-Math.atan(-k/j):0==j&&-k>0?l=3*Math.PI/2:0==j&&0>-k?l=Math.PI/2:0==j&&0==k&&(l=0),n&&(l-=n,0>l?l+=2*Math.PI:l>2*Math.PI&&(l-=2*Math.PI)),m=h.sliceMargin/180*Math.PI,i<h._radius)for(f=0;f<h.gridData.length;f++)if(o=f>0?h.gridData[f-1][1]+m:m,p=h.gridData[f][1],l>o&&p>l)return{seriesIndex:h.index,pointIndex:f,gridData:[b.x,b.y],data:h.data[f]};break;case a.jqplot.BubbleRenderer:j=b.x,k=b.y;var y=null;if(h.show){for(var f=0;f<h.gridData.length;f++)s=h.gridData[f],r=Math.sqrt((j-s[0])*(j-s[0])+(k-s[1])*(k-s[1])),r<=s[2]&&(q>=r||null==q)&&(q=r,y={seriesIndex:e,pointIndex:f,gridData:s,data:h.data[f]});if(null!=y)return y}break;case a.jqplot.FunnelRenderer:j=b.x,k=b.y;var z,A,B,C=h._vertices,D=C[0],E=C[C.length-1];for(z=d(k,D[0],E[3]),A=d(k,D[1],E[2]),f=0;f<C.length;f++)if(B=C[f],k>=B[0][1]&&k<=B[3][1]&&j>=z[0]&&j<=A[0])return{seriesIndex:h.index,pointIndex:f,gridData:null,data:h.data[f]};break;case a.jqplot.LineRenderer:if(j=b.x,k=b.y,i=h.renderer,h.show){if(!(!(h.fill||h.renderer.bands.show&&h.renderer.bands.fill)||c.plugins.highlighter&&c.plugins.highlighter.show)){var F=!1;if(j>h._boundingBox[0][0]&&j<h._boundingBox[1][0]&&k>h._boundingBox[1][1]&&k<h._boundingBox[0][1])for(var G,H=h._areaPoints.length,f=H-1,G=0;H>G;G++){var I=[h._areaPoints[G][0],h._areaPoints[G][1]],J=[h._areaPoints[f][0],h._areaPoints[f][1]];(I[1]<k&&J[1]>=k||J[1]<k&&I[1]>=k)&&I[0]+(k-I[1])/(J[1]-I[1])*(J[0]-I[0])<j&&(F=!F),f=G}if(F)return{seriesIndex:e,pointIndex:null,gridData:h.gridData,data:h.data,points:h._areaPoints};break}w=h.markerRenderer.size/2+h.neighborThreshold,v=w>0?w:0;for(var f=0;f<h.gridData.length;f++)if(s=h.gridData[f],i.constructor==a.jqplot.OHLCRenderer)if(i.candleStick){var K=h._yaxis.series_u2p;if(j>=s[0]-i._bodyWidth/2&&j<=s[0]+i._bodyWidth/2&&k>=K(h.data[f][2])&&k<=K(h.data[f][3]))return{seriesIndex:e,pointIndex:f,gridData:s,data:h.data[f]}}else if(i.hlc){var K=h._yaxis.series_u2p;if(j>=s[0]-i._tickLength&&j<=s[0]+i._tickLength&&k>=K(h.data[f][1])&&k<=K(h.data[f][2]))return{seriesIndex:e,pointIndex:f,gridData:s,data:h.data[f]}}else{var K=h._yaxis.series_u2p;if(j>=s[0]-i._tickLength&&j<=s[0]+i._tickLength&&k>=K(h.data[f][2])&&k<=K(h.data[f][3]))return{seriesIndex:e,pointIndex:f,gridData:s,data:h.data[f]}}else if(null!=s[0]&&null!=s[1]&&(r=Math.sqrt((j-s[0])*(j-s[0])+(k-s[1])*(k-s[1])),v>=r&&(q>=r||null==q)))return q=r,{seriesIndex:e,pointIndex:f,gridData:s,data:h.data[f]}}break;default:if(j=b.x,k=b.y,i=h.renderer,h.show){w=h.markerRenderer.size/2+h.neighborThreshold,v=w>0?w:0;for(var f=0;f<h.gridData.length;f++)if(s=h.gridData[f],i.constructor==a.jqplot.OHLCRenderer)if(i.candleStick){var K=h._yaxis.series_u2p;if(j>=s[0]-i._bodyWidth/2&&j<=s[0]+i._bodyWidth/2&&k>=K(h.data[f][2])&&k<=K(h.data[f][3]))return{seriesIndex:e,pointIndex:f,gridData:s,data:h.data[f]}}else if(i.hlc){var K=h._yaxis.series_u2p;if(j>=s[0]-i._tickLength&&j<=s[0]+i._tickLength&&k>=K(h.data[f][1])&&k<=K(h.data[f][2]))return{seriesIndex:e,pointIndex:f,gridData:s,data:h.data[f]}}else{var K=h._yaxis.series_u2p;if(j>=s[0]-i._tickLength&&j<=s[0]+i._tickLength&&k>=K(h.data[f][2])&&k<=K(h.data[f][3]))return{seriesIndex:e,pointIndex:f,gridData:s,data:h.data[f]}}else if(r=Math.sqrt((j-s[0])*(j-s[0])+(k-s[1])*(k-s[1])),v>=r&&(q>=r||null==q))return q=r,{seriesIndex:e,pointIndex:f,gridData:s,data:h.data[f]}}}return null}this.animate=!1,this.animateReplot=!1,this.axes={xaxis:new b("xaxis"),yaxis:new b("yaxis"),x2axis:new b("x2axis"),y2axis:new b("y2axis"),y3axis:new b("y3axis"),y4axis:new b("y4axis"),y5axis:new b("y5axis"),y6axis:new b("y6axis"),y7axis:new b("y7axis"),y8axis:new b("y8axis"),y9axis:new b("y9axis"),yMidAxis:new b("yMidAxis")},this.baseCanvas=new a.jqplot.GenericCanvas,this.captureRightClick=!1,this.data=[],this.dataRenderer,this.dataRendererOptions,this.defaults={axesDefaults:{},axes:{xaxis:{},yaxis:{},x2axis:{},y2axis:{},y3axis:{},y4axis:{},y5axis:{},y6axis:{},y7axis:{},y8axis:{},y9axis:{},yMidAxis:{}},seriesDefaults:{},series:[]},this.defaultAxisStart=1,this.drawIfHidden=!1,this.eventCanvas=new a.jqplot.GenericCanvas,this.fillBetween={series1:null,series2:null,color:null,baseSeries:0,fill:!0},this.fontFamily,this.fontSize,this.grid=new f,this.legend=new c,this.noDataIndicator={show:!1,indicator:"Loading Data...",axes:{xaxis:{min:0,max:10,tickInterval:2,show:!0},yaxis:{min:0,max:12,tickInterval:3,show:!0}}},this.negativeSeriesColors=a.jqplot.config.defaultNegativeColors,this.options={},this.previousSeriesStack=[],this.plugins={},this.series=[],this.seriesStack=[],this.seriesColors=a.jqplot.config.defaultColors,this.sortData=!0,this.stackSeries=!1,this.syncXTicks=!0,this.syncYTicks=!0,this.target=null,this.targetId=null,this.textColor,this.title=new d,this._drawCount=0,this._sumy=0,this._sumx=0,this._stackData=[],this._plotData=[],this._width=null,this._height=null,this._plotDimensions={height:null,width:null},this._gridPadding={top:null,right:null,bottom:null,left:null},this._defaultGridPadding={top:10,right:10,bottom:23,left:10},this._addDomReference=a.jqplot.config.addDomReference,this.preInitHooks=new a.jqplot.HooksManager,this.postInitHooks=new a.jqplot.HooksManager,this.preParseOptionsHooks=new a.jqplot.HooksManager,this.postParseOptionsHooks=new a.jqplot.HooksManager,this.preDrawHooks=new a.jqplot.HooksManager,this.postDrawHooks=new a.jqplot.HooksManager,this.preDrawSeriesHooks=new a.jqplot.HooksManager,this.postDrawSeriesHooks=new a.jqplot.HooksManager,this.preDrawLegendHooks=new a.jqplot.HooksManager,this.addLegendRowHooks=new a.jqplot.HooksManager,this.preSeriesInitHooks=new a.jqplot.HooksManager,this.postSeriesInitHooks=new a.jqplot.HooksManager,this.preParseSeriesOptionsHooks=new a.jqplot.HooksManager,this.postParseSeriesOptionsHooks=new a.jqplot.HooksManager,this.eventListenerHooks=new a.jqplot.EventListenerManager,this.preDrawSeriesShadowHooks=new a.jqplot.HooksManager,this.postDrawSeriesShadowHooks=new a.jqplot.HooksManager,this.colorGenerator=new a.jqplot.ColorGenerator,this.negativeColorGenerator=new a.jqplot.ColorGenerator,this.canvasManager=new a.jqplot.CanvasManager,this.themeEngine=new a.jqplot.ThemeEngine;this.init=function(c,d,e){e=e||{};for(var f=0;f<a.jqplot.preInitHooks.length;f++)a.jqplot.preInitHooks[f].call(this,c,d,e);for(var f=0;f<this.preInitHooks.hooks.length;f++)this.preInitHooks.hooks[f].call(this,c,d,e);if(this.targetId="#"+c,this.target=a("#"+c),this._addDomReference&&this.target.data("jqplot",this),this.target.removeClass("jqplot-error"),!this.target.get(0))throw new Error("No plot target specified");if("static"==this.target.css("position")&&this.target.css("position","relative"),this.target.hasClass("jqplot-target")||this.target.addClass("jqplot-target"),this.target.height())this._height=g=this.target.height();else{var g;g=e&&e.height?parseInt(e.height,10):this.target.attr("data-height")?parseInt(this.target.attr("data-height"),10):parseInt(a.jqplot.config.defaultHeight,10),this._height=g,this.target.css("height",g+"px")}if(this.target.width())this._width=i=this.target.width();else{var i;i=e&&e.width?parseInt(e.width,10):this.target.attr("data-width")?parseInt(this.target.attr("data-width"),10):parseInt(a.jqplot.config.defaultWidth,10),this._width=i,this.target.css("width",i+"px")}for(var f=0,j=G.length;j>f;f++)this.axes[G[f]]=new b(G[f]);if(this._plotDimensions.height=this._height,this._plotDimensions.width=this._width,this.grid._plotDimensions=this._plotDimensions,this.title._plotDimensions=this._plotDimensions,this.baseCanvas._plotDimensions=this._plotDimensions,this.eventCanvas._plotDimensions=this._plotDimensions,this.legend._plotDimensions=this._plotDimensions,this._height<=0||this._width<=0||!this._height||!this._width)throw new Error("Canvas dimension not set");if(e.dataRenderer&&a.isFunction(e.dataRenderer)&&(e.dataRendererOptions&&(this.dataRendererOptions=e.dataRendererOptions),this.dataRenderer=e.dataRenderer,d=this.dataRenderer(d,this,this.dataRendererOptions)),e.noDataIndicator&&a.isPlainObject(e.noDataIndicator)&&a.extend(!0,this.noDataIndicator,e.noDataIndicator),null==d||0==a.isArray(d)||0==d.length||0==a.isArray(d[0])||0==d[0].length){if(0==this.noDataIndicator.show)throw new Error("No data specified");for(var k in this.noDataIndicator.axes)for(var l in this.noDataIndicator.axes[k])this.axes[k][l]=this.noDataIndicator.axes[k][l];this.postDrawHooks.add(function(){var b=this.eventCanvas.getHeight(),c=this.eventCanvas.getWidth(),d=a('<div class="jqplot-noData-container" style="position:absolute;"></div>');this.target.append(d),d.height(b),d.width(c),d.css("top",this.eventCanvas._offsets.top),d.css("left",this.eventCanvas._offsets.left);var e=a('<div class="jqplot-noData-contents" style="text-align:center; position:relative; margin-left:auto; margin-right:auto;"></div>');d.append(e),e.html(this.noDataIndicator.indicator);var f=e.height(),g=e.width();e.height(f),e.width(g),e.css("top",(b-f)/2+"px")})}this.data=a.extend(!0,[],d),this.parseOptions(e),this.textColor&&this.target.css("color",this.textColor),this.fontFamily&&this.target.css("font-family",this.fontFamily),this.fontSize&&this.target.css("font-size",this.fontSize),this.title.init(),this.legend.init(),this._sumy=0,this._sumx=0,this.computePlotData();for(var f=0;f<this.series.length;f++){this.seriesStack.push(f),this.previousSeriesStack.push(f),this.series[f].shadowCanvas._plotDimensions=this._plotDimensions,this.series[f].canvas._plotDimensions=this._plotDimensions;for(var m=0;m<a.jqplot.preSeriesInitHooks.length;m++)a.jqplot.preSeriesInitHooks[m].call(this.series[f],c,this.data,this.options.seriesDefaults,this.options.series[f],this);for(var m=0;m<this.preSeriesInitHooks.hooks.length;m++)this.preSeriesInitHooks.hooks[m].call(this.series[f],c,this.data,this.options.seriesDefaults,this.options.series[f],this);this.series[f]._plotDimensions=this._plotDimensions,this.series[f].init(f,this.grid.borderWidth,this);for(var m=0;m<a.jqplot.postSeriesInitHooks.length;m++)a.jqplot.postSeriesInitHooks[m].call(this.series[f],c,this.data,this.options.seriesDefaults,this.options.series[f],this);for(var m=0;m<this.postSeriesInitHooks.hooks.length;m++)this.postSeriesInitHooks.hooks[m].call(this.series[f],c,this.data,this.options.seriesDefaults,this.options.series[f],this);this._sumy+=this.series[f]._sumy,this._sumx+=this.series[f]._sumx}for(var n,o,f=0,j=G.length;j>f;f++)n=G[f],o=this.axes[n],o._plotDimensions=this._plotDimensions,o.init(),null==this.axes[n].borderColor&&("x"!==n.charAt(0)&&o.useSeriesColor===!0&&o.show?o.borderColor=o._series[0].color:o.borderColor=this.grid.borderColor);this.sortData&&h(this.series),this.grid.init(),this.grid._axes=this.axes,this.legend._series=this.series;for(var f=0;f<a.jqplot.postInitHooks.length;f++)a.jqplot.postInitHooks[f].call(this,c,this.data,e);for(var f=0;f<this.postInitHooks.hooks.length;f++)this.postInitHooks.hooks[f].call(this,c,this.data,e)},this.resetAxesScale=function(b,c){var d=c||{},e=b||this.axes;if(e===!0&&(e=this.axes),a.isArray(e))for(var f=0;f<e.length;f++)this.axes[e[f]].resetScale(d[e[f]]);else if("object"==typeof e)for(var g in e)this.axes[g].resetScale(d[g])},this.reInitialize=function(c,d){for(var e=a.extend(!0,{},this.options,d),f=this.targetId.substr(1),g=null==c?this.data:c,i=0;i<a.jqplot.preInitHooks.length;i++)a.jqplot.preInitHooks[i].call(this,f,g,e);for(var i=0;i<this.preInitHooks.hooks.length;i++)this.preInitHooks.hooks[i].call(this,f,g,e);if(this._height=this.target.height(),this._width=this.target.width(),this._height<=0||this._width<=0||!this._height||!this._width)throw new Error("Target dimension not set");this._plotDimensions.height=this._height,this._plotDimensions.width=this._width,this.grid._plotDimensions=this._plotDimensions,this.title._plotDimensions=this._plotDimensions,this.baseCanvas._plotDimensions=this._plotDimensions,this.eventCanvas._plotDimensions=this._plotDimensions,this.legend._plotDimensions=this._plotDimensions;for(var j,k,l,m,i=0,n=G.length;n>i;i++){j=G[i],m=this.axes[j],k=m._ticks;for(var l=0,o=k.length;o>l;l++){var p=k[l]._elem;p&&(a.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==F&&window.G_vmlCanvasManager.uninitElement(p.get(0)),p.emptyForce(),p=null,k._elem=null)}k=null,delete m.ticks,delete m._ticks,this.axes[j]=new b(j),this.axes[j]._plotWidth=this._width,this.axes[j]._plotHeight=this._height}c&&(e.dataRenderer&&a.isFunction(e.dataRenderer)&&(e.dataRendererOptions&&(this.dataRendererOptions=e.dataRendererOptions),this.dataRenderer=e.dataRenderer,c=this.dataRenderer(c,this,this.dataRendererOptions)),this.data=a.extend(!0,[],c)),d&&this.parseOptions(e),this.title._plotWidth=this._width,this.textColor&&this.target.css("color",this.textColor),this.fontFamily&&this.target.css("font-family",this.fontFamily),this.fontSize&&this.target.css("font-size",this.fontSize),this.title.init(),this.legend.init(),this._sumy=0,this._sumx=0,this.seriesStack=[],this.previousSeriesStack=[],this.computePlotData();for(var i=0,n=this.series.length;n>i;i++){this.seriesStack.push(i),this.previousSeriesStack.push(i),this.series[i].shadowCanvas._plotDimensions=this._plotDimensions,this.series[i].canvas._plotDimensions=this._plotDimensions;for(var l=0;l<a.jqplot.preSeriesInitHooks.length;l++)a.jqplot.preSeriesInitHooks[l].call(this.series[i],f,this.data,this.options.seriesDefaults,this.options.series[i],this);for(var l=0;l<this.preSeriesInitHooks.hooks.length;l++)this.preSeriesInitHooks.hooks[l].call(this.series[i],f,this.data,this.options.seriesDefaults,this.options.series[i],this);this.series[i]._plotDimensions=this._plotDimensions,this.series[i].init(i,this.grid.borderWidth,this);for(var l=0;l<a.jqplot.postSeriesInitHooks.length;l++)a.jqplot.postSeriesInitHooks[l].call(this.series[i],f,this.data,this.options.seriesDefaults,this.options.series[i],this);for(var l=0;l<this.postSeriesInitHooks.hooks.length;l++)this.postSeriesInitHooks.hooks[l].call(this.series[i],f,this.data,this.options.seriesDefaults,this.options.series[i],this);this._sumy+=this.series[i]._sumy,this._sumx+=this.series[i]._sumx}for(var i=0,n=G.length;n>i;i++)j=G[i],m=this.axes[j],m._plotDimensions=this._plotDimensions,m.init(),null==m.borderColor&&("x"!==j.charAt(0)&&m.useSeriesColor===!0&&m.show?m.borderColor=m._series[0].color:m.borderColor=this.grid.borderColor);this.sortData&&h(this.series),this.grid.init(),this.grid._axes=this.axes,this.legend._series=this.series;for(var i=0,n=a.jqplot.postInitHooks.length;n>i;i++)a.jqplot.postInitHooks[i].call(this,f,this.data,e);for(var i=0,n=this.postInitHooks.hooks.length;n>i;i++)this.postInitHooks.hooks[i].call(this,f,this.data,e)},this.quickInit=function(){if(this._height=this.target.height(),this._width=this.target.width(),this._height<=0||this._width<=0||!this._height||!this._width)throw new Error("Target dimension not set");this._plotDimensions.height=this._height,this._plotDimensions.width=this._width,this.grid._plotDimensions=this._plotDimensions,this.title._plotDimensions=this._plotDimensions,this.baseCanvas._plotDimensions=this._plotDimensions,this.eventCanvas._plotDimensions=this._plotDimensions,this.legend._plotDimensions=this._plotDimensions;for(var b in this.axes)this.axes[b]._plotWidth=this._width,this.axes[b]._plotHeight=this._height;this.title._plotWidth=this._width,this.textColor&&this.target.css("color",this.textColor),this.fontFamily&&this.target.css("font-family",this.fontFamily),this.fontSize&&this.target.css("font-size",this.fontSize),this._sumy=0,this._sumx=0,this.computePlotData();for(var c=0;c<this.series.length;c++)"line"===this.series[c]._type&&this.series[c].renderer.bands.show&&this.series[c].renderer.initBands.call(this.series[c],this.series[c].renderer.options,this),this.series[c]._plotDimensions=this._plotDimensions,this.series[c].canvas._plotDimensions=this._plotDimensions,this._sumy+=this.series[c]._sumy,this._sumx+=this.series[c]._sumx;for(var d,e=0;12>e;e++){d=G[e];for(var f=this.axes[d]._ticks,c=0;c<f.length;c++){var g=f[c]._elem;g&&(a.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==F&&window.G_vmlCanvasManager.uninitElement(g.get(0)),g.emptyForce(),g=null,f._elem=null)}f=null,this.axes[d]._plotDimensions=this._plotDimensions,this.axes[d]._ticks=[]}this.sortData&&h(this.series),this.grid._axes=this.axes,this.legend._series=this.series},this.computePlotData=function(){this._plotData=[],this._stackData=[];var b,c,d;for(c=0,d=this.series.length;d>c;c++){b=this.series[c],this._plotData.push([]),this._stackData.push([]);var e=b.data;this._plotData[c]=a.extend(!0,[],e),this._stackData[c]=a.extend(!0,[],e),b._plotData=this._plotData[c],b._stackData=this._stackData[c];var f={x:[],y:[]};if(this.stackSeries&&!b.disableStack){b._stack=!0;for(var g="x"===b._stackAxis?0:1,h=0,i=e.length;i>h;h++){var j=e[h][g];if(null==j&&(j=0),this._plotData[c][h][g]=j,this._stackData[c][h][g]=j,c>0)for(var k=c;k--;){var l=this._plotData[k][h][g];if(j*l>=0){this._plotData[c][h][g]+=l,this._stackData[c][h][g]+=l;break}}}}else{for(var m=0;m<b.data.length;m++)f.x.push(b.data[m][0]),f.y.push(b.data[m][1]);this._stackData.push(b.data),this.series[c]._stackData=b.data,this._plotData.push(b.data),b._plotData=b.data,b._plotValues=f}for(c>0&&(b._prevPlotData=this.series[c-1]._plotData),b._sumy=0,b._sumx=0,m=b.data.length-1;m>-1;m--)b._sumy+=b.data[m][1],b._sumx+=b.data[m][0]}},this.populatePlotData=function(b,c){this._plotData=[],this._stackData=[],b._stackData=[],b._plotData=[];var d={x:[],y:[]};if(this.stackSeries&&!b.disableStack){b._stack=!0;for(var e,f,g,h,i="x"===b._stackAxis?0:1,j=a.extend(!0,[],b.data),k=a.extend(!0,[],b.data),l=0;c>l;l++)for(var m=this.series[l].data,n=0;n<m.length;n++)g=m[n],e=null!=g[0]?g[0]:0,f=null!=g[1]?g[1]:0,j[n][0]+=e,j[n][1]+=f,h=i?f:e,b.data[n][i]*h>=0&&(k[n][i]+=h);for(var o=0;o<k.length;o++)d.x.push(k[o][0]),d.y.push(k[o][1]);this._plotData.push(k),this._stackData.push(j),b._stackData=j,b._plotData=k,b._plotValues=d}else{for(var o=0;o<b.data.length;o++)d.x.push(b.data[o][0]),d.y.push(b.data[o][1]);this._stackData.push(b.data),this.series[c]._stackData=b.data,this._plotData.push(b.data),b._plotData=b.data,b._plotValues=d}for(c>0&&(b._prevPlotData=this.series[c-1]._plotData),b._sumy=0,b._sumx=0,o=b.data.length-1;o>-1;o--)b._sumy+=b.data[o][1],b._sumx+=b.data[o][0]},this.getNextSeriesColor=function(a){var b=0,c=a.seriesColors;return function(){return b<c.length?c[b++]:(b=0,c[b++])}}(this),this.parseOptions=function(b){for(var c=0;c<this.preParseOptionsHooks.hooks.length;c++)this.preParseOptionsHooks.hooks[c].call(this,b);for(var c=0;c<a.jqplot.preParseOptionsHooks.length;c++)a.jqplot.preParseOptionsHooks[c].call(this,b);this.options=a.extend(!0,{},this.defaults,b);var d=this.options;if(this.animate=d.animate,this.animateReplot=d.animateReplot,this.stackSeries=d.stackSeries,a.isPlainObject(d.fillBetween))for(var f,g=["series1","series2","color","baseSeries","fill"],c=0,h=g.length;h>c;c++)f=g[c],null!=d.fillBetween[f]&&(this.fillBetween[f]=d.fillBetween[f]);d.seriesColors&&(this.seriesColors=d.seriesColors),d.negativeSeriesColors&&(this.negativeSeriesColors=d.negativeSeriesColors),d.captureRightClick&&(this.captureRightClick=d.captureRightClick),this.defaultAxisStart=b&&null!=b.defaultAxisStart?b.defaultAxisStart:this.defaultAxisStart,this.colorGenerator.setColors(this.seriesColors),this.negativeColorGenerator.setColors(this.negativeSeriesColors),a.extend(!0,this._gridPadding,d.gridPadding),this.sortData=null!=d.sortData?d.sortData:this.sortData;for(var c=0;12>c;c++){var i=G[c],j=this.axes[i];j._options=a.extend(!0,{},d.axesDefaults,d.axes[i]),a.extend(!0,j,d.axesDefaults,d.axes[i]),j._plotWidth=this._width,j._plotHeight=this._height}var k=function(b,c,d){var e,f,g=[];if(c=c||"vertical",a.isArray(b[0]))a.extend(!0,g,b);else for(e=0,f=b.length;f>e;e++)"vertical"==c?g.push([d+e,b[e]]):g.push([b[e],d+e]);return g};this.series=[];for(var c=0;c<this.data.length;c++){for(var l=a.extend(!0,{index:c},{seriesColors:this.seriesColors,negativeSeriesColors:this.negativeSeriesColors},this.options.seriesDefaults,this.options.series[c],{rendererOptions:{animation:{show:this.animate}}}),g=new e(l),m=0;m<a.jqplot.preParseSeriesOptionsHooks.length;m++)a.jqplot.preParseSeriesOptionsHooks[m].call(g,this.options.seriesDefaults,this.options.series[c]);for(var m=0;m<this.preParseSeriesOptionsHooks.hooks.length;m++)this.preParseSeriesOptionsHooks.hooks[m].call(g,this.options.seriesDefaults,this.options.series[c]);a.extend(!0,g,l);var n="vertical";switch(g.renderer===a.jqplot.BarRenderer&&g.rendererOptions&&"horizontal"==g.rendererOptions.barDirection&&(n="horizontal",g._stackAxis="x",g._primaryAxis="_yaxis"),g.data=k(this.data[c],n,this.defaultAxisStart),g.xaxis){case"xaxis":g._xaxis=this.axes.xaxis;break;case"x2axis":g._xaxis=this.axes.x2axis}g._yaxis=this.axes[g.yaxis],g._xaxis._series.push(g),g._yaxis._series.push(g),g.show?(g._xaxis.show=!0,g._yaxis.show=!0):(g._xaxis.scaleToHiddenSeries&&(g._xaxis.show=!0),g._yaxis.scaleToHiddenSeries&&(g._yaxis.show=!0)),g.label||(g.label="Series "+(c+1).toString()),this.series.push(g);for(var m=0;m<a.jqplot.postParseSeriesOptionsHooks.length;m++)a.jqplot.postParseSeriesOptionsHooks[m].call(this.series[c],this.options.seriesDefaults,this.options.series[c]);for(var m=0;m<this.postParseSeriesOptionsHooks.hooks.length;m++)this.postParseSeriesOptionsHooks.hooks[m].call(this.series[c],this.options.seriesDefaults,this.options.series[c])}a.extend(!0,this.grid,this.options.grid);for(var c=0,h=G.length;h>c;c++){var i=G[c],j=this.axes[i];null==j.borderWidth&&(j.borderWidth=this.grid.borderWidth)}"string"==typeof this.options.title?this.title.text=this.options.title:"object"==typeof this.options.title&&a.extend(!0,this.title,this.options.title),this.title._plotWidth=this._width,this.legend.setOptions(this.options.legend);for(var c=0;c<a.jqplot.postParseOptionsHooks.length;c++)a.jqplot.postParseOptionsHooks[c].call(this,b);for(var c=0;c<this.postParseOptionsHooks.hooks.length;c++)this.postParseOptionsHooks.hooks[c].call(this,b)},this.destroy=function(){this.canvasManager.freeAllCanvases(),this.eventCanvas&&this.eventCanvas._elem&&this.eventCanvas._elem.unbind(),this.target.empty(),this.target[0].innerHTML=""},this.replot=function(b){var c=b||{},d=c.data||null,e=c.clear===!1?!1:!0,f=c.resetAxes||!1;delete c.data,delete c.clear,delete c.resetAxes,this.target.trigger("jqplotPreReplot"),e&&this.destroy(),d||!a.isEmptyObject(c)?this.reInitialize(d,c):this.quickInit(),f&&this.resetAxesScale(f,c.axes),this.draw(),this.target.trigger("jqplotPostReplot")},this.redraw=function(a){a=null!=a?a:!0,this.target.trigger("jqplotPreRedraw"),a&&(this.canvasManager.freeAllCanvases(),this.eventCanvas._elem.unbind(),this.target.empty());for(var b in this.axes)this.axes[b]._ticks=[];this.computePlotData(),this._sumy=0,this._sumx=0;for(var c=0,d=this.series.length;d>c;c++)this._sumy+=this.series[c]._sumy,this._sumx+=this.series[c]._sumx;this.draw(),this.target.trigger("jqplotPostRedraw")},this.draw=function(){if(this.drawIfHidden||this.target.is(":visible")){this.target.trigger("jqplotPreDraw");var b,c,d;for(b=0,d=a.jqplot.preDrawHooks.length;d>b;b++)a.jqplot.preDrawHooks[b].call(this);for(b=0,d=this.preDrawHooks.hooks.length;d>b;b++)this.preDrawHooks.hooks[b].apply(this,this.preDrawSeriesHooks.args[b]);this.target.append(this.baseCanvas.createElement({left:0,right:0,top:0,bottom:0},"jqplot-base-canvas",null,this)),this.baseCanvas.setContext(),this.target.append(this.title.draw()),this.title.pack({top:0,left:0});var e=this.legend.draw({},this),f={top:0,left:0,bottom:0,right:0};if("outsideGrid"==this.legend.placement){switch(this.target.append(e),this.legend.location){case"n":f.top+=this.legend.getHeight();break;case"s":f.bottom+=this.legend.getHeight();break;case"ne":case"e":case"se":f.right+=this.legend.getWidth();break;case"nw":case"w":case"sw":f.left+=this.legend.getWidth();break;default:f.right+=this.legend.getWidth()}e=e.detach()}var g,h=this.axes;for(b=0;12>b;b++)g=G[b],this.target.append(h[g].draw(this.baseCanvas._ctx,this)),h[g].set();h.yaxis.show&&(f.left+=h.yaxis.getWidth());var i,j=["y2axis","y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis"],k=[0,0,0,0,0,0,0,0],l=0;for(i=0;8>i;i++)h[j[i]].show&&(l+=h[j[i]].getWidth(),k[i]=l);if(f.right+=l,h.x2axis.show&&(f.top+=h.x2axis.getHeight()),this.title.show&&(f.top+=this.title.getHeight()),h.xaxis.show&&(f.bottom+=h.xaxis.getHeight()),this.options.gridDimensions&&a.isPlainObject(this.options.gridDimensions)){var m=parseInt(this.options.gridDimensions.width,10)||0,n=parseInt(this.options.gridDimensions.height,10)||0,o=(this._width-f.left-f.right-m)/2,p=(this._height-f.top-f.bottom-n)/2;p>=0&&o>=0&&(f.top+=p,f.bottom+=p,f.left+=o,f.right+=o)}var q=["top","bottom","left","right"];for(var i in q)null==this._gridPadding[q[i]]&&f[q[i]]>0?this._gridPadding[q[i]]=f[q[i]]:null==this._gridPadding[q[i]]&&(this._gridPadding[q[i]]=this._defaultGridPadding[q[i]]);var r=this._gridPadding;for("outsideGrid"===this.legend.placement&&(r={top:this.title.getHeight(),left:0,right:0,bottom:0},"s"===this.legend.location&&(r.left=this._gridPadding.left,r.right=this._gridPadding.right)),h.xaxis.pack({position:"absolute",bottom:this._gridPadding.bottom-h.xaxis.getHeight(),left:0,width:this._width},{min:this._gridPadding.left,max:this._width-this._gridPadding.right}),h.yaxis.pack({position:"absolute",top:0,left:this._gridPadding.left-h.yaxis.getWidth(),height:this._height},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top}),h.x2axis.pack({position:"absolute",top:this._gridPadding.top-h.x2axis.getHeight(),left:0,width:this._width},{min:this._gridPadding.left,max:this._width-this._gridPadding.right}),b=8;b>0;b--)h[j[b-1]].pack({position:"absolute",top:0,right:this._gridPadding.right-k[b-1]},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top});var s=(this._width-this._gridPadding.left-this._gridPadding.right)/2+this._gridPadding.left-h.yMidAxis.getWidth()/2;h.yMidAxis.pack({position:"absolute",top:0,left:s,zIndex:9,textAlign:"center"},{min:this._height-this._gridPadding.bottom,
5
+ max:this._gridPadding.top}),this.target.append(this.grid.createElement(this._gridPadding,this)),this.grid.draw();var t=this.series,u=t.length;for(b=0,d=u;d>b;b++)c=this.seriesStack[b],this.target.append(t[c].shadowCanvas.createElement(this._gridPadding,"jqplot-series-shadowCanvas",null,this)),t[c].shadowCanvas.setContext(),t[c].shadowCanvas._elem.data("seriesIndex",c);for(b=0,d=u;d>b;b++)c=this.seriesStack[b],this.target.append(t[c].canvas.createElement(this._gridPadding,"jqplot-series-canvas",null,this)),t[c].canvas.setContext(),t[c].canvas._elem.data("seriesIndex",c);this.target.append(this.eventCanvas.createElement(this._gridPadding,"jqplot-event-canvas",null,this)),this.eventCanvas.setContext(),this.eventCanvas._ctx.fillStyle="rgba(0,0,0,0)",this.eventCanvas._ctx.fillRect(0,0,this.eventCanvas._ctx.canvas.width,this.eventCanvas._ctx.canvas.height),this.bindCustomEvents(),this.legend.preDraw?(this.eventCanvas._elem.before(e),this.legend.pack(r),this.legend._elem?this.drawSeries({legendInfo:{location:this.legend.location,placement:this.legend.placement,width:this.legend.getWidth(),height:this.legend.getHeight(),xoffset:this.legend.xoffset,yoffset:this.legend.yoffset}}):this.drawSeries()):(this.drawSeries(),u&&a(t[u-1].canvas._elem).after(e),this.legend.pack(r));for(var b=0,d=a.jqplot.eventListenerHooks.length;d>b;b++)this.eventCanvas._elem.bind(a.jqplot.eventListenerHooks[b][0],{plot:this},a.jqplot.eventListenerHooks[b][1]);for(var b=0,d=this.eventListenerHooks.hooks.length;d>b;b++)this.eventCanvas._elem.bind(this.eventListenerHooks.hooks[b][0],{plot:this},this.eventListenerHooks.hooks[b][1]);var v=this.fillBetween;if("number"==typeof v.series1)v.fill&&v.series1!==v.series2&&v.series1<u&&v.series2<u&&"line"===t[v.series1]._type&&"line"===t[v.series2]._type&&this.doFillBetweenLines();else if(null!=v.series1&&null!=v.series2){var w=!1;if(v.series1.length===v.series2.length)for(var x=0,y=0,z=0;z<v.series1.length;z++){if(x=v.series1[z],y=v.series2[z],!(x!==y&&u>x&&u>y&&"line"===t[x]._type&&"line"===t[y]._type)){w=!1;break}w=!0}v.fill&&w&&this.doFillBetweenLines()}for(var b=0,d=a.jqplot.postDrawHooks.length;d>b;b++)a.jqplot.postDrawHooks[b].call(this);for(var b=0,d=this.postDrawHooks.hooks.length;d>b;b++)this.postDrawHooks.hooks[b].apply(this,this.postDrawHooks.args[b]);this.target.is(":visible")&&(this._drawCount+=1);var A,B,C,D;for(b=0,d=u;d>b;b++)A=t[b],B=A.renderer,C=".jqplot-point-label.jqplot-series-"+b,B.animation&&B.animation._supported&&B.animation.show&&(this._drawCount<2||this.animateReplot)&&(D=this.target.find(C),D.stop(!0,!0).hide(),A.canvas._elem.stop(!0,!0).hide(),A.shadowCanvas._elem.stop(!0,!0).hide(),A.canvas._elem.jqplotEffect("blind",{mode:"show",direction:B.animation.direction},B.animation.speed),A.shadowCanvas._elem.jqplotEffect("blind",{mode:"show",direction:B.animation.direction},B.animation.speed),D.fadeIn(.8*B.animation.speed));D=null,this.target.trigger("jqplotPostDraw",[this])}},g.prototype.doFillBetweenLines=function(){function a(a,e){var f=c[a],g=c[e];if(g.renderer.smooth)var h=g.renderer._smoothedData.slice(0).reverse();else var h=g.gridData.slice(0).reverse();if(f.renderer.smooth)var i=f.renderer._smoothedData.concat(h);else var i=f.gridData.concat(h);var j=null!==b.color?b.color:c[d].fillColor,k=null!==b.baseSeries?b.baseSeries:a,l=c[k].renderer.shapeRenderer,m={fillStyle:j,fill:!0,closePath:!0};l.draw(f.shadowCanvas._ctx,i,m)}var b=this.fillBetween,c=this.series,d=b.series1,e=b.series2,f=0,g=0;if("number"==typeof d&&"number"==typeof e)f=e>d?d:e,g=e>d?e:d,a(f,g);else for(var h=0;h<d.length;h++)f=d[h]<e[h]?d[h]:e[h],g=e[h]>d[h]?e[h]:d[h],a(f,g)},this.bindCustomEvents=function(){this.eventCanvas._elem.bind("click",{plot:this},this.onClick),this.eventCanvas._elem.bind("dblclick",{plot:this},this.onDblClick),this.eventCanvas._elem.bind("mousedown",{plot:this},this.onMouseDown),this.eventCanvas._elem.bind("mousemove",{plot:this},this.onMouseMove),this.eventCanvas._elem.bind("mouseenter",{plot:this},this.onMouseEnter),this.eventCanvas._elem.bind("mouseleave",{plot:this},this.onMouseLeave),this.captureRightClick?(this.eventCanvas._elem.bind("mouseup",{plot:this},this.onRightClick),this.eventCanvas._elem.get(0).oncontextmenu=function(){return!1}):this.eventCanvas._elem.bind("mouseup",{plot:this},this.onMouseUp)},this.onClick=function(b){var c=i(b),d=b.data.plot,e=j(c.gridPos,d),f=a.Event("jqplotClick");f.pageX=b.pageX,f.pageY=b.pageY,a(this).trigger(f,[c.gridPos,c.dataPos,e,d])},this.onDblClick=function(b){var c=i(b),d=b.data.plot,e=j(c.gridPos,d),f=a.Event("jqplotDblClick");f.pageX=b.pageX,f.pageY=b.pageY,a(this).trigger(f,[c.gridPos,c.dataPos,e,d])},this.onMouseDown=function(b){var c=i(b),d=b.data.plot,e=j(c.gridPos,d),f=a.Event("jqplotMouseDown");f.pageX=b.pageX,f.pageY=b.pageY,a(this).trigger(f,[c.gridPos,c.dataPos,e,d])},this.onMouseUp=function(b){var c=i(b),d=a.Event("jqplotMouseUp");d.pageX=b.pageX,d.pageY=b.pageY,a(this).trigger(d,[c.gridPos,c.dataPos,null,b.data.plot])},this.onRightClick=function(b){var c=i(b),d=b.data.plot,e=j(c.gridPos,d);if(d.captureRightClick)if(3==b.which){var f=a.Event("jqplotRightClick");f.pageX=b.pageX,f.pageY=b.pageY,a(this).trigger(f,[c.gridPos,c.dataPos,e,d])}else{var f=a.Event("jqplotMouseUp");f.pageX=b.pageX,f.pageY=b.pageY,a(this).trigger(f,[c.gridPos,c.dataPos,e,d])}},this.onMouseMove=function(b){var c=i(b),d=b.data.plot,e=j(c.gridPos,d),f=a.Event("jqplotMouseMove");f.pageX=b.pageX,f.pageY=b.pageY,a(this).trigger(f,[c.gridPos,c.dataPos,e,d])},this.onMouseEnter=function(b){var c=i(b),d=b.data.plot,e=a.Event("jqplotMouseEnter");e.pageX=b.pageX,e.pageY=b.pageY,e.relatedTarget=b.relatedTarget,a(this).trigger(e,[c.gridPos,c.dataPos,null,d])},this.onMouseLeave=function(b){var c=i(b),d=b.data.plot,e=a.Event("jqplotMouseLeave");e.pageX=b.pageX,e.pageY=b.pageY,e.relatedTarget=b.relatedTarget,a(this).trigger(e,[c.gridPos,c.dataPos,null,d])},this.drawSeries=function(b,c){var d,e,f;if(c="number"==typeof b&&null==c?b:c,b="object"==typeof b?b:{},c!=F)e=this.series[c],f=e.shadowCanvas._ctx,f.clearRect(0,0,f.canvas.width,f.canvas.height),e.drawShadow(f,b,this),f=e.canvas._ctx,f.clearRect(0,0,f.canvas.width,f.canvas.height),e.draw(f,b,this),e.renderer.constructor==a.jqplot.BezierCurveRenderer&&c<this.series.length-1&&this.drawSeries(c+1);else for(d=0;d<this.series.length;d++)e=this.series[d],f=e.shadowCanvas._ctx,f.clearRect(0,0,f.canvas.width,f.canvas.height),e.drawShadow(f,b,this),f=e.canvas._ctx,f.clearRect(0,0,f.canvas.width,f.canvas.height),e.draw(f,b,this);b=c=d=e=f=null},this.moveSeriesToFront=function(b){b=parseInt(b,10);var c=a.inArray(b,this.seriesStack);if(-1!=c){if(c==this.seriesStack.length-1)return void(this.previousSeriesStack=this.seriesStack.slice(0));var d=this.seriesStack[this.seriesStack.length-1],e=this.series[b].canvas._elem.detach(),f=this.series[b].shadowCanvas._elem.detach();this.series[d].shadowCanvas._elem.after(f),this.series[d].canvas._elem.after(e),this.previousSeriesStack=this.seriesStack.slice(0),this.seriesStack.splice(c,1),this.seriesStack.push(b)}},this.moveSeriesToBack=function(b){b=parseInt(b,10);var c=a.inArray(b,this.seriesStack);if(0!=c&&-1!=c){var d=this.seriesStack[0],e=this.series[b].canvas._elem.detach(),f=this.series[b].shadowCanvas._elem.detach();this.series[d].shadowCanvas._elem.before(f),this.series[d].canvas._elem.before(e),this.previousSeriesStack=this.seriesStack.slice(0),this.seriesStack.splice(c,1),this.seriesStack.unshift(b)}},this.restorePreviousSeriesOrder=function(){var a,b,c,d,e,f;if(this.seriesStack!=this.previousSeriesStack){for(a=1;a<this.previousSeriesStack.length;a++)e=this.previousSeriesStack[a],f=this.previousSeriesStack[a-1],b=this.series[e].canvas._elem.detach(),c=this.series[e].shadowCanvas._elem.detach(),this.series[f].shadowCanvas._elem.after(c),this.series[f].canvas._elem.after(b);d=this.seriesStack.slice(0),this.seriesStack=this.previousSeriesStack.slice(0),this.previousSeriesStack=d}},this.restoreOriginalSeriesOrder=function(){var a,b,c,d=[];for(a=0;a<this.series.length;a++)d.push(a);if(this.seriesStack!=d)for(this.previousSeriesStack=this.seriesStack.slice(0),this.seriesStack=d,a=1;a<this.seriesStack.length;a++)b=this.series[a].canvas._elem.detach(),c=this.series[a].shadowCanvas._elem.detach(),this.series[a-1].shadowCanvas._elem.after(c),this.series[a-1].canvas._elem.after(b)},this.activateTheme=function(a){this.themeEngine.activate(this,a)}}function h(a,b){return(3.4182054+b)*Math.pow(a,-.3534992)}function i(a){var b=(Math.exp(2*a)-1)/(Math.exp(2*a)+1);return b}function j(a){function b(a,b){return a-b==0?Math.pow(10,10):a-b}var c=this.renderer.smooth,d=this.canvas.getWidth(),e=this._xaxis.series_p2u,f=this._yaxis.series_p2u,g=null,i=a.length/d,j=[],k=[];g=isNaN(parseFloat(c))?h(i,.5):parseFloat(c);for(var l=[],m=[],n=0,o=a.length;o>n;n++)l.push(a[n][1]),m.push(a[n][0]);for(var p,q,r,s,t=a.length-1,u=1,v=a.length;v>u;u++){for(var w=[],x=[],y=0;2>y;y++){var n=u-1+y;0==n||n==t?w[y]=Math.pow(10,10):l[n+1]-l[n]==0||l[n]-l[n-1]==0?w[y]=0:(m[n+1]-m[n])/(l[n+1]-l[n])+(m[n]-m[n-1])/(l[n]-l[n-1])==0?w[y]=0:(l[n+1]-l[n])*(l[n]-l[n-1])<0?w[y]=0:w[y]=2/(b(m[n+1],m[n])/(l[n+1]-l[n])+b(m[n],m[n-1])/(l[n]-l[n-1]))}1==u?w[0]=1.5*(l[1]-l[0])/b(m[1],m[0])-w[1]/2:u==t&&(w[1]=1.5*(l[t]-l[t-1])/b(m[t],m[t-1])-w[0]/2),x[0]=-2*(w[1]+2*w[0])/b(m[u],m[u-1])+6*(l[u]-l[u-1])/Math.pow(b(m[u],m[u-1]),2),x[1]=2*(2*w[1]+w[0])/b(m[u],m[u-1])-6*(l[u]-l[u-1])/Math.pow(b(m[u],m[u-1]),2),s=1/6*(x[1]-x[0])/b(m[u],m[u-1]),r=.5*(m[u]*x[0]-m[u-1]*x[1])/b(m[u],m[u-1]),q=(l[u]-l[u-1]-r*(Math.pow(m[u],2)-Math.pow(m[u-1],2))-s*(Math.pow(m[u],3)-Math.pow(m[u-1],3)))/b(m[u],m[u-1]),p=l[u-1]-q*m[u-1]-r*Math.pow(m[u-1],2)-s*Math.pow(m[u-1],3);for(var z,A,B=(m[u]-m[u-1])/g,y=0,o=g;o>y;y++)z=[],A=m[u-1]+y*B,z.push(A),z.push(p+q*A+r*Math.pow(A,2)+s*Math.pow(A,3)),j.push(z),k.push([e(z[0]),f(z[1])])}return j.push(a[n]),k.push([e(a[n][0]),f(a[n][1])]),[j,k]}function k(a){var b,c,d,e,f,g,j,k,l,m,n,o,p,q,r,s,t,u,v=this.renderer.smooth,w=this.renderer.tension,x=this.canvas.getWidth(),y=this._xaxis.series_p2u,z=this._yaxis.series_p2u,A=null,B=null,C=null,D=null,E=null,F=null,G=null,H=a.length/x,I=[],J=[];A=isNaN(parseFloat(v))?h(H,.5):parseFloat(v),isNaN(parseFloat(w))||(w=parseFloat(w));for(var K=0,L=a.length-1;L>K;K++)for(null===w?(E=Math.abs((a[K+1][1]-a[K][1])/(a[K+1][0]-a[K][0])),q=.3,r=.6,s=(r-q)/2,t=2.5,u=-1.4,G=E/t+u,C=s*i(G)-s*i(u)+q,K>0&&(F=Math.abs((a[K][1]-a[K-1][1])/(a[K][0]-a[K-1][0]))),G=F/t+u,D=s*i(G)-s*i(u)+q,B=(C+D)/2):B=w,b=0;A>b;b++)c=b/A,d=(1+2*c)*Math.pow(1-c,2),e=c*Math.pow(1-c,2),f=Math.pow(c,2)*(3-2*c),g=Math.pow(c,2)*(c-1),a[K-1]?(j=B*(a[K+1][0]-a[K-1][0]),k=B*(a[K+1][1]-a[K-1][1])):(j=B*(a[K+1][0]-a[K][0]),k=B*(a[K+1][1]-a[K][1])),a[K+2]?(l=B*(a[K+2][0]-a[K][0]),m=B*(a[K+2][1]-a[K][1])):(l=B*(a[K+1][0]-a[K][0]),m=B*(a[K+1][1]-a[K][1])),n=d*a[K][0]+f*a[K+1][0]+e*j+g*l,o=d*a[K][1]+f*a[K+1][1]+e*k+g*m,p=[n,o],I.push(p),J.push([y(n),z(o)]);return I.push(a[L]),J.push([y(a[L][0]),z(a[L][1])]),[I,J]}function l(b,c,d){for(var e=0;e<this.series.length;e++)this.series[e].renderer.constructor==a.jqplot.LineRenderer&&this.series[e].highlightMouseOver&&(this.series[e].highlightMouseDown=!1)}function m(){this.plugins.lineRenderer&&this.plugins.lineRenderer.highlightCanvas&&(this.plugins.lineRenderer.highlightCanvas.resetCanvas(),this.plugins.lineRenderer.highlightCanvas=null),this.plugins.lineRenderer.highlightedSeriesIndex=null,this.plugins.lineRenderer.highlightCanvas=new a.jqplot.GenericCanvas,this.eventCanvas._elem.before(this.plugins.lineRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-lineRenderer-highlight-canvas",this._plotDimensions,this)),this.plugins.lineRenderer.highlightCanvas.setContext(),this.eventCanvas._elem.bind("mouseleave",{plot:this},function(a){o(a.data.plot)})}function n(a,b,c,d){var e=a.series[b],f=a.plugins.lineRenderer.highlightCanvas;f._ctx.clearRect(0,0,f._ctx.canvas.width,f._ctx.canvas.height),e._highlightedPoint=c,a.plugins.lineRenderer.highlightedSeriesIndex=b;var g={fillStyle:e.highlightColor};"line"===e.type&&e.renderer.bands.show&&(g.fill=!0,g.closePath=!0),e.renderer.shapeRenderer.draw(f._ctx,d,g),f=null}function o(a){var b=a.plugins.lineRenderer.highlightCanvas;b._ctx.clearRect(0,0,b._ctx.canvas.width,b._ctx.canvas.height);for(var c=0;c<a.series.length;c++)a.series[c]._highlightedPoint=null;a.plugins.lineRenderer.highlightedSeriesIndex=null,a.target.trigger("jqplotDataUnhighlight"),b=null}function p(a,b,c,d,e){if(d){var f=[d.seriesIndex,d.pointIndex,d.data],g=jQuery.Event("jqplotDataMouseOver");if(g.pageX=a.pageX,g.pageY=a.pageY,e.target.trigger(g,f),e.series[f[0]].highlightMouseOver&&f[0]!=e.plugins.lineRenderer.highlightedSeriesIndex){var h=jQuery.Event("jqplotDataHighlight");h.which=a.which,h.pageX=a.pageX,h.pageY=a.pageY,e.target.trigger(h,f),n(e,d.seriesIndex,d.pointIndex,d.points)}}else null==d&&o(e)}function q(a,b,c,d,e){if(d){var f=[d.seriesIndex,d.pointIndex,d.data];if(e.series[f[0]].highlightMouseDown&&f[0]!=e.plugins.lineRenderer.highlightedSeriesIndex){var g=jQuery.Event("jqplotDataHighlight");g.which=a.which,g.pageX=a.pageX,g.pageY=a.pageY,e.target.trigger(g,f),n(e,d.seriesIndex,d.pointIndex,d.points)}}else null==d&&o(e)}function r(a,b,c,d,e){var f=e.plugins.lineRenderer.highlightedSeriesIndex;null!=f&&e.series[f].highlightMouseDown&&o(e)}function s(a,b,c,d,e){if(d){var f=[d.seriesIndex,d.pointIndex,d.data],g=jQuery.Event("jqplotDataClick");g.which=a.which,g.pageX=a.pageX,g.pageY=a.pageY,e.target.trigger(g,f)}}function t(a,b,c,d,e){if(d){var f=[d.seriesIndex,d.pointIndex,d.data],g=e.plugins.lineRenderer.highlightedSeriesIndex;null!=g&&e.series[g].highlightMouseDown&&o(e);var h=jQuery.Event("jqplotDataRightClick");h.which=a.which,h.pageX=a.pageX,h.pageY=a.pageY,e.target.trigger(h,f)}}function u(a){var b;if(a=Math.abs(a),a>=10)b="%d";else if(a>1)b=a===parseInt(a,10)?"%d":"%.1f";else{var c=-Math.floor(Math.log(a)/Math.LN10);b="%."+c+"f"}return b}function v(b,c,d){for(var e,f,g,h,i,j,k,l=Math.floor(d/2),m=Math.ceil(1.5*d),n=Number.MAX_VALUE,o=c-b,p=a.jqplot.getSignificantFigures,q=0,r=m-l+1;r>q;q++)j=l+q,e=o/(j-1),f=p(e),e=Math.abs(d-j)+f.digitsRight,n>e?(n=e,g=j,k=f.digitsRight):e===n&&f.digitsRight<k&&(g=j,k=f.digitsRight);return h=Math.max(k,Math.max(p(b).digitsRight,p(c).digitsRight)),i=0===h?"%d":"%."+h+"f",e=o/(g-1),[b,c,g,i,e]}function w(a,b){b=b||7;var c,d=a/(b-1),e=Math.pow(10,Math.floor(Math.log(d)/Math.LN10)),f=d/e;return c=1>e?f>5?10*e:f>2?5*e:f>1?2*e:e:f>5?10*e:f>4?5*e:f>3?4*e:f>2?3*e:f>1?2*e:e}function x(a,b){b=b||1;var c,d=Math.floor(Math.log(a)/Math.LN10),e=Math.pow(10,d),f=a/e;return f/=b,c=.38>=f?.1:1.6>=f?.2:4>=f?.5:8>=f?1:16>=f?2:5,c*e}function y(a,b){var c,d,e=Math.floor(Math.log(a)/Math.LN10),f=Math.pow(10,e),g=a/f;return g/=b,d=.38>=g?.1:1.6>=g?.2:4>=g?.5:8>=g?1:16>=g?2:5,c=d*f,[c,d,f]}function z(a,b){return a-b}function A(a){if(null==a||"object"!=typeof a)return a;var b=new a.constructor;for(var c in a)b[c]=A(a[c]);return b}function B(a,b){if(null!=b&&"object"==typeof b)for(var c in b)"highlightColors"==c&&(a[c]=A(b[c])),null!=b[c]&&"object"==typeof b[c]?(a.hasOwnProperty(c)||(a[c]={}),B(a[c],b[c])):a[c]=b[c]}function C(a,b){if(b.indexOf)return b.indexOf(a);for(var c=0,d=b.length;d>c;c++)if(b[c]===a)return c;return-1}function D(a){return null===a?"[object Null]":Object.prototype.toString.call(a)}function E(b,c,d,e){return a.isPlainObject(b)?b:(b={effect:b},c===F&&(c={}),a.isFunction(c)&&(e=c,d=null,c={}),("number"===a.type(c)||a.fx.speeds[c])&&(e=d,d=c,c={}),a.isFunction(d)&&(e=d,d=null),c&&a.extend(b,c),d=d||c.duration,b.duration=a.fx.off?0:"number"==typeof d?d:d in a.fx.speeds?a.fx.speeds[d]:a.fx.speeds._default,b.complete=e||c.complete,b)}var F;a.fn.emptyForce=function(){for(var b,c=0;null!=(b=a(this)[c]);c++){if(1===b.nodeType&&a.cleanData(b.getElementsByTagName("*")),a.jqplot.use_excanvas)b.outerHTML="";else for(;b.firstChild;)b.removeChild(b.firstChild);b=null}return a(this)},a.fn.removeChildForce=function(a){for(;a.firstChild;)this.removeChildForce(a.firstChild),a.removeChild(a.firstChild)},a.fn.jqplot=function(){for(var b=[],c=[],d=0,e=arguments.length;e>d;d++)a.isArray(arguments[d])?b.push(arguments[d]):a.isPlainObject(arguments[d])&&c.push(arguments[d]);return this.each(function(d){var e,f,g,h,i=a(this),j=b.length,k=c.length;g=j>d?b[d]:j?b[j-1]:null,h=k>d?c[d]:k?c[k-1]:null,e=i.attr("id"),e===F&&(e="jqplot_target_"+a.jqplot.targetCounter++,i.attr("id",e)),f=a.jqplot(e,g,h),i.data("jqplot",f)})},a.jqplot=function(b,c,d){var e=null,f=null;3===arguments.length?(e=c,f=d):2===arguments.length&&(a.isArray(c)?e=c:a.isPlainObject(c)&&(f=c)),null===e&&null!==f&&f.data&&(e=f.data);var h=new g;if(a("#"+b).removeClass("jqplot-error"),!a.jqplot.config.catchErrors)return h.init(b,e,f),h.draw(),h.themeEngine.init.call(h),h;try{return h.init(b,e,f),h.draw(),h.themeEngine.init.call(h),h}catch(i){var j=a.jqplot.config.errorMessage||i.message;a("#"+b).append('<div class="jqplot-error-message">'+j+"</div>"),a("#"+b).addClass("jqplot-error"),document.getElementById(b).style.background=a.jqplot.config.errorBackground,document.getElementById(b).style.border=a.jqplot.config.errorBorder,document.getElementById(b).style.fontFamily=a.jqplot.config.errorFontFamily,document.getElementById(b).style.fontSize=a.jqplot.config.errorFontSize,document.getElementById(b).style.fontStyle=a.jqplot.config.errorFontStyle,document.getElementById(b).style.fontWeight=a.jqplot.config.errorFontWeight}},a.jqplot.version="1.0.9",a.jqplot.revision="d96a669",a.jqplot.targetCounter=1,a.jqplot.CanvasManager=function(){"undefined"==typeof a.jqplot.CanvasManager.canvases&&(a.jqplot.CanvasManager.canvases=[],a.jqplot.CanvasManager.free=[]);var b=[];this.getCanvas=function(){var c,d=!0;if(!a.jqplot.use_excanvas)for(var e=0,f=a.jqplot.CanvasManager.canvases.length;f>e;e++)if(a.jqplot.CanvasManager.free[e]===!0){d=!1,c=a.jqplot.CanvasManager.canvases[e],a.jqplot.CanvasManager.free[e]=!1,b.push(e);break}return d&&(c=document.createElement("canvas"),b.push(a.jqplot.CanvasManager.canvases.length),a.jqplot.CanvasManager.canvases.push(c),a.jqplot.CanvasManager.free.push(!1)),c},this.initCanvas=function(b){if(a.jqplot.use_excanvas)return window.G_vmlCanvasManager.initElement(b);var c=b.getContext("2d"),d=1;window.devicePixelRatio>1&&(c.webkitBackingStorePixelRatio===F||c.webkitBackingStorePixelRatio<2)&&(d=window.devicePixelRatio);var e=b.width,f=b.height;return b.width=d*b.width,b.height=d*b.height,b.style.width=e+"px",b.style.height=f+"px",c.save(),c.scale(d,d),b},this.freeAllCanvases=function(){for(var a=0,c=b.length;c>a;a++)this.freeCanvas(b[a]);b=[]},this.freeCanvas=function(b){if(a.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==F)window.G_vmlCanvasManager.uninitElement(a.jqplot.CanvasManager.canvases[b]),a.jqplot.CanvasManager.canvases[b]=null;else{var c=a.jqplot.CanvasManager.canvases[b];c.getContext("2d").clearRect(0,0,c.width,c.height),a(c).unbind().removeAttr("class").removeAttr("style"),a(c).css({left:"",top:"",position:""}),c.width=0,c.height=0,a.jqplot.CanvasManager.free[b]=!0}}},a.jqplot.log=function(){window.console&&window.console.log.apply(window.console,arguments)},a.jqplot.config={addDomReference:!1,enablePlugins:!1,defaultHeight:300,defaultWidth:400,UTCAdjust:!1,timezoneOffset:new Date(6e4*(new Date).getTimezoneOffset()),errorMessage:"",errorBackground:"",errorBorder:"",errorFontFamily:"",errorFontSize:"",errorFontStyle:"",errorFontWeight:"",catchErrors:!1,defaultTickFormatString:"%.1f",defaultColors:["#4bb2c5","#EAA228","#c5b47f","#579575","#839557","#958c12","#953579","#4b5de4","#d8b83f","#ff5800","#0085cc","#c747a3","#cddf54","#FBD178","#26B4E3","#bd70c7"],defaultNegativeColors:["#498991","#C08840","#9F9274","#546D61","#646C4A","#6F6621","#6E3F5F","#4F64B0","#A89050","#C45923","#187399","#945381","#959E5C","#C7AF7B","#478396","#907294"],dashLength:4,gapLength:4,dotGapLength:2.5,srcLocation:"jqplot/src/",pluginLocation:"jqplot/src/plugins/"},a.jqplot.arrayMax=function(a){return Math.max.apply(Math,a)},a.jqplot.arrayMin=function(a){return Math.min.apply(Math,a)},a.jqplot.enablePlugins=a.jqplot.config.enablePlugins,a.jqplot.support_canvas=function(){return"undefined"==typeof a.jqplot.support_canvas.result&&(a.jqplot.support_canvas.result=!!document.createElement("canvas").getContext),a.jqplot.support_canvas.result},a.jqplot.support_canvas_text=function(){return"undefined"==typeof a.jqplot.support_canvas_text.result&&(window.G_vmlCanvasManager!==F&&window.G_vmlCanvasManager._version>887?a.jqplot.support_canvas_text.result=!0:a.jqplot.support_canvas_text.result=!(!document.createElement("canvas").getContext||"function"!=typeof document.createElement("canvas").getContext("2d").fillText)),a.jqplot.support_canvas_text.result},a.jqplot.use_excanvas=a.support.boxModel&&a.support.objectAll&&$support.leadingWhitespace||a.jqplot.support_canvas()?!1:!0,a.jqplot.preInitHooks=[],a.jqplot.postInitHooks=[],a.jqplot.preParseOptionsHooks=[],a.jqplot.postParseOptionsHooks=[],a.jqplot.preDrawHooks=[],a.jqplot.postDrawHooks=[],a.jqplot.preDrawSeriesHooks=[],a.jqplot.postDrawSeriesHooks=[],a.jqplot.preDrawLegendHooks=[],a.jqplot.addLegendRowHooks=[],a.jqplot.preSeriesInitHooks=[],a.jqplot.postSeriesInitHooks=[],a.jqplot.preParseSeriesOptionsHooks=[],a.jqplot.postParseSeriesOptionsHooks=[],a.jqplot.eventListenerHooks=[],a.jqplot.preDrawSeriesShadowHooks=[],a.jqplot.postDrawSeriesShadowHooks=[],a.jqplot.ElemContainer=function(){this._elem,this._plotWidth,this._plotHeight,this._plotDimensions={height:null,width:null}},a.jqplot.ElemContainer.prototype.createElement=function(b,c,d,e,f){this._offsets=c;var g=d||"jqplot",h=document.createElement(b);return this._elem=a(h),this._elem.addClass(g),this._elem.css(e),this._elem.attr(f),h=null,this._elem},a.jqplot.ElemContainer.prototype.getWidth=function(){return this._elem?this._elem.outerWidth(!0):null},a.jqplot.ElemContainer.prototype.getHeight=function(){return this._elem?this._elem.outerHeight(!0):null},a.jqplot.ElemContainer.prototype.getPosition=function(){return this._elem?this._elem.position():{top:null,left:null,bottom:null,right:null}},a.jqplot.ElemContainer.prototype.getTop=function(){return this.getPosition().top},a.jqplot.ElemContainer.prototype.getLeft=function(){return this.getPosition().left},a.jqplot.ElemContainer.prototype.getBottom=function(){return this._elem.css("bottom")},a.jqplot.ElemContainer.prototype.getRight=function(){return this._elem.css("right")},b.prototype=new a.jqplot.ElemContainer,b.prototype.constructor=b,b.prototype.init=function(){a.isFunction(this.renderer)&&(this.renderer=new this.renderer),this.tickOptions.axis=this.name,null==this.tickOptions.showMark&&(this.tickOptions.showMark=this.showTicks),null==this.tickOptions.showMark&&(this.tickOptions.showMark=this.showTickMarks),null==this.tickOptions.showLabel&&(this.tickOptions.showLabel=this.showTicks),null==this.label||""==this.label?this.showLabel=!1:this.labelOptions.label=this.label,0==this.showLabel&&(this.labelOptions.show=!1),0==this.pad&&(this.pad=1),0==this.padMax&&(this.padMax=1),0==this.padMin&&(this.padMin=1),null==this.padMax&&(this.padMax=(this.pad-1)/2+1),null==this.padMin&&(this.padMin=(this.pad-1)/2+1),this.pad=this.padMax+this.padMin-1,(null!=this.min||null!=this.max)&&(this.autoscale=!1),null==this.syncTicks&&this.name.indexOf("y")>-1?this.syncTicks=!0:null==this.syncTicks&&(this.syncTicks=!1),this.renderer.init.call(this,this.rendererOptions)},b.prototype.draw=function(a,b){return this.__ticks&&(this.__ticks=null),this.renderer.draw.call(this,a,b)},b.prototype.set=function(){this.renderer.set.call(this)},b.prototype.pack=function(a,b){this.show&&this.renderer.pack.call(this,a,b),null==this._min&&(this._min=this.min,this._max=this.max,this._tickInterval=this.tickInterval,this._numberTicks=this.numberTicks,this.__ticks=this._ticks)},b.prototype.reset=function(){this.renderer.reset.call(this)},b.prototype.resetScale=function(b){a.extend(!0,this,{min:null,max:null,numberTicks:null,tickInterval:null,_ticks:[],ticks:[]},b),this.resetDataBounds()},b.prototype.resetDataBounds=function(){var b=this._dataBounds;b.min=null,b.max=null;for(var c,d,e,f=this.show?!0:!1,g=0;g<this._series.length;g++)if(d=this._series[g],d.show||this.scaleToHiddenSeries){e=d._plotData,"line"===d._type&&d.renderer.bands.show&&"x"!==this.name.charAt(0)&&(e=[[0,d.renderer.bands._min],[1,d.renderer.bands._max]]);var h=1,i=1;null!=d._type&&"ohlc"==d._type&&(h=3,i=2);for(var j=0,c=e.length;c>j;j++)"xaxis"==this.name||"x2axis"==this.name?((null!=e[j][0]&&e[j][0]<b.min||null==b.min)&&(b.min=e[j][0]),(null!=e[j][0]&&e[j][0]>b.max||null==b.max)&&(b.max=e[j][0])):((null!=e[j][h]&&e[j][h]<b.min||null==b.min)&&(b.min=e[j][h]),(null!=e[j][i]&&e[j][i]>b.max||null==b.max)&&(b.max=e[j][i]));f&&d.renderer.constructor!==a.jqplot.BarRenderer?f=!1:f&&this._options.hasOwnProperty("forceTickAt0")&&0==this._options.forceTickAt0?f=!1:f&&d.renderer.constructor===a.jqplot.BarRenderer&&("vertical"==d.barDirection&&"xaxis"!=this.name&&"x2axis"!=this.name?(null!=this._options.pad||null!=this._options.padMin)&&(f=!1):"horizontal"!=d.barDirection||"xaxis"!=this.name&&"x2axis"!=this.name||(null!=this._options.pad||null!=this._options.padMin)&&(f=!1))}f&&this.renderer.constructor===a.jqplot.LinearAxisRenderer&&b.min>=0&&(this.padMin=1,this.forceTickAt0=!0)},c.prototype=new a.jqplot.ElemContainer,c.prototype.constructor=c,c.prototype.setOptions=function(b){if(a.extend(!0,this,b),"inside"==this.placement&&(this.placement="insideGrid"),this.xoffset>0){if("insideGrid"==this.placement)switch(this.location){case"nw":case"w":case"sw":null==this.marginLeft&&(this.marginLeft=this.xoffset+"px"),this.marginRight="0px";break;case"ne":case"e":case"se":default:null==this.marginRight&&(this.marginRight=this.xoffset+"px"),this.marginLeft="0px"}else if("outside"==this.placement)switch(this.location){case"nw":case"w":case"sw":null==this.marginRight&&(this.marginRight=this.xoffset+"px"),this.marginLeft="0px";break;case"ne":case"e":case"se":default:null==this.marginLeft&&(this.marginLeft=this.xoffset+"px"),this.marginRight="0px"}this.xoffset=0}if(this.yoffset>0){if("outside"==this.placement)switch(this.location){case"sw":case"s":case"se":null==this.marginTop&&(this.marginTop=this.yoffset+"px"),this.marginBottom="0px";break;case"ne":case"n":case"nw":default:null==this.marginBottom&&(this.marginBottom=this.yoffset+"px"),this.marginTop="0px"}else if("insideGrid"==this.placement)switch(this.location){case"sw":case"s":case"se":null==this.marginBottom&&(this.marginBottom=this.yoffset+"px"),this.marginTop="0px";break;case"ne":case"n":case"nw":default:null==this.marginTop&&(this.marginTop=this.yoffset+"px"),this.marginBottom="0px"}this.yoffset=0}},c.prototype.init=function(){a.isFunction(this.renderer)&&(this.renderer=new this.renderer),this.renderer.init.call(this,this.rendererOptions)},c.prototype.draw=function(b,c){for(var d=0;d<a.jqplot.preDrawLegendHooks.length;d++)a.jqplot.preDrawLegendHooks[d].call(this,b);return this.renderer.draw.call(this,b,c)},c.prototype.pack=function(a){this.renderer.pack.call(this,a)},d.prototype=new a.jqplot.ElemContainer,d.prototype.constructor=d,d.prototype.init=function(){a.isFunction(this.renderer)&&(this.renderer=new this.renderer),this.renderer.init.call(this,this.rendererOptions)},d.prototype.draw=function(a){return this.renderer.draw.call(this,a)},d.prototype.pack=function(){this.renderer.pack.call(this)},e.prototype=new a.jqplot.ElemContainer,e.prototype.constructor=e,e.prototype.init=function(b,c,d){this.index=b,this.gridBorderWidth=c;var e,f,g=this.data,h=[];for(e=0,f=g.length;f>e;e++)if(this.breakOnNull)h.push(g[e]);else{if(null==g[e]||null==g[e][0]||null==g[e][1])continue;h.push(g[e])}if(this.data=h,this.color||(this.color=d.colorGenerator.get(this.index)),this.negativeColor||(this.negativeColor=d.negativeColorGenerator.get(this.index)),this.fillColor||(this.fillColor=this.color),this.fillAlpha){var i=a.jqplot.normalize2rgb(this.fillColor),i=a.jqplot.getColorComponents(i);this.fillColor="rgba("+i[0]+","+i[1]+","+i[2]+","+this.fillAlpha+")"}a.isFunction(this.renderer)&&(this.renderer=new this.renderer),this.renderer.init.call(this,this.rendererOptions,d),this.markerRenderer=new this.markerRenderer,this.markerOptions.color||(this.markerOptions.color=this.color),null==this.markerOptions.show&&(this.markerOptions.show=this.showMarker),this.showMarker=this.markerOptions.show,this.markerRenderer.init(this.markerOptions)},e.prototype.draw=function(b,c,d){var e=c==F?{}:c;b=b==F?this.canvas._ctx:b;var f,g,h;for(f=0;f<a.jqplot.preDrawSeriesHooks.length;f++)a.jqplot.preDrawSeriesHooks[f].call(this,b,e);for(this.show&&(this.renderer.setGridData.call(this,d),e.preventJqPlotSeriesDrawTrigger||a(b.canvas).trigger("jqplotSeriesDraw",[this.data,this.gridData]),g=[],g=e.data?e.data:this._stack?this._plotData:this.data,h=e.gridData||this.renderer.makeGridData.call(this,g,d),"line"===this._type&&this.renderer.smooth&&this.renderer._smoothedData.length&&(h=this.renderer._smoothedData),this.renderer.draw.call(this,b,h,e,d)),f=0;f<a.jqplot.postDrawSeriesHooks.length;f++)a.jqplot.postDrawSeriesHooks[f].call(this,b,e,d);b=c=d=f=g=h=null},e.prototype.drawShadow=function(b,c,d){var e=c==F?{}:c;b=b==F?this.shadowCanvas._ctx:b;var f,g,h;for(f=0;f<a.jqplot.preDrawSeriesShadowHooks.length;f++)a.jqplot.preDrawSeriesShadowHooks[f].call(this,b,e);for(this.shadow&&(this.renderer.setGridData.call(this,d),g=[],g=e.data?e.data:this._stack?this._plotData:this.data,h=e.gridData||this.renderer.makeGridData.call(this,g,d),this.renderer.drawShadow.call(this,b,h,e,d)),f=0;f<a.jqplot.postDrawSeriesShadowHooks.length;f++)a.jqplot.postDrawSeriesShadowHooks[f].call(this,b,e);b=c=d=f=g=h=null},e.prototype.toggleDisplay=function(a,b){var c,d;c=a.data.series?a.data.series:this,a.data.speed&&(d=a.data.speed),d?c.canvas._elem.is(":hidden")||!c.show?(c.show=!0,c.canvas._elem.removeClass("jqplot-series-hidden"),c.shadowCanvas._elem&&c.shadowCanvas._elem.fadeIn(d),c.canvas._elem.fadeIn(d,b),c.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+c.index).fadeIn(d)):(c.show=!1,c.canvas._elem.addClass("jqplot-series-hidden"),c.shadowCanvas._elem&&c.shadowCanvas._elem.fadeOut(d),c.canvas._elem.fadeOut(d,b),c.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+c.index).fadeOut(d)):c.canvas._elem.is(":hidden")||!c.show?(c.show=!0,c.canvas._elem.removeClass("jqplot-series-hidden"),c.shadowCanvas._elem&&c.shadowCanvas._elem.show(),c.canvas._elem.show(0,b),c.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+c.index).show()):(c.show=!1,c.canvas._elem.addClass("jqplot-series-hidden"),c.shadowCanvas._elem&&c.shadowCanvas._elem.hide(),c.canvas._elem.hide(0,b),c.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+c.index).hide())},f.prototype=new a.jqplot.ElemContainer,f.prototype.constructor=f,f.prototype.init=function(){a.isFunction(this.renderer)&&(this.renderer=new this.renderer),this.renderer.init.call(this,this.rendererOptions)},f.prototype.createElement=function(a,b){return this._offsets=a,this.renderer.createElement.call(this,b)},f.prototype.draw=function(){this.renderer.draw.call(this)},a.jqplot.GenericCanvas=function(){a.jqplot.ElemContainer.call(this),this._ctx},a.jqplot.GenericCanvas.prototype=new a.jqplot.ElemContainer,a.jqplot.GenericCanvas.prototype.constructor=a.jqplot.GenericCanvas,a.jqplot.GenericCanvas.prototype.createElement=function(b,c,d,e){this._offsets=b;var f="jqplot";c!=F&&(f=c);var g;return g=e.canvasManager.getCanvas(),null!=d&&(this._plotDimensions=d),g.width=this._plotDimensions.width-this._offsets.left-this._offsets.right,g.height=this._plotDimensions.height-this._offsets.top-this._offsets.bottom,this._elem=a(g),this._elem.css({position:"absolute",left:this._offsets.left,top:this._offsets.top}),this._elem.addClass(f),g=e.canvasManager.initCanvas(g),g=null,this._elem},a.jqplot.GenericCanvas.prototype.setContext=function(){return this._ctx=this._elem.get(0).getContext("2d"),this._ctx;
6
+ },a.jqplot.GenericCanvas.prototype.resetCanvas=function(){this._elem&&(a.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==F&&window.G_vmlCanvasManager.uninitElement(this._elem.get(0)),this._elem.emptyForce()),this._ctx=null},a.jqplot.HooksManager=function(){this.hooks=[],this.args=[]},a.jqplot.HooksManager.prototype.addOnce=function(a,b){b=b||[];for(var c=!1,d=0,e=this.hooks.length;e>d;d++)this.hooks[d]==a&&(c=!0);c||(this.hooks.push(a),this.args.push(b))},a.jqplot.HooksManager.prototype.add=function(a,b){b=b||[],this.hooks.push(a),this.args.push(b)},a.jqplot.EventListenerManager=function(){this.hooks=[]},a.jqplot.EventListenerManager.prototype.addOnce=function(a,b){for(var c,d,e=!1,d=0,f=this.hooks.length;f>d;d++)c=this.hooks[d],c[0]==a&&c[1]==b&&(e=!0);e||this.hooks.push([a,b])},a.jqplot.EventListenerManager.prototype.add=function(a,b){this.hooks.push([a,b])};var G=["yMidAxis","xaxis","yaxis","x2axis","y2axis","y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis"];a.jqplot.computeHighlightColors=function(b){var c;if(a.isArray(b)){c=[];for(var d=0;d<b.length;d++){for(var e=a.jqplot.getColorComponents(b[d]),f=[e[0],e[1],e[2]],g=f[0]+f[1]+f[2],h=0;3>h;h++)f[h]=g>660?.85*f[h]:.73*f[h]+90,f[h]=parseInt(f[h],10),f[h]>255?255:f[h];f[3]=.3+.35*e[3],c.push("rgba("+f[0]+","+f[1]+","+f[2]+","+f[3]+")")}}else{for(var e=a.jqplot.getColorComponents(b),f=[e[0],e[1],e[2]],g=f[0]+f[1]+f[2],h=0;3>h;h++)f[h]=g>660?.85*f[h]:.73*f[h]+90,f[h]=parseInt(f[h],10),f[h]>255?255:f[h];f[3]=.3+.35*e[3],c="rgba("+f[0]+","+f[1]+","+f[2]+","+f[3]+")"}return c},a.jqplot.ColorGenerator=function(b){b=b||a.jqplot.config.defaultColors;var c=0;this.next=function(){return c<b.length?b[c++]:(c=0,b[c++])},this.previous=function(){return c>0?b[c--]:(c=b.length-1,b[c])},this.get=function(a){var c=a-b.length*Math.floor(a/b.length);return b[c]},this.setColors=function(a){b=a},this.reset=function(){c=0},this.getIndex=function(){return c},this.setIndex=function(a){c=a}},a.jqplot.hex2rgb=function(a,b){a=a.replace("#",""),3==a.length&&(a=a.charAt(0)+a.charAt(0)+a.charAt(1)+a.charAt(1)+a.charAt(2)+a.charAt(2));var c;return c="rgba("+parseInt(a.slice(0,2),16)+", "+parseInt(a.slice(2,4),16)+", "+parseInt(a.slice(4,6),16),b&&(c+=", "+b),c+=")"},a.jqplot.rgb2hex=function(a){for(var b=/rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *(?:, *[0-9.]*)?\)/,c=a.match(b),d="#",e=1;4>e;e++){var f;-1!=c[e].search(/%/)?(f=parseInt(255*c[e]/100,10).toString(16),1==f.length&&(f="0"+f)):(f=parseInt(c[e],10).toString(16),1==f.length&&(f="0"+f)),d+=f}return d},a.jqplot.normalize2rgb=function(b,c){if(-1!=b.search(/^ *rgba?\(/))return b;if(-1!=b.search(/^ *#?[0-9a-fA-F]?[0-9a-fA-F]/))return a.jqplot.hex2rgb(b,c);throw new Error("Invalid color spec")},a.jqplot.getColorComponents=function(b){b=a.jqplot.colorKeywordMap[b]||b;for(var c=a.jqplot.normalize2rgb(b),d=/rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *,? *([0-9.]* *)?\)/,e=c.match(d),f=[],g=1;4>g;g++)-1!=e[g].search(/%/)?f[g-1]=parseInt(255*e[g]/100,10):f[g-1]=parseInt(e[g],10);return f[3]=parseFloat(e[4])?parseFloat(e[4]):1,f},a.jqplot.colorKeywordMap={aliceblue:"rgb(240, 248, 255)",antiquewhite:"rgb(250, 235, 215)",aqua:"rgb( 0, 255, 255)",aquamarine:"rgb(127, 255, 212)",azure:"rgb(240, 255, 255)",beige:"rgb(245, 245, 220)",bisque:"rgb(255, 228, 196)",black:"rgb( 0, 0, 0)",blanchedalmond:"rgb(255, 235, 205)",blue:"rgb( 0, 0, 255)",blueviolet:"rgb(138, 43, 226)",brown:"rgb(165, 42, 42)",burlywood:"rgb(222, 184, 135)",cadetblue:"rgb( 95, 158, 160)",chartreuse:"rgb(127, 255, 0)",chocolate:"rgb(210, 105, 30)",coral:"rgb(255, 127, 80)",cornflowerblue:"rgb(100, 149, 237)",cornsilk:"rgb(255, 248, 220)",crimson:"rgb(220, 20, 60)",cyan:"rgb( 0, 255, 255)",darkblue:"rgb( 0, 0, 139)",darkcyan:"rgb( 0, 139, 139)",darkgoldenrod:"rgb(184, 134, 11)",darkgray:"rgb(169, 169, 169)",darkgreen:"rgb( 0, 100, 0)",darkgrey:"rgb(169, 169, 169)",darkkhaki:"rgb(189, 183, 107)",darkmagenta:"rgb(139, 0, 139)",darkolivegreen:"rgb( 85, 107, 47)",darkorange:"rgb(255, 140, 0)",darkorchid:"rgb(153, 50, 204)",darkred:"rgb(139, 0, 0)",darksalmon:"rgb(233, 150, 122)",darkseagreen:"rgb(143, 188, 143)",darkslateblue:"rgb( 72, 61, 139)",darkslategray:"rgb( 47, 79, 79)",darkslategrey:"rgb( 47, 79, 79)",darkturquoise:"rgb( 0, 206, 209)",darkviolet:"rgb(148, 0, 211)",deeppink:"rgb(255, 20, 147)",deepskyblue:"rgb( 0, 191, 255)",dimgray:"rgb(105, 105, 105)",dimgrey:"rgb(105, 105, 105)",dodgerblue:"rgb( 30, 144, 255)",firebrick:"rgb(178, 34, 34)",floralwhite:"rgb(255, 250, 240)",forestgreen:"rgb( 34, 139, 34)",fuchsia:"rgb(255, 0, 255)",gainsboro:"rgb(220, 220, 220)",ghostwhite:"rgb(248, 248, 255)",gold:"rgb(255, 215, 0)",goldenrod:"rgb(218, 165, 32)",gray:"rgb(128, 128, 128)",grey:"rgb(128, 128, 128)",green:"rgb( 0, 128, 0)",greenyellow:"rgb(173, 255, 47)",honeydew:"rgb(240, 255, 240)",hotpink:"rgb(255, 105, 180)",indianred:"rgb(205, 92, 92)",indigo:"rgb( 75, 0, 130)",ivory:"rgb(255, 255, 240)",khaki:"rgb(240, 230, 140)",lavender:"rgb(230, 230, 250)",lavenderblush:"rgb(255, 240, 245)",lawngreen:"rgb(124, 252, 0)",lemonchiffon:"rgb(255, 250, 205)",lightblue:"rgb(173, 216, 230)",lightcoral:"rgb(240, 128, 128)",lightcyan:"rgb(224, 255, 255)",lightgoldenrodyellow:"rgb(250, 250, 210)",lightgray:"rgb(211, 211, 211)",lightgreen:"rgb(144, 238, 144)",lightgrey:"rgb(211, 211, 211)",lightpink:"rgb(255, 182, 193)",lightsalmon:"rgb(255, 160, 122)",lightseagreen:"rgb( 32, 178, 170)",lightskyblue:"rgb(135, 206, 250)",lightslategray:"rgb(119, 136, 153)",lightslategrey:"rgb(119, 136, 153)",lightsteelblue:"rgb(176, 196, 222)",lightyellow:"rgb(255, 255, 224)",lime:"rgb( 0, 255, 0)",limegreen:"rgb( 50, 205, 50)",linen:"rgb(250, 240, 230)",magenta:"rgb(255, 0, 255)",maroon:"rgb(128, 0, 0)",mediumaquamarine:"rgb(102, 205, 170)",mediumblue:"rgb( 0, 0, 205)",mediumorchid:"rgb(186, 85, 211)",mediumpurple:"rgb(147, 112, 219)",mediumseagreen:"rgb( 60, 179, 113)",mediumslateblue:"rgb(123, 104, 238)",mediumspringgreen:"rgb( 0, 250, 154)",mediumturquoise:"rgb( 72, 209, 204)",mediumvioletred:"rgb(199, 21, 133)",midnightblue:"rgb( 25, 25, 112)",mintcream:"rgb(245, 255, 250)",mistyrose:"rgb(255, 228, 225)",moccasin:"rgb(255, 228, 181)",navajowhite:"rgb(255, 222, 173)",navy:"rgb( 0, 0, 128)",oldlace:"rgb(253, 245, 230)",olive:"rgb(128, 128, 0)",olivedrab:"rgb(107, 142, 35)",orange:"rgb(255, 165, 0)",orangered:"rgb(255, 69, 0)",orchid:"rgb(218, 112, 214)",palegoldenrod:"rgb(238, 232, 170)",palegreen:"rgb(152, 251, 152)",paleturquoise:"rgb(175, 238, 238)",palevioletred:"rgb(219, 112, 147)",papayawhip:"rgb(255, 239, 213)",peachpuff:"rgb(255, 218, 185)",peru:"rgb(205, 133, 63)",pink:"rgb(255, 192, 203)",plum:"rgb(221, 160, 221)",powderblue:"rgb(176, 224, 230)",purple:"rgb(128, 0, 128)",red:"rgb(255, 0, 0)",rosybrown:"rgb(188, 143, 143)",royalblue:"rgb( 65, 105, 225)",saddlebrown:"rgb(139, 69, 19)",salmon:"rgb(250, 128, 114)",sandybrown:"rgb(244, 164, 96)",seagreen:"rgb( 46, 139, 87)",seashell:"rgb(255, 245, 238)",sienna:"rgb(160, 82, 45)",silver:"rgb(192, 192, 192)",skyblue:"rgb(135, 206, 235)",slateblue:"rgb(106, 90, 205)",slategray:"rgb(112, 128, 144)",slategrey:"rgb(112, 128, 144)",snow:"rgb(255, 250, 250)",springgreen:"rgb( 0, 255, 127)",steelblue:"rgb( 70, 130, 180)",tan:"rgb(210, 180, 140)",teal:"rgb( 0, 128, 128)",thistle:"rgb(216, 191, 216)",tomato:"rgb(255, 99, 71)",turquoise:"rgb( 64, 224, 208)",violet:"rgb(238, 130, 238)",wheat:"rgb(245, 222, 179)",white:"rgb(255, 255, 255)",whitesmoke:"rgb(245, 245, 245)",yellow:"rgb(255, 255, 0)",yellowgreen:"rgb(154, 205, 50)"},a.jqplot.AxisLabelRenderer=function(b){a.jqplot.ElemContainer.call(this),this.axis,this.show=!0,this.label="",this.fontFamily=null,this.fontSize=null,this.textColor=null,this._elem,this.escapeHTML=!1,a.extend(!0,this,b)},a.jqplot.AxisLabelRenderer.prototype=new a.jqplot.ElemContainer,a.jqplot.AxisLabelRenderer.prototype.constructor=a.jqplot.AxisLabelRenderer,a.jqplot.AxisLabelRenderer.prototype.init=function(b){a.extend(!0,this,b)},a.jqplot.AxisLabelRenderer.prototype.draw=function(b,c){return this._elem&&(this._elem.emptyForce(),this._elem=null),this._elem=a('<div style="position:absolute;" class="jqplot-'+this.axis+'-label"></div>'),Number(this.label)&&this._elem.css("white-space","nowrap"),this.escapeHTML?this._elem.text(this.label):this._elem.html(this.label),this.fontFamily&&this._elem.css("font-family",this.fontFamily),this.fontSize&&this._elem.css("font-size",this.fontSize),this.textColor&&this._elem.css("color",this.textColor),this._elem},a.jqplot.AxisLabelRenderer.prototype.pack=function(){},a.jqplot.AxisTickRenderer=function(b){a.jqplot.ElemContainer.call(this),this.mark="outside",this.axis,this.showMark=!0,this.showGridline=!0,this.isMinorTick=!1,this.size=4,this.markSize=6,this.show=!0,this.showLabel=!0,this.label=null,this.value=null,this._styles={},this.formatter=a.jqplot.DefaultTickFormatter,this.prefix="",this.suffix="",this.formatString="",this.fontFamily,this.fontSize,this.textColor,this.escapeHTML=!1,this._elem,this._breakTick=!1,a.extend(!0,this,b)},a.jqplot.AxisTickRenderer.prototype.init=function(b){a.extend(!0,this,b)},a.jqplot.AxisTickRenderer.prototype=new a.jqplot.ElemContainer,a.jqplot.AxisTickRenderer.prototype.constructor=a.jqplot.AxisTickRenderer,a.jqplot.AxisTickRenderer.prototype.setTick=function(a,b,c){return this.value=a,this.axis=b,c&&(this.isMinorTick=!0),this},a.jqplot.AxisTickRenderer.prototype.draw=function(){null===this.label&&(this.label=this.prefix+this.formatter(this.formatString,this.value)+this.suffix);var b={position:"absolute"};Number(this.label)&&(b.whitSpace="nowrap"),this._elem&&(this._elem.emptyForce(),this._elem=null),this._elem=a(document.createElement("div")),this._elem.addClass("jqplot-"+this.axis+"-tick"),this.escapeHTML?this._elem.text(this.label):this._elem.html(this.label),this._elem.css(b);for(var c in this._styles)this._elem.css(c,this._styles[c]);return this.fontFamily&&this._elem.css("font-family",this.fontFamily),this.fontSize&&this._elem.css("font-size",this.fontSize),this.textColor&&this._elem.css("color",this.textColor),this._breakTick&&this._elem.addClass("jqplot-breakTick"),this._elem},a.jqplot.DefaultTickFormatter=function(b,c){return"number"==typeof c?(b||(b=a.jqplot.config.defaultTickFormatString),a.jqplot.sprintf(b,c)):String(c)},a.jqplot.PercentTickFormatter=function(b,c){return"number"==typeof c?(c=100*c,b||(b=a.jqplot.config.defaultTickFormatString),a.jqplot.sprintf(b,c)):String(c)},a.jqplot.AxisTickRenderer.prototype.pack=function(){},a.jqplot.CanvasGridRenderer=function(){this.shadowRenderer=new a.jqplot.ShadowRenderer},a.jqplot.CanvasGridRenderer.prototype.init=function(b){this._ctx,a.extend(!0,this,b);var c={lineJoin:"miter",lineCap:"round",fill:!1,isarc:!1,angle:this.shadowAngle,offset:this.shadowOffset,alpha:this.shadowAlpha,depth:this.shadowDepth,lineWidth:this.shadowWidth,closePath:!1,strokeStyle:this.shadowColor};this.renderer.shadowRenderer.init(c)},a.jqplot.CanvasGridRenderer.prototype.createElement=function(b){var c;this._elem&&(a.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==F&&(c=this._elem.get(0),window.G_vmlCanvasManager.uninitElement(c),c=null),this._elem.emptyForce(),this._elem=null),c=b.canvasManager.getCanvas();var d=this._plotDimensions.width,e=this._plotDimensions.height;return c.width=d,c.height=e,this._elem=a(c),this._elem.addClass("jqplot-grid-canvas"),this._elem.css({position:"absolute",left:0,top:0}),c=b.canvasManager.initCanvas(c),this._top=this._offsets.top,this._bottom=e-this._offsets.bottom,this._left=this._offsets.left,this._right=d-this._offsets.right,this._width=this._right-this._left,this._height=this._bottom-this._top,c=null,this._elem},a.jqplot.CanvasGridRenderer.prototype.draw=function(){function b(b,d,e,f,g){c.save(),g=g||{},(null==g.lineWidth||0!=g.lineWidth)&&(a.extend(!0,c,g),c.beginPath(),c.moveTo(b,d),c.lineTo(e,f),c.stroke(),c.restore())}this._ctx=this._elem.get(0).getContext("2d");var c=this._ctx,d=this._axes;c.save(),c.clearRect(0,0,this._plotDimensions.width,this._plotDimensions.height),c.fillStyle=this.backgroundColor||this.background,c.fillRect(this._left,this._top,this._width,this._height),c.save(),c.lineJoin="miter",c.lineCap="butt",c.lineWidth=this.gridLineWidth,c.strokeStyle=this.gridLineColor;for(var e,f,g,h,i=["xaxis","yaxis","x2axis","y2axis"],j=4;j>0;j--){var k=i[j-1],l=d[k],m=l._ticks,n=m.length;if(l.show){if(l.drawBaseline){var o={};switch(null!==l.baselineWidth&&(o.lineWidth=l.baselineWidth),null!==l.baselineColor&&(o.strokeStyle=l.baselineColor),k){case"xaxis":b(this._left,this._bottom,this._right,this._bottom,o);break;case"yaxis":b(this._left,this._bottom,this._left,this._top,o);break;case"x2axis":b(this._left,this._bottom,this._right,this._bottom,o);break;case"y2axis":b(this._right,this._bottom,this._right,this._top,o)}}for(var p=n;p>0;p--){var q=m[p-1];if(q.show){var r=Math.round(l.u2p(q.value))+.5;switch(k){case"xaxis":if(q.showGridline&&this.drawGridlines&&(!q.isMinorTick&&l.drawMajorGridlines||q.isMinorTick&&l.drawMinorGridlines)&&b(r,this._top,r,this._bottom),q.showMark&&q.mark&&(!q.isMinorTick&&l.drawMajorTickMarks||q.isMinorTick&&l.drawMinorTickMarks)){g=q.markSize,h=q.mark;var r=Math.round(l.u2p(q.value))+.5;switch(h){case"outside":e=this._bottom,f=this._bottom+g;break;case"inside":e=this._bottom-g,f=this._bottom;break;case"cross":e=this._bottom-g,f=this._bottom+g;break;default:e=this._bottom,f=this._bottom+g}this.shadow&&this.renderer.shadowRenderer.draw(c,[[r,e],[r,f]],{lineCap:"butt",lineWidth:this.gridLineWidth,offset:.75*this.gridLineWidth,depth:2,fill:!1,closePath:!1}),b(r,e,r,f)}break;case"yaxis":if(q.showGridline&&this.drawGridlines&&(!q.isMinorTick&&l.drawMajorGridlines||q.isMinorTick&&l.drawMinorGridlines)&&b(this._right,r,this._left,r),q.showMark&&q.mark&&(!q.isMinorTick&&l.drawMajorTickMarks||q.isMinorTick&&l.drawMinorTickMarks)){g=q.markSize,h=q.mark;var r=Math.round(l.u2p(q.value))+.5;switch(h){case"outside":e=this._left-g,f=this._left;break;case"inside":e=this._left,f=this._left+g;break;case"cross":e=this._left-g,f=this._left+g;break;default:e=this._left-g,f=this._left}this.shadow&&this.renderer.shadowRenderer.draw(c,[[e,r],[f,r]],{lineCap:"butt",lineWidth:1.5*this.gridLineWidth,offset:.75*this.gridLineWidth,fill:!1,closePath:!1}),b(e,r,f,r,{strokeStyle:l.borderColor})}break;case"x2axis":if(q.showGridline&&this.drawGridlines&&(!q.isMinorTick&&l.drawMajorGridlines||q.isMinorTick&&l.drawMinorGridlines)&&b(r,this._bottom,r,this._top),q.showMark&&q.mark&&(!q.isMinorTick&&l.drawMajorTickMarks||q.isMinorTick&&l.drawMinorTickMarks)){g=q.markSize,h=q.mark;var r=Math.round(l.u2p(q.value))+.5;switch(h){case"outside":e=this._top-g,f=this._top;break;case"inside":e=this._top,f=this._top+g;break;case"cross":e=this._top-g,f=this._top+g;break;default:e=this._top-g,f=this._top}this.shadow&&this.renderer.shadowRenderer.draw(c,[[r,e],[r,f]],{lineCap:"butt",lineWidth:this.gridLineWidth,offset:.75*this.gridLineWidth,depth:2,fill:!1,closePath:!1}),b(r,e,r,f)}break;case"y2axis":if(q.showGridline&&this.drawGridlines&&(!q.isMinorTick&&l.drawMajorGridlines||q.isMinorTick&&l.drawMinorGridlines)&&b(this._left,r,this._right,r),q.showMark&&q.mark&&(!q.isMinorTick&&l.drawMajorTickMarks||q.isMinorTick&&l.drawMinorTickMarks)){g=q.markSize,h=q.mark;var r=Math.round(l.u2p(q.value))+.5;switch(h){case"outside":e=this._right,f=this._right+g;break;case"inside":e=this._right-g,f=this._right;break;case"cross":e=this._right-g,f=this._right+g;break;default:e=this._right,f=this._right+g}this.shadow&&this.renderer.shadowRenderer.draw(c,[[e,r],[f,r]],{lineCap:"butt",lineWidth:1.5*this.gridLineWidth,offset:.75*this.gridLineWidth,fill:!1,closePath:!1}),b(e,r,f,r,{strokeStyle:l.borderColor})}}}}q=null}l=null,m=null}i=["y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis","yMidAxis"];for(var j=7;j>0;j--){var l=d[i[j-1]],m=l._ticks;if(l.show){var s=m[l.numberTicks-1],t=m[0],u=l.getLeft(),v=[[u,s.getTop()+s.getHeight()/2],[u,t.getTop()+t.getHeight()/2+1]];this.shadow&&this.renderer.shadowRenderer.draw(c,v,{lineCap:"butt",fill:!1,closePath:!1}),b(v[0][0],v[0][1],v[1][0],v[1][1],{lineCap:"butt",strokeStyle:l.borderColor,lineWidth:l.borderWidth});for(var p=m.length;p>0;p--){var q=m[p-1];g=q.markSize,h=q.mark;var r=Math.round(l.u2p(q.value))+.5;if(q.showMark&&q.mark){switch(h){case"outside":e=u,f=u+g;break;case"inside":e=u-g,f=u;break;case"cross":e=u-g,f=u+g;break;default:e=u,f=u+g}v=[[e,r],[f,r]],this.shadow&&this.renderer.shadowRenderer.draw(c,v,{lineCap:"butt",lineWidth:1.5*this.gridLineWidth,offset:.75*this.gridLineWidth,fill:!1,closePath:!1}),b(e,r,f,r,{strokeStyle:l.borderColor})}q=null}t=null}l=null,m=null}if(c.restore(),this.shadow){var v=[[this._left,this._bottom],[this._right,this._bottom],[this._right,this._top]];this.renderer.shadowRenderer.draw(c,v)}0!=this.borderWidth&&this.drawBorder&&(b(this._left,this._top,this._right,this._top,{lineCap:"round",strokeStyle:d.x2axis.borderColor,lineWidth:d.x2axis.borderWidth}),b(this._right,this._top,this._right,this._bottom,{lineCap:"round",strokeStyle:d.y2axis.borderColor,lineWidth:d.y2axis.borderWidth}),b(this._right,this._bottom,this._left,this._bottom,{lineCap:"round",strokeStyle:d.xaxis.borderColor,lineWidth:d.xaxis.borderWidth}),b(this._left,this._bottom,this._left,this._top,{lineCap:"round",strokeStyle:d.yaxis.borderColor,lineWidth:d.yaxis.borderWidth})),c.restore(),c=null,d=null},a.jqplot.DivTitleRenderer=function(){},a.jqplot.DivTitleRenderer.prototype.init=function(b){a.extend(!0,this,b)},a.jqplot.DivTitleRenderer.prototype.draw=function(){this._elem&&(this._elem.emptyForce(),this._elem=null);var b=(this.renderer,document.createElement("div"));if(this._elem=a(b),this._elem.addClass("jqplot-title"),this.text){if(this.text){var c;this.color?c=this.color:this.textColor&&(c=this.textColor);var d={position:"absolute",top:"0px",left:"0px"};this._plotWidth&&(d.width=this._plotWidth+"px"),this.fontSize&&(d.fontSize=this.fontSize),"string"==typeof this.textAlign?d.textAlign=this.textAlign:d.textAlign="center",c&&(d.color=c),this.paddingBottom&&(d.paddingBottom=this.paddingBottom),this.fontFamily&&(d.fontFamily=this.fontFamily),this._elem.css(d),this.escapeHtml?this._elem.text(this.text):this._elem.html(this.text)}}else this.show=!1,this._elem.height(0),this._elem.width(0);return b=null,this._elem},a.jqplot.DivTitleRenderer.prototype.pack=function(){};var H=.1;a.jqplot.LinePattern=function(b,c){var d={dotted:[H,a.jqplot.config.dotGapLength],dashed:[a.jqplot.config.dashLength,a.jqplot.config.gapLength],solid:null};if("string"==typeof c)if("."===c[0]||"-"===c[0]){var e=c;c=[];for(var f=0,g=e.length;g>f;f++){if("."===e[f])c.push(H);else{if("-"!==e[f])continue;c.push(a.jqplot.config.dashLength)}c.push(a.jqplot.config.gapLength)}}else c=d[c];if(!c||!c.length)return b;var h=0,i=c[0],j=0,k=0,l=0,m=0,n=function(a,c){b.moveTo(a,c),j=a,k=c,l=a,m=c},o=function(a,d){var e=b.lineWidth,f=a-j,g=d-k,l=Math.sqrt(f*f+g*g);if(l>0&&e>0)for(f/=l,g/=l;;){var m=e*i;if(!(l>m)){j=a,k=d,0==(1&h)?b.lineTo(j,k):b.moveTo(j,k),i-=l/e;break}j+=m*f,k+=m*g,0==(1&h)?b.lineTo(j,k):b.moveTo(j,k),l-=m,h++,h>=c.length&&(h=0),i=c[h]}},p=function(){b.beginPath()},q=function(){o(l,m)};return{moveTo:n,lineTo:o,beginPath:p,closePath:q}},a.jqplot.LineRenderer=function(){this.shapeRenderer=new a.jqplot.ShapeRenderer,this.shadowRenderer=new a.jqplot.ShadowRenderer},a.jqplot.LineRenderer.prototype.init=function(b,c){b=b||{},this._type="line",this.renderer.animation={show:!1,direction:"left",speed:2500,_supported:!0},this.renderer.smooth=!1,this.renderer.tension=null,this.renderer.constrainSmoothing=!0,this.renderer._smoothedData=[],this.renderer._smoothedPlotData=[],this.renderer._hiBandGridData=[],this.renderer._lowBandGridData=[],this.renderer._hiBandSmoothedData=[],this.renderer._lowBandSmoothedData=[],this.renderer.bandData=[],this.renderer.bands={show:!1,hiData:[],lowData:[],color:this.color,showLines:!1,fill:!0,fillColor:null,_min:null,_max:null,interval:"3%"};var d={highlightMouseOver:b.highlightMouseOver,highlightMouseDown:b.highlightMouseDown,highlightColor:b.highlightColor};delete b.highlightMouseOver,delete b.highlightMouseDown,delete b.highlightColor,a.extend(!0,this.renderer,b),this.renderer.options=b,this.renderer.bandData.length>1&&(!b.bands||null==b.bands.show)?this.renderer.bands.show=!0:b.bands&&null==b.bands.show&&null!=b.bands.interval&&(this.renderer.bands.show=!0),this.fill&&(this.renderer.bands.show=!1),this.renderer.bands.show&&this.renderer.initBands.call(this,this.renderer.options,c),this._stack&&(this.renderer.smooth=!1);var e={lineJoin:this.lineJoin,lineCap:this.lineCap,fill:this.fill,isarc:!1,strokeStyle:this.color,fillStyle:this.fillColor,lineWidth:this.lineWidth,linePattern:this.linePattern,closePath:this.fill};this.renderer.shapeRenderer.init(e);var f=b.shadowOffset;null==f&&(f=this.lineWidth>2.5?1.25*(1+.6*(Math.atan(this.lineWidth/2.5)/.785398163-1)):1.25*Math.atan(this.lineWidth/2.5)/.785398163);var g={lineJoin:this.lineJoin,lineCap:this.lineCap,fill:this.fill,isarc:!1,angle:this.shadowAngle,offset:f,alpha:this.shadowAlpha,depth:this.shadowDepth,lineWidth:this.lineWidth,linePattern:this.linePattern,closePath:this.fill};if(this.renderer.shadowRenderer.init(g),this._areaPoints=[],this._boundingBox=[[],[]],!this.isTrendline&&this.fill||this.renderer.bands.show){if(this.highlightMouseOver=!0,this.highlightMouseDown=!1,this.highlightColor=null,d.highlightMouseDown&&null==d.highlightMouseOver&&(d.highlightMouseOver=!1),a.extend(!0,this,{highlightMouseOver:d.highlightMouseOver,highlightMouseDown:d.highlightMouseDown,highlightColor:d.highlightColor}),!this.highlightColor){var h=this.renderer.bands.show?this.renderer.bands.fillColor:this.fillColor;this.highlightColor=a.jqplot.computeHighlightColors(h)}this.highlighter&&(this.highlighter.show=!1)}!this.isTrendline&&c&&(c.plugins.lineRenderer={},c.postInitHooks.addOnce(l),c.postDrawHooks.addOnce(m),c.eventListenerHooks.addOnce("jqplotMouseMove",p),c.eventListenerHooks.addOnce("jqplotMouseDown",q),c.eventListenerHooks.addOnce("jqplotMouseUp",r),c.eventListenerHooks.addOnce("jqplotClick",s),c.eventListenerHooks.addOnce("jqplotRightClick",t))},a.jqplot.LineRenderer.prototype.initBands=function(b,c){var d=b.bandData||[],e=this.renderer.bands;e.hiData=[],e.lowData=[];var f=this.data;if(e._max=null,e._min=null,2==d.length)if(a.isArray(d[0][0])){for(var g,h=0,i=0,j=0,k=d[0].length;k>j;j++)g=d[0][j],(null!=g[1]&&g[1]>e._max||null==e._max)&&(e._max=g[1]),(null!=g[1]&&g[1]<e._min||null==e._min)&&(e._min=g[1]);for(var j=0,k=d[1].length;k>j;j++)g=d[1][j],(null!=g[1]&&g[1]>e._max||null==e._max)&&(e._max=g[1],i=1),(null!=g[1]&&g[1]<e._min||null==e._min)&&(e._min=g[1],h=1);i===h&&(e.show=!1),e.hiData=d[i],e.lowData=d[h]}else if(d[0].length===f.length&&d[1].length===f.length)for(var l=d[0][0]>d[1][0]?0:1,m=l?0:1,j=0,k=f.length;k>j;j++)e.hiData.push([f[j][0],d[l][j]]),e.lowData.push([f[j][0],d[m][j]]);else e.show=!1;else if(d.length>2&&!a.isArray(d[0][0]))for(var l=d[0][0]>d[0][1]?0:1,m=l?0:1,j=0,k=d.length;k>j;j++)e.hiData.push([f[j][0],d[j][l]]),e.lowData.push([f[j][0],d[j][m]]);else{var n=e.interval,o=null,p=null,q=null,r=null;if(a.isArray(n)?(o=n[0],p=n[1]):o=n,isNaN(o)?"%"===o.charAt(o.length-1)&&(q="multiply",o=parseFloat(o)/100+1):(o=parseFloat(o),q="add"),null!==p&&isNaN(p)?"%"===p.charAt(p.length-1)&&(r="multiply",p=parseFloat(p)/100+1):null!==p&&(p=parseFloat(p),r="add"),null!==o){if(null===p&&(p=-o,r=q,"multiply"===r&&(p+=2)),p>o){var s=o;o=p,p=s,s=q,q=r,r=s}for(var j=0,k=f.length;k>j;j++){switch(q){case"add":e.hiData.push([f[j][0],f[j][1]+o]);break;case"multiply":e.hiData.push([f[j][0],f[j][1]*o])}switch(r){case"add":e.lowData.push([f[j][0],f[j][1]+p]);break;case"multiply":e.lowData.push([f[j][0],f[j][1]*p])}}}else e.show=!1}for(var t=e.hiData,u=e.lowData,j=0,k=t.length;k>j;j++)(null!=t[j][1]&&t[j][1]>e._max||null==e._max)&&(e._max=t[j][1]);for(var j=0,k=u.length;k>j;j++)(null!=u[j][1]&&u[j][1]<e._min||null==e._min)&&(e._min=u[j][1]);if(null===e.fillColor){var v=a.jqplot.getColorComponents(e.color);v[3]=.5*v[3],e.fillColor="rgba("+v[0]+", "+v[1]+", "+v[2]+", "+v[3]+")"}},a.jqplot.LineRenderer.prototype.setGridData=function(a){var b=this._xaxis.series_u2p,c=this._yaxis.series_u2p,d=this._plotData,e=this._prevPlotData;this.gridData=[],this._prevGridData=[],this.renderer._smoothedData=[],this.renderer._smoothedPlotData=[],this.renderer._hiBandGridData=[],this.renderer._lowBandGridData=[],this.renderer._hiBandSmoothedData=[],this.renderer._lowBandSmoothedData=[];for(var f=this.renderer.bands,g=!1,h=0,i=d.length;i>h;h++)null!=d[h][0]&&null!=d[h][1]?this.gridData.push([b.call(this._xaxis,d[h][0]),c.call(this._yaxis,d[h][1])]):null==d[h][0]?(g=!0,this.gridData.push([null,c.call(this._yaxis,d[h][1])])):null==d[h][1]&&(g=!0,this.gridData.push([b.call(this._xaxis,d[h][0]),null])),null!=e[h]&&null!=e[h][0]&&null!=e[h][1]?this._prevGridData.push([b.call(this._xaxis,e[h][0]),c.call(this._yaxis,e[h][1])]):null!=e[h]&&null==e[h][0]?this._prevGridData.push([null,c.call(this._yaxis,e[h][1])]):null!=e[h]&&null!=e[h][0]&&null==e[h][1]&&this._prevGridData.push([b.call(this._xaxis,e[h][0]),null]);if(g&&(this.renderer.smooth=!1,"line"===this._type&&(f.show=!1)),"line"===this._type&&f.show){for(var h=0,i=f.hiData.length;i>h;h++)this.renderer._hiBandGridData.push([b.call(this._xaxis,f.hiData[h][0]),c.call(this._yaxis,f.hiData[h][1])]);for(var h=0,i=f.lowData.length;i>h;h++)this.renderer._lowBandGridData.push([b.call(this._xaxis,f.lowData[h][0]),c.call(this._yaxis,f.lowData[h][1])])}if("line"===this._type&&this.renderer.smooth&&this.gridData.length>2){var l;this.renderer.constrainSmoothing?(l=j.call(this,this.gridData),this.renderer._smoothedData=l[0],this.renderer._smoothedPlotData=l[1],f.show&&(l=j.call(this,this.renderer._hiBandGridData),this.renderer._hiBandSmoothedData=l[0],l=j.call(this,this.renderer._lowBandGridData),this.renderer._lowBandSmoothedData=l[0]),l=null):(l=k.call(this,this.gridData),this.renderer._smoothedData=l[0],this.renderer._smoothedPlotData=l[1],f.show&&(l=k.call(this,this.renderer._hiBandGridData),this.renderer._hiBandSmoothedData=l[0],l=k.call(this,this.renderer._lowBandGridData),this.renderer._lowBandSmoothedData=l[0]),l=null)}},a.jqplot.LineRenderer.prototype.makeGridData=function(a,b){var c=this._xaxis.series_u2p,d=this._yaxis.series_u2p,e=[];this.renderer._smoothedData=[],this.renderer._smoothedPlotData=[],this.renderer._hiBandGridData=[],this.renderer._lowBandGridData=[],this.renderer._hiBandSmoothedData=[],this.renderer._lowBandSmoothedData=[];for(var f=this.renderer.bands,g=!1,h=0;h<a.length;h++)null!=a[h][0]&&null!=a[h][1]?(this.step&&h>0&&e.push([c.call(this._xaxis,a[h][0]),d.call(this._yaxis,a[h-1][1])]),e.push([c.call(this._xaxis,a[h][0]),d.call(this._yaxis,a[h][1])])):null==a[h][0]?(g=!0,e.push([null,d.call(this._yaxis,a[h][1])])):null==a[h][1]&&(g=!0,e.push([c.call(this._xaxis,a[h][0]),null]));if(g&&(this.renderer.smooth=!1,"line"===this._type&&(f.show=!1)),"line"===this._type&&f.show){for(var h=0,i=f.hiData.length;i>h;h++)this.renderer._hiBandGridData.push([c.call(this._xaxis,f.hiData[h][0]),d.call(this._yaxis,f.hiData[h][1])]);for(var h=0,i=f.lowData.length;i>h;h++)this.renderer._lowBandGridData.push([c.call(this._xaxis,f.lowData[h][0]),d.call(this._yaxis,f.lowData[h][1])])}if("line"===this._type&&this.renderer.smooth&&e.length>2){var l;this.renderer.constrainSmoothing?(l=j.call(this,e),this.renderer._smoothedData=l[0],this.renderer._smoothedPlotData=l[1],f.show&&(l=j.call(this,this.renderer._hiBandGridData),this.renderer._hiBandSmoothedData=l[0],l=j.call(this,this.renderer._lowBandGridData),this.renderer._lowBandSmoothedData=l[0]),l=null):(l=k.call(this,e),this.renderer._smoothedData=l[0],this.renderer._smoothedPlotData=l[1],f.show&&(l=k.call(this,this.renderer._hiBandGridData),this.renderer._hiBandSmoothedData=l[0],l=k.call(this,this.renderer._lowBandGridData),this.renderer._lowBandSmoothedData=l[0]),l=null)}return e},a.jqplot.LineRenderer.prototype.draw=function(b,c,d,e){var f,g,h,i,j,k=a.extend(!0,{},d),l=k.shadow!=F?k.shadow:this.shadow,m=k.showLine!=F?k.showLine:this.showLine,n=k.fill!=F?k.fill:this.fill,o=k.fillAndStroke!=F?k.fillAndStroke:this.fillAndStroke;if(b.save(),c.length){if(m)if(n){if(this.fillToZero){var p=this.negativeColor;this.useNegativeColors||(p=k.fillStyle);var q=!1,r=k.fillStyle;if(o)var s=c.slice(0);if(0!=this.index&&this._stack){for(var t=this._prevGridData,f=t.length;f>0;f--)c.push(t[f-1]);l&&this.renderer.shadowRenderer.draw(b,c,k),this._areaPoints=c,this.renderer.shapeRenderer.draw(b,c,k)}else{var u=[],v=this.renderer.smooth?this.renderer._smoothedPlotData:this._plotData;this._areaPoints=[];var w=this._yaxis.series_u2p(this.fillToValue);this._xaxis.series_u2p(this.fillToValue);if(k.closePath=!0,"y"==this.fillAxis){u.push([c[0][0],w]),this._areaPoints.push([c[0][0],w]);for(var f=0;f<c.length-1;f++)if(u.push(c[f]),this._areaPoints.push(c[f]),v[f][1]*v[f+1][1]<=0){v[f][1]<0?(q=!0,k.fillStyle=p):(q=!1,k.fillStyle=r);var x=c[f][0]+(c[f+1][0]-c[f][0])*(w-c[f][1])/(c[f+1][1]-c[f][1]);u.push([x,w]),this._areaPoints.push([x,w]),l&&this.renderer.shadowRenderer.draw(b,u,k),this.renderer.shapeRenderer.draw(b,u,k),u=[[x,w]]}v[c.length-1][1]<0?(q=!0,k.fillStyle=p):(q=!1,k.fillStyle=r),u.push(c[c.length-1]),this._areaPoints.push(c[c.length-1]),u.push([c[c.length-1][0],w]),this._areaPoints.push([c[c.length-1][0],w])}l&&this.renderer.shadowRenderer.draw(b,u,k),this.renderer.shapeRenderer.draw(b,u,k)}}else{if(o)var s=c.slice(0);if(0!=this.index&&this._stack)for(var t=this._prevGridData,f=t.length;f>0;f--)c.push(t[f-1]);else{var y=b.canvas.height;c.unshift([c[0][0],y]);var z=c.length;c.push([c[z-1][0],y])}this._areaPoints=c,l&&this.renderer.shadowRenderer.draw(b,c,k),this.renderer.shapeRenderer.draw(b,c,k)}if(o){var A=a.extend(!0,{},k,{fill:!1,closePath:!1});if(this.renderer.shapeRenderer.draw(b,s,A),this.markerRenderer.show)for(this.renderer.smooth&&(s=this.gridData),f=0;f<s.length;f++)this.markerRenderer.draw(s[f][0],s[f][1],b,k.markerOptions)}}else{if(this.renderer.bands.show){var B,C=a.extend(!0,{},k);this.renderer.bands.showLines&&(B=this.renderer.smooth?this.renderer._hiBandSmoothedData:this.renderer._hiBandGridData,this.renderer.shapeRenderer.draw(b,B,k),B=this.renderer.smooth?this.renderer._lowBandSmoothedData:this.renderer._lowBandGridData,this.renderer.shapeRenderer.draw(b,B,C)),this.renderer.bands.fill&&(B=this.renderer.smooth?this.renderer._hiBandSmoothedData.concat(this.renderer._lowBandSmoothedData.reverse()):this.renderer._hiBandGridData.concat(this.renderer._lowBandGridData.reverse()),this._areaPoints=B,C.closePath=!0,C.fill=!0,C.fillStyle=this.renderer.bands.fillColor,this.renderer.shapeRenderer.draw(b,B,C))}l&&this.renderer.shadowRenderer.draw(b,c,k),this.renderer.shapeRenderer.draw(b,c,k)}var g=i=h=j=null;for(f=0;f<this._areaPoints.length;f++){var D=this._areaPoints[f];(g>D[0]||null==g)&&(g=D[0]),(j<D[1]||null==j)&&(j=D[1]),(i<D[0]||null==i)&&(i=D[0]),(h>D[1]||null==h)&&(h=D[1])}if("line"===this.type&&this.renderer.bands.show&&(j=this._yaxis.series_u2p(this.renderer.bands._min),h=this._yaxis.series_u2p(this.renderer.bands._max)),this._boundingBox=[[g,j],[i,h]],this.markerRenderer.show&&!n)for(this.renderer.smooth&&(c=this.gridData),f=0;f<c.length;f++)null!=c[f][0]&&null!=c[f][1]&&this.markerRenderer.draw(c[f][0],c[f][1],b,k.markerOptions)}b.restore()},a.jqplot.LineRenderer.prototype.drawShadow=function(a,b,c){},a.jqplot.LinearAxisRenderer=function(){},a.jqplot.LinearAxisRenderer.prototype.init=function(b){this.breakPoints=null,this.breakTickLabel="&asymp;",this.drawBaseline=!0,this.baselineWidth=null,this.baselineColor=null,this.forceTickAt0=!1,this.forceTickAt100=!1,this.tickInset=0,this.minorTicks=0,this.alignTicks=!1,this._autoFormatString="",this._overrideFormatString=!1,this._scalefact=1,a.extend(!0,this,b),this.breakPoints&&(a.isArray(this.breakPoints)?(this.breakPoints.length<2||this.breakPoints[1]<=this.breakPoints[0])&&(this.breakPoints=null):this.breakPoints=null),
7
+ null!=this.numberTicks&&this.numberTicks<2&&(this.numberTicks=2),this.resetDataBounds()},a.jqplot.LinearAxisRenderer.prototype.draw=function(b,c){if(this.show){this.renderer.createTicks.call(this,c);if(this._elem&&(this._elem.emptyForce(),this._elem=null),this._elem=a(document.createElement("div")),this._elem.addClass("jqplot-axis jqplot-"+this.name),this._elem.css("position","absolute"),"xaxis"==this.name||"x2axis"==this.name?this._elem.width(this._plotDimensions.width):this._elem.height(this._plotDimensions.height),this.labelOptions.axis=this.name,this._label=new this.labelRenderer(this.labelOptions),this._label.show){var d=this._label.draw(b,c);d.appendTo(this._elem),d=null}for(var e,f=this._ticks,g=0;g<f.length;g++)e=f[g],e.show&&e.showLabel&&(!e.isMinorTick||this.showMinorTicks)&&this._elem.append(e.draw(b,c));e=null,f=null}return this._elem},a.jqplot.LinearAxisRenderer.prototype.reset=function(){this.min=this._options.min,this.max=this._options.max,this.tickInterval=this._options.tickInterval,this.numberTicks=this._options.numberTicks,this._autoFormatString="",this._overrideFormatString&&this.tickOptions&&this.tickOptions.formatString&&(this.tickOptions.formatString="")},a.jqplot.LinearAxisRenderer.prototype.set=function(){var b,c=0,d=0,e=0,f=null==this._label?!1:this._label.show;if(this.show){for(var g,h=this._ticks,i=0;i<h.length;i++)g=h[i],g._breakTick||!g.show||!g.showLabel||g.isMinorTick&&!this.showMinorTicks||(b="xaxis"==this.name||"x2axis"==this.name?g._elem.outerHeight(!0):g._elem.outerWidth(!0),b>c&&(c=b));g=null,h=null,f&&(d=this._label._elem.outerWidth(!0),e=this._label._elem.outerHeight(!0)),"xaxis"==this.name?(c+=e,this._elem.css({height:c+"px",left:"0px",bottom:"0px"})):"x2axis"==this.name?(c+=e,this._elem.css({height:c+"px",left:"0px",top:"0px"})):"yaxis"==this.name?(c+=d,this._elem.css({width:c+"px",left:"0px",top:"0px"}),f&&this._label.constructor==a.jqplot.AxisLabelRenderer&&this._label._elem.css("width",d+"px")):(c+=d,this._elem.css({width:c+"px",right:"0px",top:"0px"}),f&&this._label.constructor==a.jqplot.AxisLabelRenderer&&this._label._elem.css("width",d+"px"))}},a.jqplot.LinearAxisRenderer.prototype.createTicks=function(b){var c,d,e,f,g=this._ticks,h=this.ticks,i=this.name,j=this._dataBounds,k="x"===this.name.charAt(0)?this._plotDimensions.width:this._plotDimensions.height,l=this.min,m=this.max,n=this.numberTicks,o=this.tickInterval,p=30;if(this._scalefact=(Math.max(k,p+1)-p)/300,h.length){for(f=0;f<h.length;f++){var q=h[f],r=new this.tickRenderer(this.tickOptions);a.isArray(q)?(r.value=q[0],this.breakPoints?q[0]==this.breakPoints[0]?(r.label=this.breakTickLabel,r._breakTick=!0,r.showGridline=!1,r.showMark=!1):q[0]>this.breakPoints[0]&&q[0]<=this.breakPoints[1]?(r.show=!1,r.showGridline=!1,r.label=q[1]):r.label=q[1]:r.label=q[1],r.setTick(q[0],this.name),this._ticks.push(r)):a.isPlainObject(q)?(a.extend(!0,r,q),r.axis=this.name,this._ticks.push(r)):(r.value=q,this.breakPoints&&(q==this.breakPoints[0]?(r.label=this.breakTickLabel,r._breakTick=!0,r.showGridline=!1,r.showMark=!1):q>this.breakPoints[0]&&q<=this.breakPoints[1]&&(r.show=!1,r.showGridline=!1)),r.setTick(q,this.name),this._ticks.push(r))}this.numberTicks=h.length,this.min=this._ticks[0].value,this.max=this._ticks[this.numberTicks-1].value,this.tickInterval=(this.max-this.min)/(this.numberTicks-1)}else{k="xaxis"==i||"x2axis"==i?this._plotDimensions.width:this._plotDimensions.height;var s=this.numberTicks;this.alignTicks&&("x2axis"===this.name&&b.axes.xaxis.show?s=b.axes.xaxis.numberTicks:"y"===this.name.charAt(0)&&"yaxis"!==this.name&&"yMidAxis"!==this.name&&b.axes.yaxis.show&&(s=b.axes.yaxis.numberTicks)),c=null!=this.min?this.min:j.min,d=null!=this.max?this.max:j.max;var t,u,v,w=d-c;if(null!=this.tickOptions&&this.tickOptions.formatString||(this._overrideFormatString=!0),null==this.min||null==this.max&&null==this.tickInterval&&!this.autoscale){this.forceTickAt0&&(c>0&&(c=0),0>d&&(d=0)),this.forceTickAt100&&(c>100&&(c=100),100>d&&(d=100));var x=!1,y=!1;null!=this.min?x=!0:null!=this.max&&(y=!0);var z=a.jqplot.LinearTickGenerator(c,d,this._scalefact,s,x,y),A=null!=this.min?c:c+w*(this.padMin-1),B=null!=this.max?d:d-w*(this.padMax-1);(A>c||d>B)&&(A=null!=this.min?c:c-w*(this.padMin-1),B=null!=this.max?d:d+w*(this.padMax-1),z=a.jqplot.LinearTickGenerator(A,B,this._scalefact,s,x,y)),this.min=z[0],this.max=z[1],this.numberTicks=z[2],this._autoFormatString=z[3],this.tickInterval=z[4]}else{if(c==d){var C=.05;c>0&&(C=Math.max(Math.log(c)/Math.LN10,.05)),c-=C,d+=C}if(this.autoscale&&null==this.min&&null==this.max){for(var D,E,F,G=!1,H=!1,f=0;f<this._series.length;f++){var I=this._series[f],J="x"==I.fillAxis?I._xaxis.name:I._yaxis.name;if(this.name==J){for(var K=I._plotValues[I.fillAxis],L=K[0],M=K[0],N=1;N<K.length;N++)K[N]<L?L=K[N]:K[N]>M&&(M=K[N]);var O=(M-L)/M;I.renderer.constructor==a.jqplot.BarRenderer?L>=0&&(I.fillToZero||O>.1)?G=!0:(G=!1,H=I.fill&&I.fillToZero&&0>L&&M>0?!0:!1):I.fill?L>=0&&(I.fillToZero||O>.1)?G=!0:0>L&&M>0&&I.fillToZero?(G=!1,H=!0):(G=!1,H=!1):0>L&&(G=!1)}}if(G)this.numberTicks=2+Math.ceil((k-(this.tickSpacing-1))/this.tickSpacing),this.min=0,l=0,E=d/(this.numberTicks-1),v=Math.pow(10,Math.abs(Math.floor(Math.log(E)/Math.LN10))),E/v==parseInt(E/v,10)&&(E+=v),this.tickInterval=Math.ceil(E/v)*v,this.max=this.tickInterval*(this.numberTicks-1);else if(H){this.numberTicks=2+Math.ceil((k-(this.tickSpacing-1))/this.tickSpacing);var P=Math.ceil(Math.abs(c)/w*(this.numberTicks-1)),Q=this.numberTicks-1-P;E=Math.max(Math.abs(c/P),Math.abs(d/Q)),v=Math.pow(10,Math.abs(Math.floor(Math.log(E)/Math.LN10))),this.tickInterval=Math.ceil(E/v)*v,this.max=this.tickInterval*Q,this.min=-this.tickInterval*P}else null==this.numberTicks&&(this.tickInterval?this.numberTicks=3+Math.ceil(w/this.tickInterval):this.numberTicks=2+Math.ceil((k-(this.tickSpacing-1))/this.tickSpacing)),null==this.tickInterval?(E=w/(this.numberTicks-1),v=1>E?Math.pow(10,Math.abs(Math.floor(Math.log(E)/Math.LN10))):1,this.tickInterval=Math.ceil(E*v*this.pad)/v):v=1/this.tickInterval,D=this.tickInterval*(this.numberTicks-1),F=(D-w)/2,null==this.min&&(this.min=Math.floor(v*(c-F))/v),null==this.max&&(this.max=this.min+D);var R,S=a.jqplot.getSignificantFigures(this.tickInterval);if(S.digitsLeft>=S.significantDigits)R="%d";else{var v=Math.max(0,5-S.digitsLeft);v=Math.min(v,S.digitsRight),R="%."+v+"f"}this._autoFormatString=R}else{t=null!=this.min?this.min:c-w*(this.padMin-1),u=null!=this.max?this.max:d+w*(this.padMax-1),w=u-t,null==this.numberTicks&&(null!=this.tickInterval?this.numberTicks=Math.ceil((u-t)/this.tickInterval)+1:k>100?this.numberTicks=parseInt(3+(k-100)/75,10):this.numberTicks=2),null==this.tickInterval&&(this.tickInterval=w/(this.numberTicks-1)),null==this.max&&(u=t+this.tickInterval*(this.numberTicks-1)),null==this.min&&(t=u-this.tickInterval*(this.numberTicks-1));var R,S=a.jqplot.getSignificantFigures(this.tickInterval);if(S.digitsLeft>=S.significantDigits)R="%d";else{var v=Math.max(0,5-S.digitsLeft);v=Math.min(v,S.digitsRight),R="%."+v+"f"}this._autoFormatString=R,this.min=t,this.max=u}if(this.renderer.constructor==a.jqplot.LinearAxisRenderer&&""==this._autoFormatString){w=this.max-this.min;var T=new this.tickRenderer(this.tickOptions),U=T.formatString||a.jqplot.config.defaultTickFormatString,U=U.match(a.jqplot.sprintf.regex)[0],V=0;if(U){if(U.search(/[fFeEgGpP]/)>-1){var W=U.match(/\%\.(\d{0,})?[eEfFgGpP]/);V=W?parseInt(W[1],10):6}else U.search(/[di]/)>-1&&(V=0);var X=Math.pow(10,-V);if(this.tickInterval<X&&null==n&&null==o)if(this.tickInterval=X,null==m&&null==l){this.min=Math.floor(this._dataBounds.min/X)*X,this.min==this._dataBounds.min&&(this.min=this._dataBounds.min-this.tickInterval),this.max=Math.ceil(this._dataBounds.max/X)*X,this.max==this._dataBounds.max&&(this.max=this._dataBounds.max+this.tickInterval);var Y=(this.max-this.min)/this.tickInterval;Y=Y.toFixed(11),Y=Math.ceil(Y),this.numberTicks=Y+1}else if(null==m){var Y=(this._dataBounds.max-this.min)/this.tickInterval;Y=Y.toFixed(11),this.numberTicks=Math.ceil(Y)+2,this.max=this.min+this.tickInterval*(this.numberTicks-1)}else if(null==l){var Y=(this.max-this._dataBounds.min)/this.tickInterval;Y=Y.toFixed(11),this.numberTicks=Math.ceil(Y)+2,this.min=this.max-this.tickInterval*(this.numberTicks-1)}else this.numberTicks=Math.ceil((m-l)/this.tickInterval)+1,this.min=Math.floor(l*Math.pow(10,V))/Math.pow(10,V),this.max=Math.ceil(m*Math.pow(10,V))/Math.pow(10,V),this.numberTicks=Math.ceil((this.max-this.min)/this.tickInterval)+1}}}this._overrideFormatString&&""!=this._autoFormatString&&(this.tickOptions=this.tickOptions||{},this.tickOptions.formatString=this._autoFormatString);for(var r,Z,f=0;f<this.numberTicks;f++){if(e=this.min+f*this.tickInterval,r=new this.tickRenderer(this.tickOptions),r.setTick(e,this.name),this._ticks.push(r),f<this.numberTicks-1)for(var N=0;N<this.minorTicks;N++)e+=this.tickInterval/(this.minorTicks+1),Z=a.extend(!0,{},this.tickOptions,{name:this.name,value:e,label:"",isMinorTick:!0}),r=new this.tickRenderer(Z),this._ticks.push(r);r=null}}this.tickInset&&(this.min=this.min-this.tickInset*this.tickInterval,this.max=this.max+this.tickInset*this.tickInterval),g=null},a.jqplot.LinearAxisRenderer.prototype.resetTickValues=function(b){if(a.isArray(b)&&b.length==this._ticks.length){for(var c,d=0;d<b.length;d++)c=this._ticks[d],c.value=b[d],c.label=c.formatter(c.formatString,b[d]),c.label=c.prefix+c.label,c._elem.html(c.label);c=null,this.min=a.jqplot.arrayMin(b),this.max=a.jqplot.arrayMax(b),this.pack()}},a.jqplot.LinearAxisRenderer.prototype.pack=function(b,c){b=b||{},c=c||this._offsets;var d=this._ticks,e=this.max,f=this.min,g=c.max,h=c.min,i=null==this._label?!1:this._label.show;for(var j in b)this._elem.css(j,b[j]);this._offsets=c;var k=g-h,l=e-f;if(this.breakPoints?(l=l-this.breakPoints[1]+this.breakPoints[0],this.p2u=function(a){return(a-h)*l/k+f},this.u2p=function(a){return a>this.breakPoints[0]&&a<this.breakPoints[1]&&(a=this.breakPoints[0]),a<=this.breakPoints[0]?(a-f)*k/l+h:(a-this.breakPoints[1]+this.breakPoints[0]-f)*k/l+h},"x"==this.name.charAt(0)?(this.series_u2p=function(a){return a>this.breakPoints[0]&&a<this.breakPoints[1]&&(a=this.breakPoints[0]),a<=this.breakPoints[0]?(a-f)*k/l:(a-this.breakPoints[1]+this.breakPoints[0]-f)*k/l},this.series_p2u=function(a){return a*l/k+f}):(this.series_u2p=function(a){return a>this.breakPoints[0]&&a<this.breakPoints[1]&&(a=this.breakPoints[0]),a>=this.breakPoints[1]?(a-e)*k/l:(a+this.breakPoints[1]-this.breakPoints[0]-e)*k/l},this.series_p2u=function(a){return a*l/k+e})):(this.p2u=function(a){return(a-h)*l/k+f},this.u2p=function(a){return(a-f)*k/l+h},"xaxis"==this.name||"x2axis"==this.name?(this.series_u2p=function(a){return(a-f)*k/l},this.series_p2u=function(a){return a*l/k+f}):(this.series_u2p=function(a){return(a-e)*k/l},this.series_p2u=function(a){return a*l/k+e})),this.show)if("xaxis"==this.name||"x2axis"==this.name){for(var m=0;m<d.length;m++){var n=d[m];if(n.show&&n.showLabel){var o;if(n.constructor==a.jqplot.CanvasAxisTickRenderer&&n.angle){var p="xaxis"==this.name?1:-1;switch(n.labelPosition){case"auto":o=p*n.angle<0?-n.getWidth()+n._textRenderer.height*Math.sin(-n._textRenderer.angle)/2:-n._textRenderer.height*Math.sin(n._textRenderer.angle)/2;break;case"end":o=-n.getWidth()+n._textRenderer.height*Math.sin(-n._textRenderer.angle)/2;break;case"start":o=-n._textRenderer.height*Math.sin(n._textRenderer.angle)/2;break;case"middle":o=-n.getWidth()/2+n._textRenderer.height*Math.sin(-n._textRenderer.angle)/2;break;default:o=-n.getWidth()/2+n._textRenderer.height*Math.sin(-n._textRenderer.angle)/2}}else o=-n.getWidth()/2;var q=this.u2p(n.value)+o+"px";n._elem.css("left",q),n.pack()}}if(i){var r=this._label._elem.outerWidth(!0);this._label._elem.css("left",h+k/2-r/2+"px"),"xaxis"==this.name?this._label._elem.css("bottom","0px"):this._label._elem.css("top","0px"),this._label.pack()}}else{for(var m=0;m<d.length;m++){var n=d[m];if(n.show&&n.showLabel){var o;if(n.constructor==a.jqplot.CanvasAxisTickRenderer&&n.angle){var p="yaxis"==this.name?1:-1;switch(n.labelPosition){case"auto":case"end":o=p*n.angle<0?-n._textRenderer.height*Math.cos(-n._textRenderer.angle)/2:-n.getHeight()+n._textRenderer.height*Math.cos(n._textRenderer.angle)/2;break;case"start":o=n.angle>0?-n._textRenderer.height*Math.cos(-n._textRenderer.angle)/2:-n.getHeight()+n._textRenderer.height*Math.cos(n._textRenderer.angle)/2;break;case"middle":o=-n.getHeight()/2;break;default:o=-n.getHeight()/2}}else o=-n.getHeight()/2;var q=this.u2p(n.value)+o+"px";n._elem.css("top",q),n.pack()}}if(i){var s=this._label._elem.outerHeight(!0);this._label._elem.css("top",g-k/2-s/2+"px"),"yaxis"==this.name?this._label._elem.css("left","0px"):this._label._elem.css("right","0px"),this._label.pack()}}d=null};a.jqplot.LinearTickGenerator=function(b,c,d,e,f,g){if(f=null===f?!1:f,g=null===g||f?!1:g,b===c&&(c=c?0:1),d=d||1,b>c){var h=c;c=b,b=h}var i=[],j=x(c-b,d),k=a.jqplot.getSignificantFigures;if(null==e)if(f||g){if(f){i[0]=b,i[2]=Math.ceil((c-b)/j+1),i[1]=b+(i[2]-1)*j;var l=k(b).digitsRight,m=k(j).digitsRight;m>l?i[3]=u(j):i[3]="%."+l+"f",i[4]=j}else if(g){i[1]=c,i[2]=Math.ceil((c-b)/j+1),i[0]=c-(i[2]-1)*j;var n=k(c).digitsRight,m=k(j).digitsRight;m>n?i[3]=u(j):i[3]="%."+n+"f",i[4]=j}}else i[0]=Math.floor(b/j)*j,i[1]=Math.ceil(c/j)*j,i[2]=Math.round((i[1]-i[0])/j+1),i[3]=u(j),i[4]=j;else{var o=[];if(o[0]=Math.floor(b/j)*j,o[1]=Math.ceil(c/j)*j,o[2]=Math.round((o[1]-o[0])/j+1),o[3]=u(j),o[4]=j,o[2]===e)i=o;else{var p=w(o[1]-o[0],e);i[0]=o[0],i[2]=e,i[4]=p,i[3]=u(p),i[1]=i[0]+(i[2]-1)*i[4]}}return i},a.jqplot.LinearTickGenerator.bestLinearInterval=x,a.jqplot.LinearTickGenerator.bestInterval=w,a.jqplot.LinearTickGenerator.bestLinearComponents=y,a.jqplot.LinearTickGenerator.bestConstrainedInterval=v,a.jqplot.MarkerRenderer=function(b){this.show=!0,this.style="filledCircle",this.lineWidth=2,this.size=9,this.color="#666666",this.shadow=!0,this.shadowAngle=45,this.shadowOffset=1,this.shadowDepth=3,this.shadowAlpha="0.07",this.shadowRenderer=new a.jqplot.ShadowRenderer,this.shapeRenderer=new a.jqplot.ShapeRenderer,a.extend(!0,this,b)},a.jqplot.MarkerRenderer.prototype.init=function(b){a.extend(!0,this,b);var c={angle:this.shadowAngle,offset:this.shadowOffset,alpha:this.shadowAlpha,lineWidth:this.lineWidth,depth:this.shadowDepth,closePath:!0};-1!=this.style.indexOf("filled")&&(c.fill=!0),-1!=this.style.indexOf("ircle")&&(c.isarc=!0,c.closePath=!1),this.shadowRenderer.init(c);var d={fill:!1,isarc:!1,strokeStyle:this.color,fillStyle:this.color,lineWidth:this.lineWidth,closePath:!0};-1!=this.style.indexOf("filled")&&(d.fill=!0),-1!=this.style.indexOf("ircle")&&(d.isarc=!0,d.closePath=!1),this.shapeRenderer.init(d)},a.jqplot.MarkerRenderer.prototype.drawDiamond=function(a,b,c,d,e){var f=1.2,g=this.size/2/f,h=this.size/2*f,i=[[a-g,b],[a,b+h],[a+g,b],[a,b-h]];this.shadow&&this.shadowRenderer.draw(c,i),this.shapeRenderer.draw(c,i,e)},a.jqplot.MarkerRenderer.prototype.drawPlus=function(b,c,d,e,f){var g=1,h=this.size/2*g,i=this.size/2*g,j=[[b,c-i],[b,c+i]],k=[[b+h,c],[b-h,c]],l=a.extend(!0,{},this.options,{closePath:!1});this.shadow&&(this.shadowRenderer.draw(d,j,{closePath:!1}),this.shadowRenderer.draw(d,k,{closePath:!1})),this.shapeRenderer.draw(d,j,l),this.shapeRenderer.draw(d,k,l)},a.jqplot.MarkerRenderer.prototype.drawX=function(b,c,d,e,f){var g=1,h=this.size/2*g,i=this.size/2*g,j=a.extend(!0,{},this.options,{closePath:!1}),k=[[b-h,c-i],[b+h,c+i]],l=[[b-h,c+i],[b+h,c-i]];this.shadow&&(this.shadowRenderer.draw(d,k,{closePath:!1}),this.shadowRenderer.draw(d,l,{closePath:!1})),this.shapeRenderer.draw(d,k,j),this.shapeRenderer.draw(d,l,j)},a.jqplot.MarkerRenderer.prototype.drawDash=function(a,b,c,d,e){var f=1,g=this.size/2*f,h=(this.size/2*f,[[a-g,b],[a+g,b]]);this.shadow&&this.shadowRenderer.draw(c,h),this.shapeRenderer.draw(c,h,e)},a.jqplot.MarkerRenderer.prototype.drawLine=function(a,b,c,d,e){var f=[a,b];this.shadow&&this.shadowRenderer.draw(c,f),this.shapeRenderer.draw(c,f,e)},a.jqplot.MarkerRenderer.prototype.drawSquare=function(a,b,c,d,e){var f=1,g=this.size/2/f,h=this.size/2*f,i=[[a-g,b-h],[a-g,b+h],[a+g,b+h],[a+g,b-h]];this.shadow&&this.shadowRenderer.draw(c,i),this.shapeRenderer.draw(c,i,e)},a.jqplot.MarkerRenderer.prototype.drawCircle=function(a,b,c,d,e){var f=this.size/2,g=2*Math.PI,h=[a,b,f,0,g,!0];this.shadow&&this.shadowRenderer.draw(c,h),this.shapeRenderer.draw(c,h,e)},a.jqplot.MarkerRenderer.prototype.draw=function(a,b,c,d){if(d=d||{},null==d.show||0!=d.show)switch(d.color&&!d.fillStyle&&(d.fillStyle=d.color),d.color&&!d.strokeStyle&&(d.strokeStyle=d.color),this.style){case"diamond":this.drawDiamond(a,b,c,!1,d);break;case"filledDiamond":this.drawDiamond(a,b,c,!0,d);break;case"circle":this.drawCircle(a,b,c,!1,d);break;case"filledCircle":this.drawCircle(a,b,c,!0,d);break;case"square":this.drawSquare(a,b,c,!1,d);break;case"filledSquare":this.drawSquare(a,b,c,!0,d);break;case"x":this.drawX(a,b,c,!0,d);break;case"plus":this.drawPlus(a,b,c,!0,d);break;case"dash":this.drawDash(a,b,c,!0,d);break;case"line":this.drawLine(a,b,c,!1,d);break;default:this.drawDiamond(a,b,c,!1,d)}},a.jqplot.ShadowRenderer=function(b){this.angle=45,this.offset=1,this.alpha=.07,this.lineWidth=1.5,this.lineJoin="miter",this.lineCap="round",this.closePath=!1,this.fill=!1,this.depth=3,this.strokeStyle="rgba(0,0,0,0.1)",this.isarc=!1,a.extend(!0,this,b)},a.jqplot.ShadowRenderer.prototype.init=function(b){a.extend(!0,this,b)},a.jqplot.ShadowRenderer.prototype.draw=function(b,c,d){b.save();var e=null!=d?d:{},f=null!=e.fill?e.fill:this.fill,g=null!=e.fillRect?e.fillRect:this.fillRect,h=null!=e.closePath?e.closePath:this.closePath,i=null!=e.offset?e.offset:this.offset,j=null!=e.alpha?e.alpha:this.alpha,k=null!=e.depth?e.depth:this.depth,l=null!=e.isarc?e.isarc:this.isarc,m=null!=e.linePattern?e.linePattern:this.linePattern;b.lineWidth=null!=e.lineWidth?e.lineWidth:this.lineWidth,b.lineJoin=null!=e.lineJoin?e.lineJoin:this.lineJoin,b.lineCap=null!=e.lineCap?e.lineCap:this.lineCap,b.strokeStyle=e.strokeStyle||this.strokeStyle||"rgba(0,0,0,"+j+")",b.fillStyle=e.fillStyle||this.fillStyle||"rgba(0,0,0,"+j+")";for(var n=0;k>n;n++){var o=a.jqplot.LinePattern(b,m);if(b.translate(Math.cos(this.angle*Math.PI/180)*i,Math.sin(this.angle*Math.PI/180)*i),o.beginPath(),l)b.arc(c[0],c[1],c[2],c[3],c[4],!0);else if(g)g&&b.fillRect(c[0],c[1],c[2],c[3]);else if(c&&c.length)for(var p=!0,q=0;q<c.length;q++)null!=c[q][0]&&null!=c[q][1]?p?(o.moveTo(c[q][0],c[q][1]),p=!1):o.lineTo(c[q][0],c[q][1]):p=!0;h&&o.closePath(),f?b.fill():b.stroke()}b.restore()},a.jqplot.ShapeRenderer=function(b){this.lineWidth=1.5,this.linePattern="solid",this.lineJoin="miter",this.lineCap="round",this.closePath=!1,this.fill=!1,this.isarc=!1,this.fillRect=!1,this.strokeRect=!1,this.clearRect=!1,this.strokeStyle="#999999",this.fillStyle="#999999",a.extend(!0,this,b)},a.jqplot.ShapeRenderer.prototype.init=function(b){a.extend(!0,this,b)},a.jqplot.ShapeRenderer.prototype.draw=function(b,c,d){b.save();var e=null!=d?d:{},f=null!=e.fill?e.fill:this.fill,g=null!=e.closePath?e.closePath:this.closePath,h=null!=e.fillRect?e.fillRect:this.fillRect,i=null!=e.strokeRect?e.strokeRect:this.strokeRect,j=null!=e.clearRect?e.clearRect:this.clearRect,k=null!=e.isarc?e.isarc:this.isarc,l=null!=e.linePattern?e.linePattern:this.linePattern,m=a.jqplot.LinePattern(b,l);if(b.lineWidth=e.lineWidth||this.lineWidth,b.lineJoin=e.lineJoin||this.lineJoin,b.lineCap=e.lineCap||this.lineCap,b.strokeStyle=e.strokeStyle||e.color||this.strokeStyle,b.fillStyle=e.fillStyle||this.fillStyle,b.beginPath(),k)return b.arc(c[0],c[1],c[2],c[3],c[4],!0),g&&b.closePath(),f?b.fill():b.stroke(),void b.restore();if(j)return b.clearRect(c[0],c[1],c[2],c[3]),void b.restore();if(h||i){if(h&&b.fillRect(c[0],c[1],c[2],c[3]),i)return b.strokeRect(c[0],c[1],c[2],c[3]),void b.restore()}else if(c&&c.length){for(var n=!0,o=0;o<c.length;o++)null!=c[o][0]&&null!=c[o][1]?n?(m.moveTo(c[o][0],c[o][1]),n=!1):m.lineTo(c[o][0],c[o][1]):n=!0;g&&m.closePath(),f?b.fill():b.stroke()}b.restore()},a.jqplot.TableLegendRenderer=function(){},a.jqplot.TableLegendRenderer.prototype.init=function(b){a.extend(!0,this,b)},a.jqplot.TableLegendRenderer.prototype.addrow=function(b,c,d,e){var f,g,h,i,j,k=d?this.rowSpacing+"px":"0px";h=document.createElement("tr"),f=a(h),f.addClass("jqplot-table-legend"),h=null,e?f.prependTo(this._elem):f.appendTo(this._elem),this.showSwatches&&(g=a(document.createElement("td")),g.addClass("jqplot-table-legend jqplot-table-legend-swatch"),g.css({textAlign:"center",paddingTop:k}),i=a(document.createElement("div")),i.addClass("jqplot-table-legend-swatch-outline"),j=a(document.createElement("div")),j.addClass("jqplot-table-legend-swatch"),j.css({backgroundColor:c,borderColor:c}),f.append(g.append(i.append(j)))),this.showLabels&&(g=a(document.createElement("td")),g.addClass("jqplot-table-legend jqplot-table-legend-label"),g.css("paddingTop",k),f.append(g),this.escapeHtml?g.text(b):g.html(b)),g=null,i=null,j=null,f=null,h=null},a.jqplot.TableLegendRenderer.prototype.draw=function(){if(this._elem&&(this._elem.emptyForce(),this._elem=null),this.show){var b=this._series,c=document.createElement("table");this._elem=a(c),this._elem.addClass("jqplot-table-legend");var d={position:"absolute"};this.background&&(d.background=this.background),this.border&&(d.border=this.border),this.fontSize&&(d.fontSize=this.fontSize),this.fontFamily&&(d.fontFamily=this.fontFamily),this.textColor&&(d.textColor=this.textColor),null!=this.marginTop&&(d.marginTop=this.marginTop),null!=this.marginBottom&&(d.marginBottom=this.marginBottom),null!=this.marginLeft&&(d.marginLeft=this.marginLeft),null!=this.marginRight&&(d.marginRight=this.marginRight);for(var e,f=!1,g=!1,h=0;h<b.length;h++)if(e=b[h],(e._stack||e.renderer.constructor==a.jqplot.BezierCurveRenderer)&&(g=!0),e.show&&e.showLabel){var i=this.labels[h]||e.label.toString();if(i){var j=e.color;g&&h<b.length-1?f=!0:g&&h==b.length-1&&(f=!1),this.renderer.addrow.call(this,i,j,f,g),f=!0}for(var k=0;k<a.jqplot.addLegendRowHooks.length;k++){var l=a.jqplot.addLegendRowHooks[k].call(this,e);l&&(this.renderer.addrow.call(this,l.label,l.color,f),f=!0)}i=null}}return this._elem},a.jqplot.TableLegendRenderer.prototype.pack=function(a){if(this.show)if("insideGrid"==this.placement)switch(this.location){case"nw":var b=a.left,c=a.top;this._elem.css("left",b),this._elem.css("top",c);break;case"n":var b=(a.left+(this._plotDimensions.width-a.right))/2-this.getWidth()/2,c=a.top;this._elem.css("left",b),this._elem.css("top",c);break;case"ne":var b=a.right,c=a.top;this._elem.css({right:b,top:c});break;case"e":var b=a.right,c=(a.top+(this._plotDimensions.height-a.bottom))/2-this.getHeight()/2;this._elem.css({right:b,top:c});break;case"se":var b=a.right,c=a.bottom;this._elem.css({right:b,bottom:c});break;case"s":var b=(a.left+(this._plotDimensions.width-a.right))/2-this.getWidth()/2,c=a.bottom;this._elem.css({left:b,bottom:c});break;case"sw":var b=a.left,c=a.bottom;this._elem.css({left:b,bottom:c});break;case"w":var b=a.left,c=(a.top+(this._plotDimensions.height-a.bottom))/2-this.getHeight()/2;this._elem.css({left:b,top:c});break;default:var b=a.right,c=a.bottom;this._elem.css({right:b,bottom:c})}else if("outside"==this.placement)switch(this.location){case"nw":var b=this._plotDimensions.width-a.left,c=a.top;this._elem.css("right",b),this._elem.css("top",c);break;case"n":var b=(a.left+(this._plotDimensions.width-a.right))/2-this.getWidth()/2,c=this._plotDimensions.height-a.top;this._elem.css("left",b),this._elem.css("bottom",c);break;case"ne":var b=this._plotDimensions.width-a.right,c=a.top;this._elem.css({left:b,top:c});break;case"e":var b=this._plotDimensions.width-a.right,c=(a.top+(this._plotDimensions.height-a.bottom))/2-this.getHeight()/2;this._elem.css({left:b,top:c});break;case"se":var b=this._plotDimensions.width-a.right,c=a.bottom;this._elem.css({left:b,bottom:c});break;case"s":var b=(a.left+(this._plotDimensions.width-a.right))/2-this.getWidth()/2,c=this._plotDimensions.height-a.bottom;this._elem.css({left:b,top:c});break;case"sw":var b=this._plotDimensions.width-a.left,c=a.bottom;this._elem.css({right:b,bottom:c});break;case"w":var b=this._plotDimensions.width-a.left,c=(a.top+(this._plotDimensions.height-a.bottom))/2-this.getHeight()/2;this._elem.css({right:b,top:c});break;default:var b=a.right,c=a.bottom;this._elem.css({right:b,bottom:c})}else switch(this.location){case"nw":this._elem.css({left:0,top:a.top});break;case"n":var b=(a.left+(this._plotDimensions.width-a.right))/2-this.getWidth()/2;this._elem.css({left:b,top:a.top});break;case"ne":this._elem.css({right:0,top:a.top});break;case"e":var c=(a.top+(this._plotDimensions.height-a.bottom))/2-this.getHeight()/2;this._elem.css({right:a.right,top:c});break;case"se":this._elem.css({right:a.right,bottom:a.bottom});break;case"s":var b=(a.left+(this._plotDimensions.width-a.right))/2-this.getWidth()/2;this._elem.css({left:b,bottom:a.bottom});break;case"sw":this._elem.css({left:a.left,bottom:a.bottom});break;case"w":var c=(a.top+(this._plotDimensions.height-a.bottom))/2-this.getHeight()/2;this._elem.css({left:a.left,top:c});break;default:this._elem.css({right:a.right,bottom:a.bottom})}},a.jqplot.ThemeEngine=function(){this.themes={},this.activeTheme=null},a.jqplot.ThemeEngine.prototype.init=function(){var b,c,d,e=new a.jqplot.Theme({_name:"Default"});for(b in e.target)"textColor"==b?e.target[b]=this.target.css("color"):e.target[b]=this.target.css(b);if(this.title.show&&this.title._elem)for(b in e.title)"textColor"==b?e.title[b]=this.title._elem.css("color"):e.title[b]=this.title._elem.css(b);for(b in e.grid)e.grid[b]=this.grid[b];if(null==e.grid.backgroundColor&&null!=this.grid.background&&(e.grid.backgroundColor=this.grid.background),this.legend.show&&this.legend._elem)for(b in e.legend)"textColor"==b?e.legend[b]=this.legend._elem.css("color"):e.legend[b]=this.legend._elem.css(b);var f;for(c=0;c<this.series.length;c++){f=this.series[c],f.renderer.constructor==a.jqplot.LineRenderer?e.series.push(new L):f.renderer.constructor==a.jqplot.BarRenderer?e.series.push(new N):f.renderer.constructor==a.jqplot.PieRenderer?e.series.push(new O):f.renderer.constructor==a.jqplot.DonutRenderer?e.series.push(new P):f.renderer.constructor==a.jqplot.FunnelRenderer?e.series.push(new Q):f.renderer.constructor==a.jqplot.MeterGaugeRenderer?e.series.push(new R):e.series.push({});for(b in e.series[c])e.series[c][b]=f[b]}var g,h;for(b in this.axes){if(h=this.axes[b],g=e.axes[b]=new I,g.borderColor=h.borderColor,g.borderWidth=h.borderWidth,h._ticks&&h._ticks[0])for(d in g.ticks)h._ticks[0].hasOwnProperty(d)?g.ticks[d]=h._ticks[0][d]:h._ticks[0]._elem&&(g.ticks[d]=h._ticks[0]._elem.css(d));if(h._label&&h._label.show)for(d in g.label)h._label[d]?g.label[d]=h._label[d]:h._label._elem&&("textColor"==d?g.label[d]=h._label._elem.css("color"):g.label[d]=h._label._elem.css(d))}this.themeEngine._add(e),this.themeEngine.activeTheme=this.themeEngine.themes[e._name]},a.jqplot.ThemeEngine.prototype.get=function(a){return a?this.themes[a]:this.activeTheme},a.jqplot.ThemeEngine.prototype.getThemeNames=function(){var a=[];for(var b in this.themes)a.push(b);return a.sort(z)},a.jqplot.ThemeEngine.prototype.getThemes=function(){var a=[],b=[];for(var c in this.themes)a.push(c);a.sort(z);for(var d=0;d<a.length;d++)b.push(this.themes[a[d]]);return b},a.jqplot.ThemeEngine.prototype.activate=function(b,c){var d=!1;if(!c&&this.activeTheme&&this.activeTheme._name&&(c=this.activeTheme._name),!this.themes.hasOwnProperty(c))throw new Error("No theme of that name");var e=this.themes[c];this.activeTheme=e;var f,g=["xaxis","x2axis","yaxis","y2axis"];for(p=0;p<g.length;p++){var h=g[p];null!=e.axesStyles.borderColor&&(b.axes[h].borderColor=e.axesStyles.borderColor),null!=e.axesStyles.borderWidth&&(b.axes[h].borderWidth=e.axesStyles.borderWidth)}for(var i in b.axes){var j=b.axes[i];if(j.show){var k=e.axes[i]||{},l=e.axesStyles,m=a.jqplot.extend(!0,{},k,l);if(f=null!=e.axesStyles.borderColor?e.axesStyles.borderColor:m.borderColor,null!=m.borderColor&&(j.borderColor=m.borderColor,d=!0),f=null!=e.axesStyles.borderWidth?e.axesStyles.borderWidth:m.borderWidth,null!=m.borderWidth&&(j.borderWidth=m.borderWidth,d=!0),j._ticks&&j._ticks[0])for(var n in m.ticks)f=m.ticks[n],null!=f&&(j.tickOptions[n]=f,j._ticks=[],d=!0);if(j._label&&j._label.show)for(var n in m.label)f=m.label[n],null!=f&&(j.labelOptions[n]=f,d=!0)}}for(var o in e.grid)null!=e.grid[o]&&(b.grid[o]=e.grid[o]);if(d||b.grid.draw(),b.legend.show)for(o in e.legend)null!=e.legend[o]&&(b.legend[o]=e.legend[o]);if(b.title.show)for(o in e.title)null!=e.title[o]&&(b.title[o]=e.title[o]);var p;for(p=0;p<e.series.length;p++){var q={};for(o in e.series[p])f=null!=e.seriesStyles[o]?e.seriesStyles[o]:e.series[p][o],null!=f&&(q[o]=f,"color"==o?(b.series[p].renderer.shapeRenderer.fillStyle=f,b.series[p].renderer.shapeRenderer.strokeStyle=f,b.series[p][o]=f):"lineWidth"==o||"linePattern"==o?(b.series[p].renderer.shapeRenderer[o]=f,b.series[p][o]=f):"markerOptions"==o?(B(b.series[p].markerOptions,f),B(b.series[p].markerRenderer,f)):b.series[p][o]=f,d=!0)}d&&(b.target.empty(),b.draw());for(o in e.target)null!=e.target[o]&&b.target.css(o,e.target[o])},a.jqplot.ThemeEngine.prototype._add=function(a,b){if(b&&(a._name=b),a._name||(a._name=Date.parse(new Date)),this.themes.hasOwnProperty(a._name))throw new Error("jqplot.ThemeEngine Error: Theme already in use");this.themes[a._name]=a},a.jqplot.ThemeEngine.prototype.remove=function(a){return"Default"==a?!1:delete this.themes[a]},a.jqplot.ThemeEngine.prototype.newTheme=function(b,c){"object"==typeof b&&(c=c||b,b=null),b=c&&c._name?c._name:b||Date.parse(new Date);var d=this.copy(this.themes.Default._name,b);return a.jqplot.extend(d,c),d},a.jqplot.clone=A,a.jqplot.merge=B,a.jqplot.extend=function(){var b,c=arguments[0]||{},d=1,e=arguments.length,f=!1;for("boolean"==typeof c&&(f=c,c=arguments[1]||{},d=2),"object"!=typeof c&&"[object Function]"===!toString.call(c)&&(c={});e>d;d++)if(null!=(b=arguments[d]))for(var g in b){var h=c[g],i=b[g];c!==i&&(f&&i&&"object"==typeof i&&!i.nodeType?c[g]=a.jqplot.extend(f,h||(null!=i.length?[]:{}),i):i!==F&&(c[g]=i))}return c},a.jqplot.ThemeEngine.prototype.rename=function(a,b){if("Default"==a||"Default"==b)throw new Error("jqplot.ThemeEngine Error: Cannot rename from/to Default");if(this.themes.hasOwnProperty(b))throw new Error("jqplot.ThemeEngine Error: New name already in use.");if(this.themes.hasOwnProperty(a)){var c=this.copy(a,b);return this.remove(a),c}throw new Error("jqplot.ThemeEngine Error: Old name or new name invalid")},a.jqplot.ThemeEngine.prototype.copy=function(b,c,d){if("Default"==c)throw new Error("jqplot.ThemeEngine Error: Cannot copy over Default theme");if(!this.themes.hasOwnProperty(b)){var e="jqplot.ThemeEngine Error: Source name invalid";throw new Error(e)}if(this.themes.hasOwnProperty(c)){var e="jqplot.ThemeEngine Error: Target name invalid";throw new Error(e)}var f=A(this.themes[b]);return f._name=c,a.jqplot.extend(!0,f,d),this._add(f),f},a.jqplot.Theme=function(b,c){"object"==typeof b&&(c=c||b,b=null),b=b||Date.parse(new Date),this._name=b,this.target={backgroundColor:null},this.legend={textColor:null,fontFamily:null,fontSize:null,border:null,background:null},this.title={textColor:null,fontFamily:null,fontSize:null,textAlign:null},this.seriesStyles={},this.series=[],this.grid={drawGridlines:null,gridLineColor:null,gridLineWidth:null,backgroundColor:null,borderColor:null,borderWidth:null,shadow:null},this.axesStyles={label:{},ticks:{}},this.axes={},"string"==typeof c?this._name=c:"object"==typeof c&&a.jqplot.extend(!0,this,c)};var I=function(){this.borderColor=null,this.borderWidth=null,this.ticks=new J,this.label=new K},J=function(){this.show=null,this.showGridline=null,this.showLabel=null,this.showMark=null,this.size=null,this.textColor=null,this.whiteSpace=null,this.fontSize=null,this.fontFamily=null},K=function(){this.textColor=null,this.whiteSpace=null,this.fontSize=null,
8
+ this.fontFamily=null,this.fontWeight=null},L=function(){this.color=null,this.lineWidth=null,this.linePattern=null,this.shadow=null,this.fillColor=null,this.showMarker=null,this.markerOptions=new M},M=function(){this.show=null,this.style=null,this.lineWidth=null,this.size=null,this.color=null,this.shadow=null},N=function(){this.color=null,this.seriesColors=null,this.lineWidth=null,this.shadow=null,this.barPadding=null,this.barMargin=null,this.barWidth=null,this.highlightColors=null},O=function(){this.seriesColors=null,this.padding=null,this.sliceMargin=null,this.fill=null,this.shadow=null,this.startAngle=null,this.lineWidth=null,this.highlightColors=null},P=function(){this.seriesColors=null,this.padding=null,this.sliceMargin=null,this.fill=null,this.shadow=null,this.startAngle=null,this.lineWidth=null,this.innerDiameter=null,this.thickness=null,this.ringMargin=null,this.highlightColors=null},Q=function(){this.color=null,this.lineWidth=null,this.shadow=null,this.padding=null,this.sectionMargin=null,this.seriesColors=null,this.highlightColors=null},R=function(){this.padding=null,this.backgroundColor=null,this.ringColor=null,this.tickColor=null,this.ringWidth=null,this.intervalColors=null,this.intervalInnerRadius=null,this.intervalOuterRadius=null,this.hubRadius=null,this.needleThickness=null,this.needlePad=null};a.fn.jqplotChildText=function(){return a(this).contents().filter(function(){return 3==this.nodeType}).text()},a.fn.jqplotGetComputedFontStyle=function(){for(var a=window.getComputedStyle?window.getComputedStyle(this[0],""):this[0].currentStyle,b=a["font-style"]?["font-style","font-weight","font-size","font-family"]:["fontStyle","fontWeight","fontSize","fontFamily"],c=[],d=0;d<b.length;++d){var e=String(a[b[d]]);e&&"normal"!=e&&c.push(e)}return c.join(" ")},a.fn.jqplotToImageCanvas=function(b){function c(b){var c=parseInt(a(b).css("line-height"),10);return isNaN(c)&&(c=1.2*parseInt(a(b).css("font-size"),10)),c}function d(b,d,e,f,g,h){for(var i=c(b),j=a(b).innerWidth(),k=(a(b).innerHeight(),e.split(/\s+/)),l=k.length,m="",n=[],o=g,p=f,q=0;l>q;q++)m+=k[q],d.measureText(m).width>j&&m.length>k[q].length&&(n.push(q),m="",q--);if(0===n.length)"center"===a(b).css("textAlign")&&(p=f+(h-d.measureText(m).width)/2-s),d.fillText(e,p,g);else{m=k.slice(0,n[0]).join(" "),"center"===a(b).css("textAlign")&&(p=f+(h-d.measureText(m).width)/2-s),d.fillText(m,p,o),o+=i;for(var q=1,r=n.length;r>q;q++)m=k.slice(n[q-1],n[q]).join(" "),"center"===a(b).css("textAlign")&&(p=f+(h-d.measureText(m).width)/2-s),d.fillText(m,p,o),o+=i;m=k.slice(n[q-1],k.length).join(" "),"center"===a(b).css("textAlign")&&(p=f+(h-d.measureText(m).width)/2-s),d.fillText(m,p,o)}}function e(b,c,f){var g=b.tagName.toLowerCase(),h=a(b).position(),i=window.getComputedStyle?window.getComputedStyle(b,""):b.currentStyle,j=c+h.left+parseInt(i.marginLeft,10)+parseInt(i.borderLeftWidth,10)+parseInt(i.paddingLeft,10),k=f+h.top+parseInt(i.marginTop,10)+parseInt(i.borderTopWidth,10)+parseInt(i.paddingTop,10),l=m.width;if("div"!=g&&"span"!=g||a(b).hasClass("jqplot-highlighter-tooltip"))if("table"===g&&a(b).hasClass("jqplot-table-legend")){w.strokeStyle=a(b).css("border-top-color"),w.fillStyle=a(b).css("background-color"),w.fillRect(j,k,a(b).innerWidth(),a(b).innerHeight()),parseInt(a(b).css("border-top-width"),10)>0&&w.strokeRect(j,k,a(b).innerWidth(),a(b).innerHeight()),a(b).find("div.jqplot-table-legend-swatch-outline").each(function(){var b=a(this);w.strokeStyle=b.css("border-top-color");var c=j+b.position().left,d=k+b.position().top;w.strokeRect(c,d,b.innerWidth(),b.innerHeight()),c+=parseInt(b.css("padding-left"),10),d+=parseInt(b.css("padding-top"),10);var e=b.innerHeight()-2*parseInt(b.css("padding-top"),10),f=b.innerWidth()-2*parseInt(b.css("padding-left"),10),g=b.children("div.jqplot-table-legend-swatch");w.fillStyle=g.css("background-color"),w.fillRect(c,d,f,e)}),a(b).find("td.jqplot-table-legend-label").each(function(){var b=a(this),c=j+b.position().left,e=k+b.position().top+parseInt(b.css("padding-top"),10);w.font=b.jqplotGetComputedFontStyle(),w.fillStyle=b.css("color"),d(b,w,b.text(),c,e,l)})}else"canvas"==g&&w.drawImage(b,j,k);else{a(b).children().each(function(){e(this,j,k)});var n=a(b).jqplotChildText();n&&(w.font=a(b).jqplotGetComputedFontStyle(),w.fillStyle=a(b).css("color"),d(b,w,n,j,k,l))}}b=b||{};var f=null==b.x_offset?0:b.x_offset,g=null==b.y_offset?0:b.y_offset,h=null==b.backgroundColor?"rgb(255,255,255)":b.backgroundColor;if(0==a(this).width()||0==a(this).height())return null;if(a.jqplot.use_excanvas)return null;for(var i,j,k,l,m=document.createElement("canvas"),n=a(this).outerHeight(!0),o=a(this).outerWidth(!0),p=a(this).offset(),q=p.left,r=p.top,s=0,t=0,u=["jqplot-table-legend","jqplot-xaxis-tick","jqplot-x2axis-tick","jqplot-yaxis-tick","jqplot-y2axis-tick","jqplot-y3axis-tick","jqplot-y4axis-tick","jqplot-y5axis-tick","jqplot-y6axis-tick","jqplot-y7axis-tick","jqplot-y8axis-tick","jqplot-y9axis-tick","jqplot-xaxis-label","jqplot-x2axis-label","jqplot-yaxis-label","jqplot-y2axis-label","jqplot-y3axis-label","jqplot-y4axis-label","jqplot-y5axis-label","jqplot-y6axis-label","jqplot-y7axis-label","jqplot-y8axis-label","jqplot-y9axis-label"],v=0;v<u.length;v++)a(this).find("."+u[v]).each(function(){i=a(this).offset().top-r,j=a(this).offset().left-q,l=j+a(this).outerWidth(!0)+s,k=i+a(this).outerHeight(!0)+t,-s>j&&(o=o-s-j,s=-j),-t>i&&(n=n-t-i,t=-i),l>o&&(o=l),k>n&&(n=k)});m.width=o+Number(f),m.height=n+Number(g);var w=m.getContext("2d");return w.save(),w.fillStyle=h,w.fillRect(0,0,m.width,m.height),w.restore(),w.translate(s,t),w.textAlign="left",w.textBaseline="top",a(this).children().each(function(){e(this,f,g)}),m},a.fn.jqplotToImageStr=function(b){var c=a(this).jqplotToImageCanvas(b);return c?c.toDataURL("image/png"):null},a.fn.jqplotToImageElem=function(b){var c=document.createElement("img"),d=a(this).jqplotToImageStr(b);return c.src=d,c},a.fn.jqplotToImageElemStr=function(b){var c="<img src="+a(this).jqplotToImageStr(b)+" />";return c},a.fn.jqplotSaveImage=function(){var b=a(this).jqplotToImageStr({});b&&(window.location.href=b.replace("image/png","image/octet-stream"))},a.fn.jqplotViewImage=function(){var b=a(this).jqplotToImageElemStr({});a(this).jqplotToImageStr({});if(b){var c=window.open("");c.document.open("image/png"),c.document.write(b),c.document.close(),c=null}};var S=function(){switch(this.syntax=S.config.syntax,this._type="jsDate",this.proxy=new Date,this.options={},this.locale=S.regional.getLocale(),this.formatString="",this.defaultCentury=S.config.defaultCentury,arguments.length){case 0:break;case 1:if("[object Object]"==D(arguments[0])&&"jsDate"!=arguments[0]._type){var a=this.options=arguments[0];this.syntax=a.syntax||this.syntax,this.defaultCentury=a.defaultCentury||this.defaultCentury,this.proxy=S.createDate(a.date)}else this.proxy=S.createDate(arguments[0]);break;default:for(var b=[],c=0;c<arguments.length;c++)b.push(arguments[c]);this.proxy=new Date,this.proxy.setFullYear.apply(this.proxy,b.slice(0,3)),b.slice(3).length&&this.proxy.setHours.apply(this.proxy,b.slice(3))}};S.config={defaultLocale:"en",syntax:"perl",defaultCentury:1900},S.prototype.add=function(a,b){var c=V[b]||V.day;return"number"==typeof c?this.proxy.setTime(this.proxy.getTime()+c*a):c.add(this,a),this},S.prototype.clone=function(){return new S(this.proxy.getTime())},S.prototype.getUtcOffset=function(){return 6e4*this.proxy.getTimezoneOffset()},S.prototype.diff=function(a,b,c){if(a=new S(a),null===a)return null;var d=V[b]||V.day;if("number"==typeof d)var e=(this.proxy.getTime()-a.proxy.getTime())/d;else var e=d.diff(this.proxy,a.proxy);return c?e:Math[e>0?"floor":"ceil"](e)},S.prototype.getAbbrDayName=function(){return S.regional[this.locale].dayNamesShort[this.proxy.getDay()]},S.prototype.getAbbrMonthName=function(){return S.regional[this.locale].monthNamesShort[this.proxy.getMonth()]},S.prototype.getAMPM=function(){return this.proxy.getHours()>=12?"PM":"AM"},S.prototype.getAmPm=function(){return this.proxy.getHours()>=12?"pm":"am"},S.prototype.getCentury=function(){return parseInt(this.proxy.getFullYear()/100,10)},S.prototype.getDate=function(){return this.proxy.getDate()},S.prototype.getDay=function(){return this.proxy.getDay()},S.prototype.getDayOfWeek=function(){var a=this.proxy.getDay();return 0===a?7:a},S.prototype.getDayOfYear=function(){var a=this.proxy,b=a-new Date(""+a.getFullYear()+"/1/1 GMT");return b+=6e4*a.getTimezoneOffset(),a=null,parseInt(b/6e4/60/24,10)+1},S.prototype.getDayName=function(){return S.regional[this.locale].dayNames[this.proxy.getDay()]},S.prototype.getFullWeekOfYear=function(){var a=this.proxy,b=this.getDayOfYear(),c=6-a.getDay(),d=parseInt((b+c)/7,10);return d},S.prototype.getFullYear=function(){return this.proxy.getFullYear()},S.prototype.getGmtOffset=function(){var a=this.proxy.getTimezoneOffset()/60,b=0>a?"+":"-";return a=Math.abs(a),b+U(Math.floor(a),2)+":"+U(a%1*60,2)},S.prototype.getHours=function(){return this.proxy.getHours()},S.prototype.getHours12=function(){var a=this.proxy.getHours();return a>12?a-12:0==a?12:a},S.prototype.getIsoWeek=function(){var a=this.proxy,b=this.getWeekOfYear(),c=new Date(""+a.getFullYear()+"/1/1").getDay(),d=b+(c>4||1>=c?0:1);return 53==d&&new Date(""+a.getFullYear()+"/12/31").getDay()<4?d=1:0===d&&(a=new S(new Date(""+(a.getFullYear()-1)+"/12/31")),d=a.getIsoWeek()),a=null,d},S.prototype.getMilliseconds=function(){return this.proxy.getMilliseconds()},S.prototype.getMinutes=function(){return this.proxy.getMinutes()},S.prototype.getMonth=function(){return this.proxy.getMonth()},S.prototype.getMonthName=function(){return S.regional[this.locale].monthNames[this.proxy.getMonth()]},S.prototype.getMonthNumber=function(){return this.proxy.getMonth()+1},S.prototype.getSeconds=function(){return this.proxy.getSeconds()},S.prototype.getShortYear=function(){return this.proxy.getYear()%100},S.prototype.getTime=function(){return this.proxy.getTime()},S.prototype.getTimezoneAbbr=function(){return this.proxy.toString().replace(/^.*\(([^)]+)\)$/,"$1")},S.prototype.getTimezoneName=function(){var a=/(?:\((.+)\)$| ([A-Z]{3}) )/.exec(this.toString());return a[1]||a[2]||"GMT"+this.getGmtOffset()},S.prototype.getTimezoneOffset=function(){return this.proxy.getTimezoneOffset()},S.prototype.getWeekOfYear=function(){var a=this.getDayOfYear(),b=7-this.getDayOfWeek(),c=parseInt((a+b)/7,10);return c},S.prototype.getUnix=function(){return Math.round(this.proxy.getTime()/1e3,0)},S.prototype.getYear=function(){return this.proxy.getYear()},S.prototype.next=function(a){return a=a||"day",this.clone().add(1,a)},S.prototype.set=function(){switch(arguments.length){case 0:this.proxy=new Date;break;case 1:if("[object Object]"==D(arguments[0])&&"jsDate"!=arguments[0]._type){var a=this.options=arguments[0];this.syntax=a.syntax||this.syntax,this.defaultCentury=a.defaultCentury||this.defaultCentury,this.proxy=S.createDate(a.date)}else this.proxy=S.createDate(arguments[0]);break;default:for(var b=[],c=0;c<arguments.length;c++)b.push(arguments[c]);this.proxy=new Date,this.proxy.setFullYear.apply(this.proxy,b.slice(0,3)),b.slice(3).length&&this.proxy.setHours.apply(this.proxy,b.slice(3))}return this},S.prototype.setDate=function(a){return this.proxy.setDate(a),this},S.prototype.setFullYear=function(){return this.proxy.setFullYear.apply(this.proxy,arguments),this},S.prototype.setHours=function(){return this.proxy.setHours.apply(this.proxy,arguments),this},S.prototype.setMilliseconds=function(a){return this.proxy.setMilliseconds(a),this},S.prototype.setMinutes=function(){return this.proxy.setMinutes.apply(this.proxy,arguments),this},S.prototype.setMonth=function(){return this.proxy.setMonth.apply(this.proxy,arguments),this},S.prototype.setSeconds=function(){return this.proxy.setSeconds.apply(this.proxy,arguments),this},S.prototype.setTime=function(a){return this.proxy.setTime(a),this},S.prototype.setYear=function(){return this.proxy.setYear.apply(this.proxy,arguments),this},S.prototype.strftime=function(a){return a=a||this.formatString||S.regional[this.locale].formatString,S.strftime(this,a,this.syntax)},S.prototype.toString=function(){return this.proxy.toString()},S.prototype.toYmdInt=function(){return 1e4*this.proxy.getFullYear()+100*this.getMonthNumber()+this.proxy.getDate()},S.regional={en:{monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],formatString:"%Y-%m-%d %H:%M:%S"},fr:{monthNames:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],monthNamesShort:["Jan","Fév","Mar","Avr","Mai","Jun","Jul","Aoû","Sep","Oct","Nov","Déc"],dayNames:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],dayNamesShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],formatString:"%Y-%m-%d %H:%M:%S"},de:{monthNames:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],dayNamesShort:["So","Mo","Di","Mi","Do","Fr","Sa"],formatString:"%Y-%m-%d %H:%M:%S"},es:{monthNames:["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],monthNamesShort:["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"],dayNames:["Domingo","Lunes","Martes","Mi&eacute;rcoles","Jueves","Viernes","S&aacute;bado"],dayNamesShort:["Dom","Lun","Mar","Mi&eacute;","Juv","Vie","S&aacute;b"],formatString:"%Y-%m-%d %H:%M:%S"},ru:{monthNames:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthNamesShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],dayNames:["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],dayNamesShort:["вск","пнд","втр","срд","чтв","птн","сбт"],formatString:"%Y-%m-%d %H:%M:%S"},ar:{monthNames:["كانون الثاني","شباط","آذار","نيسان","آذار","حزيران","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["السبت","الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة"],dayNamesShort:["سبت","أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة"],formatString:"%Y-%m-%d %H:%M:%S"},pt:{monthNames:["Janeiro","Fevereiro","Mar&ccedil;o","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Ter&ccedil;a-feira","Quarta-feira","Quinta-feira","Sexta-feira","S&aacute;bado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","S&aacute;b"],formatString:"%Y-%m-%d %H:%M:%S"},"pt-BR":{monthNames:["Janeiro","Fevereiro","Mar&ccedil;o","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Ter&ccedil;a-feira","Quarta-feira","Quinta-feira","Sexta-feira","S&aacute;bado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","S&aacute;b"],formatString:"%Y-%m-%d %H:%M:%S"},pl:{monthNames:["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"],monthNamesShort:["Sty","Lut","Mar","Kwi","Maj","Cze","Lip","Sie","Wrz","Paź","Lis","Gru"],dayNames:["Niedziela","Poniedziałek","Wtorek","Środa","Czwartek","Piątek","Sobota"],dayNamesShort:["Ni","Pn","Wt","Śr","Cz","Pt","Sb"],formatString:"%Y-%m-%d %H:%M:%S"},nl:{monthNames:["Januari","Februari","Maart","April","Mei","Juni","July","Augustus","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],dayNames:",".Zaterdag,dayNamesShort:["Zo","Ma","Di","Wo","Do","Vr","Za"],formatString:"%Y-%m-%d %H:%M:%S"},sv:{monthNames:["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],monthNamesShort:["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],dayNames:["söndag","måndag","tisdag","onsdag","torsdag","fredag","lördag"],dayNamesShort:["sön","mån","tis","ons","tor","fre","lör"],formatString:"%Y-%m-%d %H:%M:%S"},it:{monthNames:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthNamesShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],dayNames:["Domenica","Lunedi","Martedi","Mercoledi","Giovedi","Venerdi","Sabato"],dayNamesShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],formatString:"%d-%m-%Y %H:%M:%S"}},S.regional["en-US"]=S.regional["en-GB"]=S.regional.en,S.regional.getLocale=function(){var a=S.config.defaultLocale;return document&&document.getElementsByTagName("html")&&document.getElementsByTagName("html")[0].lang&&(a=document.getElementsByTagName("html")[0].lang,S.regional.hasOwnProperty(a)||(a=S.config.defaultLocale)),a};var T=864e5,U=function(a,b){a=String(a);var c=b-a.length,d=String(Math.pow(10,c)).slice(1);return d.concat(a)},V={millisecond:1,second:1e3,minute:6e4,hour:36e5,day:T,week:7*T,month:{add:function(a,b){V.year.add(a,Math[b>0?"floor":"ceil"](b/12));var c=a.getMonth()+b%12;12==c?(c=0,a.setYear(a.getFullYear()+1)):-1==c&&(c=11,a.setYear(a.getFullYear()-1)),a.setMonth(c)},diff:function(a,b){var c=a.getFullYear()-b.getFullYear(),d=a.getMonth()-b.getMonth()+12*c,e=a.getDate()-b.getDate();return d+e/30}},year:{add:function(a,b){a.setYear(a.getFullYear()+Math[b>0?"floor":"ceil"](b))},diff:function(a,b){return V.month.diff(a,b)/12}}};for(var W in V)"s"!=W.substring(W.length-1)&&(V[W+"s"]=V[W]);var X=function(a,b,c){if(S.formats[c].shortcuts[b])return S.strftime(a,S.formats[c].shortcuts[b],c);var d=(S.formats[c].codes[b]||"").split("."),e=a["get"+d[0]]?a["get"+d[0]]():"";return d[1]&&(e=U(e,d[1])),e};S.strftime=function(a,b,c,d){var e="perl",f=S.regional.getLocale();c&&S.formats.hasOwnProperty(c)?e=c:c&&S.regional.hasOwnProperty(c)&&(f=c),d&&S.formats.hasOwnProperty(d)?e=d:d&&S.regional.hasOwnProperty(d)&&(f=d),("[object Object]"!=D(a)||"jsDate"!=a._type)&&(a=new S(a),a.locale=f),b||(b=a.formatString||S.regional[f].formatString);for(var g,h=b||"%Y-%m-%d",i="";h.length>0;)(g=h.match(S.formats[e].codes.matcher))?(i+=h.slice(0,g.index),i+=(g[1]||"")+X(a,g[2],e),h=h.slice(g.index+g[0].length)):(i+=h,h="");return i},S.formats={ISO:"%Y-%m-%dT%H:%M:%S.%N%G",SQL:"%Y-%m-%d %H:%M:%S"},S.formats.perl={codes:{matcher:/()%(#?(%|[a-z]))/i,Y:"FullYear",y:"ShortYear.2",m:"MonthNumber.2","#m":"MonthNumber",B:"MonthName",b:"AbbrMonthName",d:"Date.2","#d":"Date",e:"Date",A:"DayName",a:"AbbrDayName",w:"Day",H:"Hours.2","#H":"Hours",I:"Hours12.2","#I":"Hours12",p:"AMPM",M:"Minutes.2","#M":"Minutes",S:"Seconds.2","#S":"Seconds",s:"Unix",N:"Milliseconds.3","#N":"Milliseconds",O:"TimezoneOffset",Z:"TimezoneName",G:"GmtOffset"},shortcuts:{F:"%Y-%m-%d",T:"%H:%M:%S",X:"%H:%M:%S",x:"%m/%d/%y",D:"%m/%d/%y","#c":"%a %b %e %H:%M:%S %Y",v:"%e-%b-%Y",R:"%H:%M",r:"%I:%M:%S %p",t:" ",n:"\n","%":"%"}},S.formats.php={codes:{matcher:/()%((%|[a-z]))/i,a:"AbbrDayName",A:"DayName",d:"Date.2",e:"Date",j:"DayOfYear.3",u:"DayOfWeek",w:"Day",U:"FullWeekOfYear.2",V:"IsoWeek.2",W:"WeekOfYear.2",b:"AbbrMonthName",B:"MonthName",m:"MonthNumber.2",h:"AbbrMonthName",C:"Century.2",y:"ShortYear.2",Y:"FullYear",H:"Hours.2",I:"Hours12.2",l:"Hours12",p:"AMPM",P:"AmPm",M:"Minutes.2",S:"Seconds.2",s:"Unix",O:"TimezoneOffset",z:"GmtOffset",Z:"TimezoneAbbr"},shortcuts:{D:"%m/%d/%y",F:"%Y-%m-%d",T:"%H:%M:%S",X:"%H:%M:%S",x:"%m/%d/%y",R:"%H:%M",r:"%I:%M:%S %p",t:" ",n:"\n","%":"%"}},S.createDate=function(a){function b(a,b){var c,d,e,f,g=parseFloat(b[1]),h=parseFloat(b[2]),i=parseFloat(b[3]),j=S.config.defaultCentury;return g>31?(d=i,e=h,c=j+g):(d=h,e=g,c=j+i),f=e+"/"+d+"/"+c,a.replace(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})/,f)}if(null==a)return new Date;if(a instanceof Date)return a;if("number"==typeof a)return new Date(a);var c=String(a).replace(/^\s*(.+)\s*$/g,"$1");c=c.replace(/^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,4})/,"$1/$2/$3"),c=c.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{4})/i,"$1 $2 $3");var d=c.match(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i);if(d&&d.length>3){var e=parseFloat(d[3]),f=S.config.defaultCentury+e;f=String(f),c=c.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i,d[1]+" "+d[2]+" "+f)}d=c.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})[^0-9]/),d&&d.length>3&&(c=b(c,d));var d=c.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})$/);d&&d.length>3&&(c=b(c,d));for(var g,h,i,j=0,k=S.matchers.length,l=c;k>j;){if(h=Date.parse(l),!isNaN(h))return new Date(h);if(g=S.matchers[j],"function"==typeof g){if(i=g.call(S,l),i instanceof Date)return i}else l=c.replace(g[0],g[1]);j++}return NaN},S.daysInMonth=function(a,b){return 2==b?29==new Date(a,1,29).getDate()?29:28:[F,31,F,31,30,31,30,31,31,30,31,30,31][b]},S.matchers=[[/(3[01]|[0-2]\d)\s*\.\s*(1[0-2]|0\d)\s*\.\s*([1-9]\d{3})/,"$2/$1/$3"],[/([1-9]\d{3})\s*-\s*(1[0-2]|0\d)\s*-\s*(3[01]|[0-2]\d)/,"$2/$3/$1"],function(a){var b=a.match(/^(?:(.+)\s+)?([012]?\d)(?:\s*\:\s*(\d\d))?(?:\s*\:\s*(\d\d(\.\d*)?))?\s*(am|pm)?\s*$/i);if(b){if(b[1]){var c=this.createDate(b[1]);if(isNaN(c))return}else{var c=new Date;c.setMilliseconds(0)}var d=parseFloat(b[2]);return b[6]&&(d="am"==b[6].toLowerCase()?12==d?0:d:12==d?12:d+12),c.setHours(d,parseInt(b[3]||0,10),parseInt(b[4]||0,10),1e3*(parseFloat(b[5]||0)||0)),c}return a},function(a){var b=a.match(/^(?:(.+))[T|\s+]([012]\d)(?:\:(\d\d))(?:\:(\d\d))(?:\.\d+)([\+\-]\d\d\:\d\d)$/i);if(b){if(b[1]){var c=this.createDate(b[1]);if(isNaN(c))return}else{var c=new Date;c.setMilliseconds(0)}var d=parseFloat(b[2]);return c.setHours(d,parseInt(b[3],10),parseInt(b[4],10),1e3*parseFloat(b[5])),c}return a},function(a){var b=a.match(/^([0-3]?\d)\s*[-\/.\s]{1}\s*([a-zA-Z]{3,9})\s*[-\/.\s]{1}\s*([0-3]?\d)$/);if(b){var c,d,e,f=new Date,g=S.config.defaultCentury,h=parseFloat(b[1]),i=parseFloat(b[3]);h>31?(d=i,c=g+h):(d=h,c=g+i);var e=C(b[2],S.regional[S.regional.getLocale()].monthNamesShort);return-1==e&&(e=C(b[2],S.regional[S.regional.getLocale()].monthNames)),f.setFullYear(c,e,d),f.setHours(0,0,0,0),f}return a}],a.jsDate=S,a.jqplot.sprintf=function(){function b(a,b,c,d){var e=a.length>=b?"":Array(1+b-a.length>>>0).join(c);return d?a+e:e+a}function c(b){for(var c=new String(b),d=10;d>0&&c!=(c=c.replace(/^(\d+)(\d{3})/,"$1"+a.jqplot.sprintf.thousandsSeparator+"$2"));d--);return c}function d(a,c,d,e,f,g){var h=e-a.length;if(h>0){var i=" ";g&&(i="&nbsp;"),a=d||!f?b(a,e,i,d):a.slice(0,c.length)+b("",h,"0",!0)+a.slice(c.length)}return a}function e(a,c,e,f,g,h,i,j){var k=a>>>0;return e=e&&k&&{2:"0b",8:"0",16:"0x"}[c]||"",a=e+b(k.toString(c),h||0,"0",!1),d(a,e,f,g,i,j)}function f(a,b,c,e,f,g){return null!=e&&(a=a.slice(0,e)),d(a,"",b,c,f,g)}var g=arguments,h=0,i=g[h++];return i.replace(a.jqplot.sprintf.regex,function(i,j,k,l,m,n,o){if("%%"==i)return"%";for(var p=!1,q="",r=!1,s=!1,t=!1,u=!1,v=0;k&&v<k.length;v++)switch(k.charAt(v)){case" ":q=" ";break;case"+":q="+";break;case"-":p=!0;break;case"0":r=!0;break;case"#":s=!0;break;case"&":t=!0;break;case"'":u=!0}if(l=l?"*"==l?+g[h++]:"*"==l.charAt(0)?+g[l.slice(1,-1)]:+l:0,0>l&&(l=-l,p=!0),!isFinite(l))throw new Error("$.jqplot.sprintf: (minimum-)width must be finite");n=n?"*"==n?+g[h++]:"*"==n.charAt(0)?+g[n.slice(1,-1)]:+n:"fFeE".indexOf(o)>-1?6:"d"==o?0:void 0;var w=j?g[j.slice(0,-1)]:g[h++];switch(o){case"s":return null==w?"":f(String(w),p,l,n,r,t);case"c":return f(String.fromCharCode(+w),p,l,n,r,t);case"b":return e(w,2,s,p,l,n,r,t);case"o":return e(w,8,s,p,l,n,r,t);case"x":return e(w,16,s,p,l,n,r,t);case"X":return e(w,16,s,p,l,n,r,t).toUpperCase();case"u":return e(w,10,s,p,l,n,r,t);case"i":var x=parseInt(+w,10);if(isNaN(x))return"";var y=0>x?"-":q,z=u?c(String(Math.abs(x))):String(Math.abs(x));return w=y+b(z,n,"0",!1),d(w,y,p,l,r,t);case"d":var x=Math.round(+w);if(isNaN(x))return"";var y=0>x?"-":q,z=u?c(String(Math.abs(x))):String(Math.abs(x));return w=y+b(z,n,"0",!1),d(w,y,p,l,r,t);case"e":case"E":case"f":case"F":case"g":case"G":var x=+w;if(isNaN(x))return"";var y=0>x?"-":q,A=["toExponential","toFixed","toPrecision"]["efg".indexOf(o.toLowerCase())],B=["toString","toUpperCase"]["eEfFgG".indexOf(o)%2],z=Math.abs(x)[A](n),C=z.toString().split(".");C[0]=u?c(C[0]):C[0],z=C.join(a.jqplot.sprintf.decimalMark),w=y+z;var D=d(w,y,p,l,r,t)[B]();return D;case"p":case"P":var x=+w;if(isNaN(x))return"";var y=0>x?"-":q,C=String(Number(Math.abs(x)).toExponential()).split(/e|E/),E=-1!=C[0].indexOf(".")?C[0].length-1:String(x).length,F=C[1]<0?-C[1]-1:0;if(Math.abs(x)<1)w=n>=E+F?y+Math.abs(x).toPrecision(E):n-1>=E?y+Math.abs(x).toExponential(E-1):y+Math.abs(x).toExponential(n-1);else{var G=n>=E?E:n;w=y+Math.abs(x).toPrecision(G)}var B=["toString","toUpperCase"]["pP".indexOf(o)%2];return d(w,y,p,l,r,t)[B]();case"n":return"";default:return i}})},a.jqplot.sprintf.thousandsSeparator=",",a.jqplot.sprintf.decimalMark=".",a.jqplot.sprintf.regex=/%%|%(\d+\$)?([-+#0&\' ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([nAscboxXuidfegpEGP])/g,a.jqplot.getSignificantFigures=function(a){var b=String(Number(Math.abs(a)).toExponential()).split(/e|E/),c=-1!=b[0].indexOf(".")?b[0].length-1:b[0].length,d=b[1]<0?-b[1]-1:0,e=parseInt(b[1],10),f=e+1>0?e+1:0,g=f>=c?0:c-e-1;return{significantDigits:c,digitsLeft:f,digitsRight:g,zeros:d,exponent:e}},a.jqplot.getPrecision=function(b){return a.jqplot.getSignificantFigures(b).digitsRight};var Y=a.uiBackCompat!==!1;a.jqplot.effects={effect:{}};var Z="jqplot.storage.";a.extend(a.jqplot.effects,{version:"1.9pre",save:function(a,b){for(var c=0;c<b.length;c++)null!==b[c]&&a.data(Z+b[c],a[0].style[b[c]])},restore:function(a,b){for(var c=0;c<b.length;c++)null!==b[c]&&a.css(b[c],a.data(Z+b[c]))},setMode:function(a,b){return"toggle"===b&&(b=a.is(":hidden")?"show":"hide"),b},createWrapper:function(b){if(b.parent().is(".ui-effects-wrapper"))return b.parent();var c={width:b.outerWidth(!0),height:b.outerHeight(!0),"float":b.css("float")},d=a("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e={width:b.width(),height:b.height()},f=document.activeElement;return b.wrap(d),(b[0]===f||a.contains(b[0],f))&&a(f).focus(),d=b.parent(),"static"===b.css("position")?(d.css({position:"relative"}),b.css({position:"relative"})):(a.extend(c,{position:b.css("position"),zIndex:b.css("z-index")}),a.each(["top","left","bottom","right"],function(a,d){c[d]=b.css(d),isNaN(parseInt(c[d],10))&&(c[d]="auto")}),b.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),b.css(e),d.css(c).show()},removeWrapper:function(b){var c=document.activeElement;return b.parent().is(".ui-effects-wrapper")&&(b.parent().replaceWith(b),(b[0]===c||a.contains(b[0],c))&&a(c).focus()),b}}),a.fn.extend({jqplotEffect:function(b,c,d,e){function f(b){function c(){a.isFunction(e)&&e.call(d[0]),a.isFunction(b)&&b()}var d=a(this),e=g.complete,f=g.mode;(d.is(":hidden")?"hide"===f:"show"===f)?c():j.call(d[0],g,c)}var g=E.apply(this,arguments),h=g.mode,i=g.queue,j=a.jqplot.effects.effect[g.effect],k=!j&&Y&&a.jqplot.effects[g.effect];return a.fx.off||!j&&!k?h?this[h](g.duration,g.complete):this.each(function(){g.complete&&g.complete.call(this)}):j?i===!1?this.each(f):this.queue(i||"fx",f):k.call(this,{options:g,duration:g.duration,callback:g.complete,mode:g.mode})}});var $=/up|down|vertical/,_=/up|left|vertical|horizontal/;a.jqplot.effects.effect.blind=function(b,c){var d,e,f,g=a(this),h=["position","top","bottom","left","right","height","width"],i=a.jqplot.effects.setMode(g,b.mode||"hide"),j=b.direction||"up",k=$.test(j),l=k?"height":"width",m=k?"top":"left",n=_.test(j),o={},p="show"===i;g.parent().is(".ui-effects-wrapper")?a.jqplot.effects.save(g.parent(),h):a.jqplot.effects.save(g,h),g.show(),f=parseInt(g.css("top"),10),d=a.jqplot.effects.createWrapper(g).css({overflow:"hidden"}),e=k?d[l]()+f:d[l](),o[l]=p?String(e):"0",n||(g.css(k?"bottom":"right",0).css(k?"top":"left","").css({position:"absolute"}),o[m]=p?"0":String(e)),p&&(d.css(l,0),n||d.css(m,e)),d.animate(o,{duration:b.duration,easing:b.easing,queue:!1,complete:function(){"hide"===i&&g.hide(),a.jqplot.effects.restore(g,h),a.jqplot.effects.removeWrapper(g),c()}})}}(jQuery);
js/js.js DELETED
@@ -1,183 +0,0 @@
1
-
2
- var colors = ['#DB6946', '#C14543', '#445060', '#395953', '#6C8C80', '#829AB5', '#BF807A', '#BF0000', '#006BB7', '#EC732C', '#BF3D27', '#A6375F',
3
- '#8C6D46', '#326149', '#802B35', '#8A3842', '#366D73', '#4D6173', '#4A4659', '#C9D65B', '#F45552', '#F3CC5E', '#F29B88', '#D96941',
4
- '#484F73', '#C9AB81', '#F5655C', '#F0C480'];
5
- //------------------------------------------------------------------------------
6
- function convertToNumeric(data){
7
- if(data instanceof Array){
8
- for(var index in data){
9
- data[index] = Number(data[index]);
10
- }
11
- } else{
12
- data = Number(data);
13
- }
14
- return data;
15
- }
16
- //------------------------------------------------------------------------------
17
- function getRandomElementFromArray(array){
18
- var ranIndex = Math.floor(Math.random() * array.length);
19
- return array[ranIndex];
20
- }
21
- //------------------------------------------------------------------------------
22
- function drawVisitsLineChart(visitsData){
23
-
24
- /*
25
-
26
-
27
- var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
28
-
29
- var barChartData = {
30
- labels : visitsData.data.dates,
31
- datasets : [
32
- {
33
- label: "Visitors",
34
- barShowStroke: false,
35
- fillColor : "rgba(220,220,220,0.5)",
36
- strokeColor : "rgba(220,220,220,0.8)",
37
- highlightFill: "rgba(220,220,220,0.75)",
38
- highlightStroke: "rgba(220,220,220,1)",
39
- data : visitsData.data.visitors
40
- },
41
- {
42
- label: "Visits",
43
- barShowStroke: false,
44
- fillColor : "rgba(151,187,205,0.5)",
45
- strokeColor : "rgba(151,187,205,0.8)",
46
- highlightFill : "rgba(151,187,205,0.75)",
47
- highlightStroke : "rgba(151,187,205,1)",
48
- data : visitsData.data.visits
49
- }
50
- ]
51
-
52
- }
53
- var ctx = document.getElementById("visitorsVisitsChart").getContext("2d");
54
- window.myBar = new Chart(ctx).Bar(barChartData, {
55
- responsive : true,
56
- animation:true,
57
- scaleOverride:true,
58
- scaleSteps:5,
59
- scaleStartValue:0,
60
- scaleStepWidth:10
61
- });
62
- */
63
-
64
-
65
- var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
66
- var lineChartData = {
67
- labels : visitsData.data.dates,
68
- datasets : [
69
- {
70
- label: "Visitors",
71
- fillColor : "rgba(220,220,220,0.2)",
72
- strokeColor : "rgba(220,220,220,1)",
73
- pointColor : "rgba(220,220,220,1)",
74
- pointStrokeColor : "#fff",
75
- pointHighlightFill : "#fff",
76
- pointHighlightStroke : "rgba(220,220,220,1)",
77
- data : visitsData.data.visitors
78
- },
79
- {
80
- label: "Visits",
81
- fillColor : "rgba(151,187,205,0.2)",
82
- strokeColor : "rgba(151,187,205,1)",
83
- pointColor : "rgba(151,187,205,1)",
84
- pointStrokeColor : "#fff",
85
- pointHighlightFill : "#fff",
86
- pointHighlightStroke : "rgba(151,187,205,1)",
87
- data : visitsData.data.visits
88
- }
89
- ]
90
-
91
- }
92
-
93
- window.onload = function(){
94
- var ctx = document.getElementById("visitorsVisitsChart").getContext("2d");
95
- window.myLine = new Chart(ctx).Line(lineChartData, {
96
- responsive: true,
97
- scaleOverride:false,
98
- scaleSteps:5,
99
- scaleStartValue:0,
100
- scaleStepWidth:5
101
- });
102
- }
103
-
104
- }
105
- //------------------------------------------------------------------------------
106
- function drawBrowsersBieChart(browsersData){
107
- var brsBieChartData = [];
108
- var container = jQuery('#browsersLegContainer');
109
- var html = '';
110
- if(browsersData.length == 0)
111
- {
112
- document.getElementById('browsersLegContainer').style.display = 'none';
113
- }else{
114
- document.getElementById('browsersLegContainer').style.display = 'block';
115
- }
116
- for(var i = 0; i < browsersData.length; i++){
117
- var color = getRandomElementFromArray(colors);
118
- var value = Number(browsersData[i].hits);
119
- brsBieChartData[i] = {label: browsersData[i].bsr_name, value: value, color: color};
120
- html += (isEmpty(value))? '' : '<div class="legend">' +
121
- '<span class="color" style="background-color: ' + color + ';">&nbsp;&nbsp;</span>' +
122
- '<span class="name">' + browsersData[i].bsr_name + '</span>' +
123
- '<span class="value">' + value + '</span>' +
124
- '</div>';
125
- }
126
- html += '<div class="cleaner"></div>';
127
- container.html(html);
128
- var ctx = document.getElementById("brsBiechartContainer").getContext("2d");
129
- window.myPie = new Chart(ctx).Pie(brsBieChartData);
130
- }
131
- //------------------------------------------------------------------------------
132
- function drawSrhEngVstLineChart(srhEngVisitsData){
133
- var srh_series = [];
134
- var container = jQuery('#srchEngLegContainer');
135
-
136
- document.getElementById('srchEngLegContainer').style.display = 'none';
137
- var html = '';
138
- for(var index in srhEngVisitsData.data.search_engines){
139
- var color = getRandomElementFromArray(colors);
140
- var value = countVisits(srhEngVisitsData.data.search_engines[index]);
141
-
142
- if(parseFloat(value) !=0)
143
- {
144
- document.getElementById('srchEngLegContainer').style.display = 'block';
145
- }
146
-
147
- srh_series[srh_series.length] = {
148
- "label": index,
149
- "value": value,
150
- "color": color
151
- }
152
-
153
- html += (isEmpty(value))? '' : '<div class="legend">' +
154
- '<span class="color" style="background-color: ' + color + ';">&nbsp;&nbsp;</span>' +
155
- '<span class="name">' + index + '</span>' +
156
- '<span class="value">' + value + '</span>' +
157
- '</div>';
158
- }
159
-
160
-
161
-
162
-
163
- html += '<div class="cleaner"></div>';
164
- container.html(html);
165
- var ctx = document.getElementById("srhEngBieChartContainer").getContext("2d");
166
- window.myPie = new Chart(ctx).Pie(srh_series);
167
- }
168
-
169
- function isEmpty(val){
170
- return (val == null || val == 0 || val == '' || val == '0');
171
- }
172
-
173
- //------------------------------------------------------------------------------
174
- function countVisits(arr){
175
- var count = 0;
176
- for(var i = 0; i < arr.length; i++){
177
- count += Number(arr[i]);
178
- }
179
- return count;
180
- }
181
- //------------------------------------------------------------------------------
182
-
183
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/sweetalert.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Sweetalert2=t()}(this,function(){"use strict";function e(){if(void 0===arguments[0])return console.error("SweetAlert2 expects at least 1 attribute!"),!1;var e=c({},j);switch(typeof arguments[0]){case"string":e.title=arguments[0],e.text=arguments[1]||"",e.type=arguments[2]||"";break;case"object":c(e,arguments[0]),e.extraParams=arguments[0].extraParams,"email"===e.input&&null===e.inputValidator&&(e.inputValidator=function(e){return new Promise(function(t,n){var o=/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;o.test(e)?t():n("Invalid email address")})});break;default:return console.error('SweetAlert2: Unexpected type of argument! Expected "string" or "object", got '+typeof arguments[0]),!1}K(e);var n=f();return new Promise(function(o,r){function a(t,n){for(var o=b(e.focusCancel),i=0;i<o.length;i++){t+=n,t===o.length?t=0:-1===t&&(t=o.length-1);var r=o[t];if(L(r))return r.focus()}}function l(n){var o=n||window.event,i=o.keyCode||o.which;if(-1!==[9,13,32,27].indexOf(i)){for(var l=o.target||o.srcElement,c=b(e.focusCancel),s=-1,u=0;u<c.length;u++)if(l===c[u]){s=u;break}9===i?(o.shiftKey?a(s,-1):a(s,1),V(o)):13===i||32===i?-1===s&&(e.focusCancel?O(P,o):O(M,o)):27===i&&e.allowEscapeKey===!0&&(t.closeModal(e.onClose),r("esc"))}}e.timer&&(n.timeout=setTimeout(function(){t.closeModal(e.onClose),r("timer")},e.timer));var c=function(){switch(e.input){case"select":return x(n,i.select);case"radio":return n.querySelector("."+i.radio+" input:checked")||n.querySelector("."+i.radio+" input:first-child");case"checkbox":return n.querySelector("#"+i.checkbox);case"textarea":return x(n,i.textarea);default:return x(n,i.input)}},u=function(){var t=c();switch(e.input){case"checkbox":return t.checked?1:0;case"radio":return t.checked?t.value:null;case"file":return t.files.length?t.files[0]:null;default:return e.inputAutoTrim?t.value.trim():t.value}};e.input&&setTimeout(function(){var e=c();e&&w(e)},0);var p,f=function(n){e.showLoaderOnConfirm&&t.showLoading(),e.preConfirm?e.preConfirm(n,e.extraParams).then(function(i){t.closeModal(e.onClose),o(i||n)},function(e){t.hideLoading(),e&&t.showValidationError(e)}):(t.closeModal(e.onClose),o(n))},g=function(n){var o=n||window.event,i=o.target||o.srcElement,a=v(),l=h(),c=a===i||a.contains(i),d=l===i||l.contains(i);switch(o.type){case"mouseover":case"mouseup":e.buttonsStyling&&(c?a.style.backgroundColor=s(e.confirmButtonColor,-.1):d&&(l.style.backgroundColor=s(e.cancelButtonColor,-.1)));break;case"mouseout":e.buttonsStyling&&(c?a.style.backgroundColor=e.confirmButtonColor:d&&(l.style.backgroundColor=e.cancelButtonColor));break;case"mousedown":e.buttonsStyling&&(c?a.style.backgroundColor=s(e.confirmButtonColor,-.2):d&&(l.style.backgroundColor=s(e.cancelButtonColor,-.2)));break;case"click":if(c&&t.isVisible())if(e.input){var p=u();e.inputValidator?(t.disableInput(),e.inputValidator(p,e.extraParams).then(function(){t.enableInput(),f(p)},function(e){t.enableInput(),e&&t.showValidationError(e)})):f(p)}else f(!0);else d&&t.isVisible()&&(t.closeModal(e.onClose),r("cancel"))}},q=n.querySelectorAll("button");for(p=0;p<q.length;p++)q[p].onclick=g,q[p].onmouseover=g,q[p].onmouseout=g,q[p].onmousedown=g;y().onclick=function(){t.closeModal(e.onClose),r("close")},m().onclick=function(){e.allowOutsideClick&&(t.closeModal(e.onClose),r("overlay"))};var M=v(),P=h();e.reverseButtons?M.parentNode.insertBefore(P,M):M.parentNode.insertBefore(M,P),d.previousWindowKeyDown=window.onkeydown,window.onkeydown=l,e.buttonsStyling&&(M.style.borderLeftColor=e.confirmButtonColor,M.style.borderRightColor=e.confirmButtonColor),t.showLoading=t.enableLoading=function(){C(M,"loading"),C(n,"loading"),M.disabled=!0,P.disabled=!0},t.hideLoading=t.disableLoading=function(){k(M,"loading"),k(n,"loading"),M.disabled=!1,P.disabled=!1},t.enableButtons=function(){M.disabled=!1,P.disabled=!1},t.disableButtons=function(){M.disabled=!0,P.disabled=!0},t.enableConfirmButton=function(){M.disabled=!1},t.disableConfirmButton=function(){M.disabled=!0},t.enableInput=function(){var e=c();if("radio"===e.type)for(var t=e.parentNode.parentNode,n=t.querySelectorAll("input"),o=0;o<n.length;o++)n[o].disabled=!1;else e.disabled=!1},t.disableInput=function(){var e=c();if("radio"===e.type)for(var t=e.parentNode.parentNode,n=t.querySelectorAll("input"),o=0;o<n.length;o++)n[o].disabled=!0;else e.disabled=!0},t.showValidationError=function(e){var t=n.querySelector("."+i.validationerror);t.innerHTML=e,S(t);var o=c();w(o),C(o,"error")},t.resetValidationError=function(){var e=n.querySelector("."+i.validationerror);B(e);var t=c();t&&k(t,"error")},t.enableButtons(),t.hideLoading(),t.resetValidationError();var T,N=["input","select","radio","checkbox","textarea"];for(p=0;p<N.length;p++){var H=i[N[p]];for(T=x(n,H);T.attributes.length>0;)T.removeAttribute(T.attributes[0].name);for(var D in e.inputAttributes)T.setAttribute(D,e.inputAttributes[D]);T.className=H,e.inputClass&&C(T,e.inputClass),A(T)}var I;switch(e.input){case"text":case"email":case"password":case"file":T=x(n,i.input),T.value=e.inputValue,T.placeholder=e.inputPlaceholder,T.type=e.input,E(T);break;case"select":var j=x(n,i.select);if(j.innerHTML="",e.inputPlaceholder){var K=document.createElement("option");K.innerHTML=e.inputPlaceholder,K.value="",K.disabled=!0,K.selected=!0,j.appendChild(K)}I=function(t){for(var n in t){var o=document.createElement("option");o.value=n,o.innerHTML=t[n],e.inputValue===n&&(o.selected=!0),j.appendChild(o)}E(j),j.focus()};break;case"radio":var z=x(n,i.radio);z.innerHTML="",I=function(t){for(var n in t){var o=1,r=document.createElement("input"),a=document.createElement("label"),l=document.createElement("span");r.type="radio",r.name=i.radio,r.value=n,r.id=i.radio+"-"+o++,e.inputValue===n&&(r.checked=!0),l.innerHTML=t[n],a.appendChild(r),a.appendChild(l),a["for"]=r.id,z.appendChild(a)}E(z);var c=z.querySelectorAll("input");c.length&&c[0].focus()};break;case"checkbox":var R=x(n,i.checkbox),Z=n.querySelector("#"+i.checkbox);Z.value=1,Z.checked=Boolean(e.inputValue);var $=R.getElementsByTagName("span");$.length&&R.removeChild($[0]),$=document.createElement("span"),$.innerHTML=e.inputPlaceholder,R.appendChild($),E(R);break;case"textarea":var F=x(n,i.textarea);F.value=e.inputValue,F.placeholder=e.inputPlaceholder,E(F);break;case null:break;default:console.error('SweetAlert2: Unexpected type of input! Expected "text" or "email" or "password", "select", "checkbox", "textarea" or "file", got "'+e.input+'"')}"select"!==e.input&&"radio"!==e.input||(e.inputOptions instanceof Promise?(t.showLoading(),e.inputOptions.then(function(e){t.hideLoading(),I(e)})):"object"==typeof e.inputOptions?I(e.inputOptions):console.error("SweetAlert2: Unexpected type of inputOptions! Expected object or Promise, got "+typeof e.inputOptions)),W(),U(e.animation,e.onOpen),a(-1,1)})}function t(){var n=arguments,o=f();return null===o&&(t.init(),o=f()),t.isVisible()&&t.close(),e.apply(this,n)}var n="swal2-",o=function(e){var t={};for(var o in e)t[e[o]]=n+e[o];return t},i=o(["container","modal","overlay","close","content","spacer","confirm","cancel","icon","image","input","select","radio","checkbox","textarea","validationerror"]),r=o(["success","warning","info","question","error"]),a={title:"",text:"",html:"",type:null,customClass:"",animation:!0,allowOutsideClick:!0,allowEscapeKey:!0,showConfirmButton:!0,showCancelButton:!1,preConfirm:null,confirmButtonText:"OK",confirmButtonColor:"#3085d6",confirmButtonClass:null,cancelButtonText:"Cancel",cancelButtonColor:"#aaa",cancelButtonClass:null,buttonsStyling:!0,reverseButtons:!1,focusCancel:!1,showCloseButton:!1,showLoaderOnConfirm:!1,imageUrl:null,imageWidth:null,imageHeight:null,imageClass:null,timer:null,width:500,padding:20,background:"#fff",input:null,inputPlaceholder:"",inputValue:"",inputOptions:{},inputAutoTrim:!0,inputClass:null,inputAttributes:{},inputValidator:null,onOpen:null,onClose:null},l='<div class="'+i.overlay+'" tabIndex="-1"></div><div class="'+i.modal+'" style="display: none" tabIndex="-1"><div class="'+i.icon+" "+r.error+'"><span class="x-mark"><span class="line left"></span><span class="line right"></span></span></div><div class="'+i.icon+" "+r.question+'">?</div><div class="'+i.icon+" "+r.warning+'">!</div><div class="'+i.icon+" "+r.info+'">i</div><div class="'+i.icon+" "+r.success+'"><span class="line tip"></span> <span class="line long"></span><div class="placeholder"></div> <div class="fix"></div></div><img class="'+i.image+'"><h2></h2><div class="'+i.content+'"></div><input class="'+i.input+'"><select class="'+i.select+'"></select><div class="'+i.radio+'"></div><label for="'+i.checkbox+'" class="'+i.checkbox+'"><input type="checkbox" id="'+i.checkbox+'"></label><textarea class="'+i.textarea+'"></textarea><div class="'+i.validationerror+'"></div><hr class="'+i.spacer+'"><button class="'+i.confirm+'">OK</button><button class="'+i.cancel+'">Cancel</button><span class="'+i.close+'">&times;</span></div>',c=function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e},s=function(e,t){e=String(e).replace(/[^0-9a-f]/gi,""),e.length<6&&(e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]),t=t||0;for(var n="#",o=0;3>o;o++){var i=parseInt(e.substr(2*o,2),16);i=Math.round(Math.min(Math.max(0,i+i*t),255)).toString(16),n+=("00"+i).substr(i.length)}return n},u=function(e){return"function"==typeof e},d={previousWindowKeyDown:null,previousActiveElement:null},p=function(e){return document.querySelector("."+e)},f=function(){return p(i.modal)},m=function(){return p(i.overlay)},v=function(){return p(i.confirm)},h=function(){return p(i.cancel)},y=function(){return p(i.close)},b=function(e){var t=[v(),h()];return e&&t.reverse(),t.concat(Array.prototype.slice.call(f().querySelectorAll("button:not([class^="+n+"]), input:not([type=hidden]), textarea, select")))},g=function(e,t){return e.classList.contains(t)},w=function(e){e.focus();var t=e.value;e.value="",e.value=t},C=function(e,t){if(e&&t){var n=t.split(/\s+/);n.forEach(function(t){e.classList.add(t)})}},k=function(e,t){if(e&&t){var n=t.split(/\s+/);n.forEach(function(t){e.classList.remove(t)})}},x=function(e,t){for(var n=0;n<e.childNodes.length;n++)if(g(e.childNodes[n],t))return e.childNodes[n]},E=function(e){e.style.opacity="",e.style.display="block"},S=function(e){if(e&&!e.length)return E(e);for(var t=0;t<e.length;++t)E(e[t])},A=function(e){e.style.opacity="",e.style.display="none"},B=function(e){if(e&&!e.length)return A(e);for(var t=0;t<e.length;++t)A(e[t])},L=function(e){return e.offsetWidth||e.offsetHeight||e.getClientRects().length},q=function(e,t){e.style.removeProperty?e.style.removeProperty(t):e.style.removeAttribute(t)},M=function(e){var t=e.style.display;e.style.left="-9999px",e.style.display="block";var n=e.clientHeight;return e.style.left="",e.style.display=t,"-"+parseInt(n/2,10)+"px"},P=function(e,t){if(+e.style.opacity<1){t=t||16,e.style.opacity=0,e.style.display="block";var n=+new Date,o=function(){var i=+e.style.opacity+(new Date-n)/100;e.style.opacity=i>1?1:i,n=+new Date,+e.style.opacity<1&&setTimeout(o,t)};o()}},T=function(e,t){if(+e.style.opacity>0){t=t||16;var n=e.style.opacity,o=+new Date,i=function(){var r=new Date-o,a=+e.style.opacity-r/(100*n);e.style.opacity=a,o=+new Date,+e.style.opacity>0?setTimeout(i,t):A(e)};i()}},O=function(e){if("function"==typeof MouseEvent){var t=new MouseEvent("click",{view:window,bubbles:!1,cancelable:!0});e.dispatchEvent(t)}else if(document.createEvent){var n=document.createEvent("MouseEvents");n.initEvent("click",!1,!1),e.dispatchEvent(n)}else document.createEventObject?e.fireEvent("onclick"):"function"==typeof e.onclick&&e.onclick()},V=function(e){"function"==typeof e.stopPropagation?(e.stopPropagation(),e.preventDefault()):window.event&&window.event.hasOwnProperty("cancelBubble")&&(window.event.cancelBubble=!0)},N=function(){var e=document.createElement("div"),t={WebkitAnimation:"webkitAnimationEnd",OAnimation:"oAnimationEnd oanimationend",msAnimation:"MSAnimationEnd",animation:"animationend"};for(var n in t)if(t.hasOwnProperty(n)&&void 0!==e.style[n])return t[n];return!1}(),H=function(){var e=f();window.onkeydown=d.previousWindowKeyDown,d.previousActiveElement&&d.previousActiveElement.focus&&d.previousActiveElement.focus(),clearTimeout(e.timeout)},D=function(e){var t=n+"mediaquery-"+Math.random().toString(36).substring(2,7),o=document.getElementsByTagName("head")[0],i=document.createElement("style");return i.type="text/css",i.id=t,i.innerHTML=e,o.appendChild(i),t},I=function(e){if(!e)return!1;var t=document.getElementsByTagName("head")[0],n=document.getElementById(e);n&&t.removeChild(n)},j=c({},a),K=function(e){var t=f();for(var n in e)a.hasOwnProperty(n)||"extraParams"===n||console.warn('SweetAlert2: Unknown parameter "'+n+'"');e.width=e.width.toString();var o,l=e.width.match(/^(\d+)(px|%)?$/);if(l?(o="px",l[2]&&(o=l[2]),l=parseInt(l[1],10),t.style.width=l+o,t.style.marginLeft=-l/2+o):console.warn('SweetAlert2: Invalid width parameter, usage examples: "400px", "50%", or just 500 which equals to "500px"'),t.style.padding=e.padding+"px",t.style.background=e.background,"px"===o){var c=5,s=l+l*(c/100)*2,u=D("@media screen and (max-width: "+s+"px) {."+i.modal+" {width: auto !important;left: "+c+"% !important;right: "+c+"% !important;margin-left: 0 !important;}}");t.setAttribute("data-mediaquery-id",u)}var d=t.querySelector("h2"),p=t.querySelector("."+i.content),m=v(),y=h(),b=t.querySelector("."+i.spacer),g=t.querySelector("."+i.close);if(d.innerHTML=e.title.split("\n").join("<br>"),e.text||e.html){if("object"==typeof e.html)if(p.innerHTML="",0 in e.html)for(var w=0;w in e.html;w++)p.appendChild(e.html[w]);else p.appendChild(e.html);else p.innerHTML=e.html||e.text.split("\n").join("<br>");S(p)}else B(p);if(e.showCloseButton?S(g):B(g),t.className=i.modal,e.customClass&&C(t,e.customClass),B(t.querySelectorAll("."+i.icon)),e.type){var x=!1;for(var E in r)if(e.type===E){x=!0;break}if(!x)return console.error("SweetAlert2: Unknown alert type: "+e.type),!1;var A=t.querySelector("."+i.icon+"."+r[e.type]);switch(S(A),e.type){case"success":C(A,"animate"),C(A.querySelector(".tip"),"animate-success-tip"),C(A.querySelector(".long"),"animate-success-long");break;case"error":C(A,"animate-error-icon"),C(A.querySelector(".x-mark"),"animate-x-mark");break;case"warning":C(A,"pulse-warning")}}var L=t.querySelector("."+i.image);e.imageUrl?(L.setAttribute("src",e.imageUrl),S(L),e.imageWidth?L.setAttribute("width",e.imageWidth):L.removeAttribute("width"),e.imageHeight?L.setAttribute("height",e.imageHeight):L.removeAttribute("height"),L.className=i.image,e.imageClass&&C(L,e.imageClass)):B(L),e.showCancelButton?y.style.display="inline-block":B(y),e.showConfirmButton?q(m,"display"):B(m),e.showConfirmButton||e.showCancelButton?S(b):B(b),m.innerHTML=e.confirmButtonText,y.innerHTML=e.cancelButtonText,e.buttonsStyling&&(m.style.backgroundColor=e.confirmButtonColor,y.style.backgroundColor=e.cancelButtonColor),m.className=i.confirm,C(m,e.confirmButtonClass),y.className=i.cancel,C(y,e.cancelButtonClass),e.buttonsStyling?(C(m,"styled"),C(y,"styled")):(k(m,"styled"),k(y,"styled"),m.style.backgroundColor=m.style.borderLeftColor=m.style.borderRightColor="",y.style.backgroundColor=y.style.borderLeftColor=y.style.borderRightColor=""),e.animation===!0?k(t,"no-animation"):C(t,"no-animation")},U=function(e,t){var n=f();e?(P(m(),10),C(n,"show-swal2"),k(n,"hide-swal2")):S(m()),S(n),d.previousActiveElement=document.activeElement,null!==t&&"function"==typeof t&&t.call(this,n)},W=function(){var e=f();null!==e&&(e.style.marginTop=M(e))};return t.isVisible=function(){var e=f();return L(e)},t.queue=function(e,n){var o;return n&&(o={fork:function(e){n=e,this.next=e[0]},repeatCurrent:function(){n.unshift(this.current),this.next=this.current},insert:function(e){n.unshift(e),this.next=this.state},terminate:function(){n=[],this.next=""}}),new Promise(function(i,r){!function a(l,c){var s=null;u(e)?n&&n.length>0?(o.current=n[0],o.next=n.length>1?n[1]:"",o.alertNumber=l,n.shift(),s=e(o)):s=e(l):l<e.length&&(s=e[l]),s?t(s).then(function(){a(l+1,c)},function(e){r(e)}):i()}(0)})},t.close=t.closeModal=function(e){var t=f();k(t,"show-swal2"),C(t,"hide-swal2");var n=t.querySelector("."+i.icon+"."+r.success);k(n,"animate"),k(n.querySelector(".tip"),"animate-success-tip"),k(n.querySelector(".long"),"animate-success-long");var o=t.querySelector("."+i.icon+"."+r.error);k(o,"animate-error-icon"),k(o.querySelector(".x-mark"),"animate-x-mark");var a=t.querySelector("."+i.icon+"."+r.warning);k(a,"pulse-warning"),H();var l=t.getAttribute("data-mediaquery-id");N&&!g(t,"no-animation")?t.addEventListener(N,function c(){t.removeEventListener(N,c),g(t,"hide-swal2")&&(A(t),T(m(),0)),I(l)}):(A(t),A(m()),I(l)),null!==e&&"function"==typeof e&&e.call(this,t)},t.clickConfirm=function(){v().click()},t.clickCancel=function(){h().click()},t.init=function(){if("undefined"==typeof document)return void console.log("SweetAlert2 requires document to initialize");if(!document.getElementsByClassName(i.container).length){var e=document.createElement("div");e.className=i.container,e.innerHTML=l,document.body.appendChild(e);var n=f(),o=x(n,i.input),r=x(n,i.select),a=n.querySelector("#"+i.checkbox),c=x(n,i.textarea),s=x(n,i.image);o.oninput=function(){t.resetValidationError()},o.onkeyup=function(e){e.stopPropagation(),13===e.keyCode&&t.clickConfirm()},r.onchange=function(){t.resetValidationError()},a.onchange=function(){t.resetValidationError()},c.oninput=function(){t.resetValidationError()},s.onload=s.onerror=W,window.addEventListener("resize",W,!1)}},t.setDefaults=function(e){if(!e)throw new Error("userParams is required");if("object"!=typeof e)throw new Error("userParams has to be a object");c(j,e)},t.resetDefaults=function(){j=c({},a)},t.version="4.2.4",window.sweetAlert=window.swal=t,function(){"complete"===document.readyState||"interactive"===document.readyState&&document.body?t.init():document.addEventListener("DOMContentLoaded",function e(){document.removeEventListener("DOMContentLoaded",e,!1),t.init()},!1)}(),"function"==typeof Promise?Promise.prototype.done=Promise.prototype.done||function(){return this["catch"](function(){})}:console.warn("SweetAlert2: Please inlude Promise polyfill BEFORE including sweetalert2.js if IE10+ support needed."),t});
lang/ar_lang.php CHANGED
@@ -1,48 +1,48 @@
1
  <?php
2
 
3
- define('ahc_summary_statistics', 'إحصائية موجزة');
4
  define('ahc_visitors', 'الزوار');
5
- define('ahc_visits', 'المشاهدات');
6
- define('ahc_today', 'اليوم');
7
- define('ahc_yesterday', 'الأمس');
8
- define('ahc_this_week', 'هذ الأسبوع');
9
- define('ahc_this_month', 'هذا الشهر');
10
- define('ahc_this_yesr', 'هذا العام');
11
- define('ahc_total', 'المجموع');
12
 
13
  define('ahc_search_engines', 'محركات البحث');
14
- define('ahc_daily_total', 'المجموع اليومي');
15
 
16
  define('ahc_browsers', 'المتصفحات');
17
 
18
  define('ahc_refering_sites', 'أكثر المواقع المشيرة للموقع');
19
- define('ahc_total_times', 'عدد المرات');
20
- define('ahc_site_name', 'إسم الموقع');
21
 
22
  define('ahc_countries_visits_rank', 'ترتيب الدول حسب الزوار');
23
- define('ahc_country', 'الدولة');
24
- define('ahc_rank', 'الترتيب');
25
- define('ahc_flag', 'العلم');
26
 
27
  define('ahc_recent_visitors', 'اخر الزوار');
28
 
29
- define('ahc_latest_search_words', 'أخر الكلمات المستخدمة في البحث');
30
 
31
- define('ahc_today_visitors_on_map', 'زوار اليوم على الخريطة');
32
 
33
- define('ahc_visits_in_last_20days', 'المشاهدات في اخر '.AHC_VISITORS_VISITS_LIMIT.' يوم');
34
- define('ahc_no_visits_visitors', 'عدد الزوار والزيارات');
35
  define('ahc_search_engines_in_last_20days', 'محركات البحث بالنسبة للزيارات في اخر 20 يوم');
36
 
37
  define('traffic_by_title', 'الزيارات بالنسبة للمواضيع');
38
- define('ahc_title', 'العنوان');
39
  define('ahc_hits', 'المشاهدات');
40
- define('ahc_percent', 'النسبة');
41
 
42
  define('ahc_visits_time_graph', 'أوقات الزيارات');
43
- define('ahc_time', 'الوقت');
44
  define('ahc_visitors_graph', 'الزوار');
45
- define('ahc_pages', 'الصفجات');
46
 
47
- define('ahc_view_referer', 'عرض الرابط المشير');
48
  ?>
1
  <?php
2
 
3
+ define('ahcfree_summary_statistics', 'إحصائية موجزة');
4
  define('ahc_visitors', 'الزوار');
5
+ define('ahcfree_visits', 'المشاهدات');
6
+ define('ahcfree_today', 'اليوم');
7
+ define('ahcfree_yesterday', 'الأمس');
8
+ define('ahcfree_this_week', 'هذ الأسبوع');
9
+ define('ahcfree_this_month', 'هذا الشهر');
10
+ define('ahcfree_this_yesr', 'هذا العام');
11
+ define('ahcfree_total', 'المجموع');
12
 
13
  define('ahc_search_engines', 'محركات البحث');
14
+ define('ahcfree_daily_total', 'المجموع اليومي');
15
 
16
  define('ahc_browsers', 'المتصفحات');
17
 
18
  define('ahc_refering_sites', 'أكثر المواقع المشيرة للموقع');
19
+ define('ahcfree_total_times', 'عدد المرات');
20
+ define('ahcfree_site_name', 'إسم الموقع');
21
 
22
  define('ahc_countries_visits_rank', 'ترتيب الدول حسب الزوار');
23
+ define('ahcfree_country', 'الدولة');
24
+ define('ahcfree_rank', 'الترتيب');
25
+ define('ahcfree_flag', 'العلم');
26
 
27
  define('ahc_recent_visitors', 'اخر الزوار');
28
 
29
+ define('ahcfree_latest_search_words', 'أخر الكلمات المستخدمة في البحث');
30
 
31
+ define('ahcfree_today_visitors_on_map', 'زوار اليوم على الخريطة');
32
 
33
+ define('ahcfree_visits_in_last_20days', 'المشاهدات في اخر '.AHC_VISITORS_VISITS_LIMIT.' يوم');
34
+ define('ahcfree_no_visits_visitors', 'عدد الزوار والزيارات');
35
  define('ahc_search_engines_in_last_20days', 'محركات البحث بالنسبة للزيارات في اخر 20 يوم');
36
 
37
  define('traffic_by_title', 'الزيارات بالنسبة للمواضيع');
38
+ define('ahcfree_title', 'العنوان');
39
  define('ahc_hits', 'المشاهدات');
40
+ define('ahcfree_percent', 'النسبة');
41
 
42
  define('ahc_visits_time_graph', 'أوقات الزيارات');
43
+ define('ahcfree_time', 'الوقت');
44
  define('ahc_visitors_graph', 'الزوار');
45
+ define('ahcfree_pages', 'الصفجات');
46
 
47
+ define('ahcfree_view_referer', 'عرض الرابط المشير');
48
  ?>
lang/en_lang.php CHANGED
@@ -1,48 +1,48 @@
1
  <?php
2
 
3
- define('ahc_summary_statistics', 'Summary Statistics');
4
  define('ahc_visitors', 'Visitors');
5
- define('ahc_visits', 'Visits');
6
- define('ahc_today', 'Today');
7
- define('ahc_yesterday', 'Yesterday');
8
- define('ahc_this_week', 'This Week');
9
- define('ahc_this_month', 'This Month');
10
- define('ahc_this_yesr', 'This Year');
11
- define('ahc_total', 'Total');
12
 
13
  define('ahc_search_engines', 'Search Engines');
14
- define('ahc_daily_total', 'Daily Total');
15
 
16
  define('ahc_browsers', 'Browsers');
17
 
18
  define('ahc_refering_sites', 'Top Refering Sites');
19
- define('ahc_total_times', 'Total Times');
20
- define('ahc_site_name', 'Site Name');
21
 
22
  define('ahc_countries_visits_rank', 'Countries Rank in Order to Visitors');
23
- define('ahc_country', 'Country');
24
- define('ahc_rank', 'Rank');
25
- define('ahc_flag', 'Flag');
26
 
27
  define('ahc_recent_visitors', 'Recent Visitors');
28
 
29
- define('ahc_latest_search_words', 'Latest Search Words');
30
 
31
- define('ahc_today_visitors_on_map', 'Today Visitors on Map');
32
 
33
- define('ahc_visits_in_last_20days', 'Visits in the last '.AHC_VISITORS_VISITS_LIMIT.' days');
34
- define('ahc_no_visits_visitors', 'Number of visitors and visits');
35
  define('ahc_search_engines_in_last_20days', 'Referrer search engine in the last 20 days');
36
 
37
  define('traffic_by_title', 'Traffic by title');
38
- define('ahc_title', 'Title');
39
  define('ahc_hits', 'Hits');
40
- define('ahc_percent', 'Percent');
41
 
42
  define('ahc_visits_time_graph', 'Visits time graph');
43
- define('ahc_time', 'Time');
44
  define('ahc_visitors_graph', 'Visitors graph');
45
- define('ahc_pages', 'Pages');
46
 
47
- define('ahc_view_referer', 'View referer link');
48
  ?>
1
  <?php
2
 
3
+ define('ahcfree_summary_statistics', 'Summary Statistics');
4
  define('ahc_visitors', 'Visitors');
5
+ define('ahcfree_visits', 'Visits');
6
+ define('ahcfree_today', 'Today');
7
+ define('ahcfree_yesterday', 'Yesterday');
8
+ define('ahcfree_this_week', 'This Week');
9
+ define('ahcfree_this_month', 'This Month');
10
+ define('ahcfree_this_yesr', 'This Year');
11
+ define('ahcfree_total', 'Total');
12
 
13
  define('ahc_search_engines', 'Search Engines');
14
+ define('ahcfree_daily_total', 'Daily Total');
15
 
16
  define('ahc_browsers', 'Browsers');
17
 
18
  define('ahc_refering_sites', 'Top Refering Sites');
19
+ define('ahcfree_total_times', 'Total Times');
20
+ define('ahcfree_site_name', 'Site Name');
21
 
22
  define('ahc_countries_visits_rank', 'Countries Rank in Order to Visitors');
23
+ define('ahcfree_country', 'Country');
24
+ define('ahcfree_rank', 'Rank');
25
+ define('ahcfree_flag', 'Flag');
26
 
27
  define('ahc_recent_visitors', 'Recent Visitors');
28
 
29
+ define('ahcfree_latest_search_words', 'Latest Search Words');
30
 
31
+ define('ahcfree_today_visitors_on_map', 'Today Visitors on Map');
32
 
33
+ define('ahcfree_visits_in_last_20days', 'Visits in the last '.AHC_VISITORS_VISITS_LIMIT.' days');
34
+ define('ahcfree_no_visits_visitors', 'Number of visitors and visits');
35
  define('ahc_search_engines_in_last_20days', 'Referrer search engine in the last 20 days');
36
 
37
  define('traffic_by_title', 'Traffic by title');
38
+ define('ahcfree_title', 'Title');
39
  define('ahc_hits', 'Hits');
40
+ define('ahcfree_percent', 'Percent');
41
 
42
  define('ahc_visits_time_graph', 'Visits time graph');
43
+ define('ahcfree_time', 'Time');
44
  define('ahc_visitors_graph', 'Visitors graph');
45
+ define('ahcfree_pages', 'Pages');
46
 
47
+ define('ahcfree_view_referer', 'View referer link');
48
  ?>
lang/js/ar_lang.js CHANGED
@@ -1,5 +1,5 @@
1
 
2
  var ahc_visitors = 'الزوار';
3
- var ahc_visits = 'المشاهدات';
4
- var ahc_no_visits_visitors = 'عدد الزوار والزيارات';
5
- var ahc_no_visits = 'عدد الزيارات';
1
 
2
  var ahc_visitors = 'الزوار';
3
+ var ahcfree_visits = 'المشاهدات';
4
+ var ahcfree_no_visits_visitors = 'عدد الزوار والزيارات';
5
+ var ahcfree_no_visits = 'عدد الزيارات';
lang/js/en_lang.js CHANGED
@@ -1,5 +1,5 @@
1
 
2
  var ahc_visitors = 'Visitors';
3
- var ahc_visits = 'Visits';
4
- var ahc_no_visits_visitors = 'Number of visitors and visits';
5
- var ahc_no_visits = 'Number of visits';
1
 
2
  var ahc_visitors = 'Visitors';
3
+ var ahcfree_visits = 'Visits';
4
+ var ahcfree_no_visits_visitors = 'Number of visitors and visits';
5
+ var ahcfree_no_visits = 'Number of visits';
lib/Chart_js/.gitignore DELETED
@@ -1,7 +0,0 @@
1
-
2
- .DS_Store
3
-
4
- node_modules/*
5
- custom/*
6
-
7
- docs/index.md
 
 
 
 
 
 
 
lib/Chart_js/CONTRIBUTING.md DELETED
@@ -1,20 +0,0 @@
1
- Contributing
2
- ============
3
-
4
- New contributions to the library are welcome, just a couple of guidelines:
5
-
6
- * Tabs for indentation, not spaces please.
7
- * Please ensure you're changing the individual files in /src, not the concatenated output in the Chart.js file in the root of the repo.
8
- * Please check that your code will pass jshint code standards, `gulp jshint` will run this for you.
9
- * Please keep pull requests concise, and document new functionality in the relevant .md file.
10
- * Consider whether your changes are useful for all users, or if creating a Chart.js extension would be more appropriate.
11
- * Please avoid committing in the build Chart.js & Chart.min.js file, as it causes conflicts when merging.
12
-
13
- New Chart Types
14
- ===============
15
-
16
- Chart.js is designed to be modular. See http://www.chartjs.org/docs/#advanced-usage-writing-new-chart-types
17
-
18
- All discussion of new chart types (horizontal bar charts, X-Y scatter plot, etc.) should be done in the Chart.js Google Group at https://groups.google.com/forum/#!forum/chartjs-user-discussion This will get the most exposure for getting people to help define requirements, complete programming and documentation of your vision.
19
-
20
- Please do not request new chart types in the project issues. Fully implemented, documented, and useful new charts may be maintained in a new repository. Later, we may add a link to selected external repositories from this project.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/Chart.js DELETED
@@ -1,3379 +0,0 @@
1
- /*!
2
- * Chart.js
3
- * http://chartjs.org/
4
- * Version: 1.0.1-beta.4
5
- *
6
- * Copyright 2014 Nick Downie
7
- * Released under the MIT license
8
- * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
9
- */
10
-
11
-
12
- (function(){
13
-
14
- "use strict";
15
-
16
- //Declare root variable - window in the browser, global on the server
17
- var root = this,
18
- previous = root.Chart;
19
-
20
- //Occupy the global variable of Chart, and create a simple base class
21
- var Chart = function(context){
22
- var chart = this;
23
- this.canvas = context.canvas;
24
-
25
- this.ctx = context;
26
-
27
- //Variables global to the chart
28
- var width = this.width = context.canvas.width;
29
- var height = this.height = context.canvas.height;
30
- this.aspectRatio = this.width / this.height;
31
- //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
32
- helpers.retinaScale(this);
33
-
34
- return this;
35
- };
36
- //Globally expose the defaults to allow for user updating/changing
37
- Chart.defaults = {
38
- global: {
39
- // Boolean - Whether to animate the chart
40
- animation: true,
41
-
42
- // Number - Number of animation steps
43
- animationSteps: 60,
44
-
45
- // String - Animation easing effect
46
- animationEasing: "easeOutQuart",
47
-
48
- // Boolean - If we should show the scale at all
49
- showScale: true,
50
-
51
- // Boolean - If we want to override with a hard coded scale
52
- scaleOverride: false,
53
-
54
- // ** Required if scaleOverride is true **
55
- // Number - The number of steps in a hard coded scale
56
- scaleSteps: null,
57
- // Number - The value jump in the hard coded scale
58
- scaleStepWidth: null,
59
- // Number - The scale starting value
60
- scaleStartValue: null,
61
-
62
- // String - Colour of the scale line
63
- scaleLineColor: "rgba(0,0,0,.1)",
64
-
65
- // Number - Pixel width of the scale line
66
- scaleLineWidth: 1,
67
-
68
- // Boolean - Whether to show labels on the scale
69
- scaleShowLabels: true,
70
-
71
- // Interpolated JS string - can access value
72
- scaleLabel: "<%=value%>",
73
-
74
- // Boolean - Whether the scale should stick to integers, and not show any floats even if drawing space is there
75
- scaleIntegersOnly: true,
76
-
77
- // Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
78
- scaleBeginAtZero: false,
79
-
80
- // String - Scale label font declaration for the scale label
81
- scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
82
-
83
- // Number - Scale label font size in pixels
84
- scaleFontSize: 12,
85
-
86
- // String - Scale label font weight style
87
- scaleFontStyle: "normal",
88
-
89
- // String - Scale label font colour
90
- scaleFontColor: "#666",
91
-
92
- // Boolean - whether or not the chart should be responsive and resize when the browser does.
93
- responsive: false,
94
-
95
- // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
96
- maintainAspectRatio: true,
97
-
98
- // Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove
99
- showTooltips: true,
100
-
101
- // Array - Array of string names to attach tooltip events
102
- tooltipEvents: ["mousemove", "touchstart", "touchmove", "mouseout"],
103
-
104
- // String - Tooltip background colour
105
- tooltipFillColor: "rgba(0,0,0,0.8)",
106
-
107
- // String - Tooltip label font declaration for the scale label
108
- tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
109
-
110
- // Number - Tooltip label font size in pixels
111
- tooltipFontSize: 14,
112
-
113
- // String - Tooltip font weight style
114
- tooltipFontStyle: "normal",
115
-
116
- // String - Tooltip label font colour
117
- tooltipFontColor: "#fff",
118
-
119
- // String - Tooltip title font declaration for the scale label
120
- tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
121
-
122
- // Number - Tooltip title font size in pixels
123
- tooltipTitleFontSize: 14,
124
-
125
- // String - Tooltip title font weight style
126
- tooltipTitleFontStyle: "bold",
127
-
128
- // String - Tooltip title font colour
129
- tooltipTitleFontColor: "#fff",
130
-
131
- // Number - pixel width of padding around tooltip text
132
- tooltipYPadding: 6,
133
-
134
- // Number - pixel width of padding around tooltip text
135
- tooltipXPadding: 6,
136
-
137
- // Number - Size of the caret on the tooltip
138
- tooltipCaretSize: 8,
139
-
140
- // Number - Pixel radius of the tooltip border
141
- tooltipCornerRadius: 6,
142
-
143
- // Number - Pixel offset from point x to tooltip edge
144
- tooltipXOffset: 10,
145
-
146
- // String - Template string for single tooltips
147
- tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>",
148
-
149
- // String - Template string for single tooltips
150
- multiTooltipTemplate: "<%= value %>",
151
-
152
- // String - Colour behind the legend colour block
153
- multiTooltipKeyBackground: '#fff',
154
-
155
- // Function - Will fire on animation progression.
156
- onAnimationProgress: function(){},
157
-
158
- // Function - Will fire on animation completion.
159
- onAnimationComplete: function(){}
160
-
161
- }
162
- };
163
-
164
- //Create a dictionary of chart types, to allow for extension of existing types
165
- Chart.types = {};
166
-
167
- //Global Chart helpers object for utility methods and classes
168
- var helpers = Chart.helpers = {};
169
-
170
- //-- Basic js utility methods
171
- var each = helpers.each = function(loopable,callback,self){
172
- var additionalArgs = Array.prototype.slice.call(arguments, 3);
173
- // Check to see if null or undefined firstly.
174
- if (loopable){
175
- if (loopable.length === +loopable.length){
176
- var i;
177
- for (i=0; i<loopable.length; i++){
178
- callback.apply(self,[loopable[i], i].concat(additionalArgs));
179
- }
180
- }
181
- else{
182
- for (var item in loopable){
183
- callback.apply(self,[loopable[item],item].concat(additionalArgs));
184
- }
185
- }
186
- }
187
- },
188
- clone = helpers.clone = function(obj){
189
- var objClone = {};
190
- each(obj,function(value,key){
191
- if (obj.hasOwnProperty(key)) objClone[key] = value;
192
- });
193
- return objClone;
194
- },
195
- extend = helpers.extend = function(base){
196
- each(Array.prototype.slice.call(arguments,1), function(extensionObject) {
197
- each(extensionObject,function(value,key){
198
- if (extensionObject.hasOwnProperty(key)) base[key] = value;
199
- });
200
- });
201
- return base;
202
- },
203
- merge = helpers.merge = function(base,master){
204
- //Merge properties in left object over to a shallow clone of object right.
205
- var args = Array.prototype.slice.call(arguments,0);
206
- args.unshift({});
207
- return extend.apply(null, args);
208
- },
209
- indexOf = helpers.indexOf = function(arrayToSearch, item){
210
- if (Array.prototype.indexOf) {
211
- return arrayToSearch.indexOf(item);
212
- }
213
- else{
214
- for (var i = 0; i < arrayToSearch.length; i++) {
215
- if (arrayToSearch[i] === item) return i;
216
- }
217
- return -1;
218
- }
219
- },
220
- where = helpers.where = function(collection, filterCallback){
221
- var filtered = [];
222
-
223
- helpers.each(collection, function(item){
224
- if (filterCallback(item)){
225
- filtered.push(item);
226
- }
227
- });
228
-
229
- return filtered;
230
- },
231
- findNextWhere = helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex){
232
- // Default to start of the array
233
- if (!startIndex){
234
- startIndex = -1;
235
- }
236
- for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
237
- var currentItem = arrayToSearch[i];
238
- if (filterCallback(currentItem)){
239
- return currentItem;
240
- }
241
- };
242
- },
243
- findPreviousWhere = helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex){
244
- // Default to end of the array
245
- if (!startIndex){
246
- startIndex = arrayToSearch.length;
247
- }
248
- for (var i = startIndex - 1; i >= 0; i--) {
249
- var currentItem = arrayToSearch[i];
250
- if (filterCallback(currentItem)){
251
- return currentItem;
252
- }
253
- };
254
- },
255
- inherits = helpers.inherits = function(extensions){
256
- //Basic javascript inheritance based on the model created in Backbone.js
257
- var parent = this;
258
- var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function(){ return parent.apply(this, arguments); };
259
-
260
- var Surrogate = function(){ this.constructor = ChartElement;};
261
- Surrogate.prototype = parent.prototype;
262
- ChartElement.prototype = new Surrogate();
263
-
264
- ChartElement.extend = inherits;
265
-
266
- if (extensions) extend(ChartElement.prototype, extensions);
267
-
268
- ChartElement.__super__ = parent.prototype;
269
-
270
- return ChartElement;
271
- },
272
- noop = helpers.noop = function(){},
273
- uid = helpers.uid = (function(){
274
- var id=0;
275
- return function(){
276
- return "chart-" + id++;
277
- };
278
- })(),
279
- warn = helpers.warn = function(str){
280
- //Method for warning of errors
281
- if (window.console && typeof window.console.warn == "function") console.warn(str);
282
- },
283
- amd = helpers.amd = (typeof define == 'function' && define.amd),
284
- //-- Math methods
285
- isNumber = helpers.isNumber = function(n){
286
- return !isNaN(parseFloat(n)) && isFinite(n);
287
- },
288
- max = helpers.max = function(array){
289
- return Math.max.apply( Math, array );
290
- },
291
- min = helpers.min = function(array){
292
- return Math.min.apply( Math, array );
293
- },
294
- cap = helpers.cap = function(valueToCap,maxValue,minValue){
295
- if(isNumber(maxValue)) {
296
- if( valueToCap > maxValue ) {
297
- return maxValue;
298
- }
299
- }
300
- else if(isNumber(minValue)){
301
- if ( valueToCap < minValue ){
302
- return minValue;
303
- }
304
- }
305
- return valueToCap;
306
- },
307
- getDecimalPlaces = helpers.getDecimalPlaces = function(num){
308
- if (num%1!==0 && isNumber(num)){
309
- return num.toString().split(".")[1].length;
310
- }
311
- else {
312
- return 0;
313
- }
314
- },
315
- toRadians = helpers.radians = function(degrees){
316
- return degrees * (Math.PI/180);
317
- },
318
- // Gets the angle from vertical upright to the point about a centre.
319
- getAngleFromPoint = helpers.getAngleFromPoint = function(centrePoint, anglePoint){
320
- var distanceFromXCenter = anglePoint.x - centrePoint.x,
321
- distanceFromYCenter = anglePoint.y - centrePoint.y,
322
- radialDistanceFromCenter = Math.sqrt( distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
323
-
324
-
325
- var angle = Math.PI * 2 + Math.atan2(distanceFromYCenter, distanceFromXCenter);
326
-
327
- //If the segment is in the top left quadrant, we need to add another rotation to the angle
328
- if (distanceFromXCenter < 0 && distanceFromYCenter < 0){
329
- angle += Math.PI*2;
330
- }
331
-
332
- return {
333
- angle: angle,
334
- distance: radialDistanceFromCenter
335
- };
336
- },
337
- aliasPixel = helpers.aliasPixel = function(pixelWidth){
338
- return (pixelWidth % 2 === 0) ? 0 : 0.5;
339
- },
340
- splineCurve = helpers.splineCurve = function(FirstPoint,MiddlePoint,AfterPoint,t){
341
- //Props to Rob Spencer at scaled innovation for his post on splining between points
342
- //http://scaledinnovation.com/analytics/splines/aboutSplines.html
343
- var d01=Math.sqrt(Math.pow(MiddlePoint.x-FirstPoint.x,2)+Math.pow(MiddlePoint.y-FirstPoint.y,2)),
344
- d12=Math.sqrt(Math.pow(AfterPoint.x-MiddlePoint.x,2)+Math.pow(AfterPoint.y-MiddlePoint.y,2)),
345
- fa=t*d01/(d01+d12),// scaling factor for triangle Ta
346
- fb=t*d12/(d01+d12);
347
- return {
348
- inner : {
349
- x : MiddlePoint.x-fa*(AfterPoint.x-FirstPoint.x),
350
- y : MiddlePoint.y-fa*(AfterPoint.y-FirstPoint.y)
351
- },
352
- outer : {
353
- x: MiddlePoint.x+fb*(AfterPoint.x-FirstPoint.x),
354
- y : MiddlePoint.y+fb*(AfterPoint.y-FirstPoint.y)
355
- }
356
- };
357
- },
358
- calculateOrderOfMagnitude = helpers.calculateOrderOfMagnitude = function(val){
359
- return Math.floor(Math.log(val) / Math.LN10);
360
- },
361
- calculateScaleRange = helpers.calculateScaleRange = function(valuesArray, drawingSize, textSize, startFromZero, integersOnly){
362
-
363
- //Set a minimum step of two - a point at the top of the graph, and a point at the base
364
- var minSteps = 2,
365
- maxSteps = Math.floor(drawingSize/(textSize * 1.5)),
366
- skipFitting = (minSteps >= maxSteps);
367
-
368
- var maxValue = max(valuesArray),
369
- minValue = min(valuesArray);
370
-
371
- // We need some degree of seperation here to calculate the scales if all the values are the same
372
- // Adding/minusing 0.5 will give us a range of 1.
373
- if (maxValue === minValue){
374
- maxValue += 0.5;
375
- // So we don't end up with a graph with a negative start value if we've said always start from zero
376
- if (minValue >= 0.5 && !startFromZero){
377
- minValue -= 0.5;
378
- }
379
- else{
380
- // Make up a whole number above the values
381
- maxValue += 0.5;
382
- }
383
- }
384
-
385
- var valueRange = Math.abs(maxValue - minValue),
386
- rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange),
387
- graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),
388
- graphMin = (startFromZero) ? 0 : Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),
389
- graphRange = graphMax - graphMin,
390
- stepValue = Math.pow(10, rangeOrderOfMagnitude),
391
- numberOfSteps = Math.round(graphRange / stepValue);
392
-
393
- //If we have more space on the graph we'll use it to give more definition to the data
394
- while((numberOfSteps > maxSteps || (numberOfSteps * 2) < maxSteps) && !skipFitting) {
395
- if(numberOfSteps > maxSteps){
396
- stepValue *=2;
397
- numberOfSteps = Math.round(graphRange/stepValue);
398
- // Don't ever deal with a decimal number of steps - cancel fitting and just use the minimum number of steps.
399
- if (numberOfSteps % 1 !== 0){
400
- skipFitting = true;
401
- }
402
- }
403
- //We can fit in double the amount of scale points on the scale
404
- else{
405
- //If user has declared ints only, and the step value isn't a decimal
406
- if (integersOnly && rangeOrderOfMagnitude >= 0){
407
- //If the user has said integers only, we need to check that making the scale more granular wouldn't make it a float
408
- if(stepValue/2 % 1 === 0){
409
- stepValue /=2;
410
- numberOfSteps = Math.round(graphRange/stepValue);
411
- }
412
- //If it would make it a float break out of the loop
413
- else{
414
- break;
415
- }
416
- }
417
- //If the scale doesn't have to be an int, make the scale more granular anyway.
418
- else{
419
- stepValue /=2;
420
- numberOfSteps = Math.round(graphRange/stepValue);
421
- }
422
-
423
- }
424
- }
425
-
426
- if (skipFitting){
427
- numberOfSteps = minSteps;
428
- stepValue = graphRange / numberOfSteps;
429
- }
430
-
431
- return {
432
- steps : numberOfSteps,
433
- stepValue : stepValue,
434
- min : graphMin,
435
- max : graphMin + (numberOfSteps * stepValue)
436
- };
437
-
438
- },
439
- /* jshint ignore:start */
440
- // Blows up jshint errors based on the new Function constructor
441
- //Templating methods
442
- //Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/
443
- template = helpers.template = function(templateString, valuesObject){
444
- // If templateString is function rather than string-template - call the function for valuesObject
445
- if(templateString instanceof Function){
446
- return templateString(valuesObject);
447
- }
448
-
449
- var cache = {};
450
- function tmpl(str, data){
451
- // Figure out if we're getting a template, or if we need to
452
- // load the template - and be sure to cache the result.
453
- var fn = !/\W/.test(str) ?
454
- cache[str] = cache[str] :
455
-
456
- // Generate a reusable function that will serve as a template
457
- // generator (and which will be cached).
458
- new Function("obj",
459
- "var p=[],print=function(){p.push.apply(p,arguments);};" +
460
-
461
- // Introduce the data as local variables using with(){}
462
- "with(obj){p.push('" +
463
-
464
- // Convert the template into pure JavaScript
465
- str
466
- .replace(/[\r\t\n]/g, " ")
467
- .split("<%").join("\t")
468
- .replace(/((^|%>)[^\t]*)'/g, "$1\r")
469
- .replace(/\t=(.*?)%>/g, "',$1,'")
470
- .split("\t").join("');")
471
- .split("%>").join("p.push('")
472
- .split("\r").join("\\'") +
473
- "');}return p.join('');"
474
- );
475
-
476
- // Provide some basic currying to the user
477
- return data ? fn( data ) : fn;
478
- }
479
- return tmpl(templateString,valuesObject);
480
- },
481
- /* jshint ignore:end */
482
- generateLabels = helpers.generateLabels = function(templateString,numberOfSteps,graphMin,stepValue){
483
- var labelsArray = new Array(numberOfSteps);
484
- if (labelTemplateString){
485
- each(labelsArray,function(val,index){
486
- labelsArray[index] = template(templateString,{value: (graphMin + (stepValue*(index+1)))});
487
- });
488
- }
489
- return labelsArray;
490
- },
491
- //--Animation methods
492
- //Easing functions adapted from Robert Penner's easing equations
493
- //http://www.robertpenner.com/easing/
494
- easingEffects = helpers.easingEffects = {
495
- linear: function (t) {
496
- return t;
497
- },
498
- easeInQuad: function (t) {
499
- return t * t;
500
- },
501
- easeOutQuad: function (t) {
502
- return -1 * t * (t - 2);
503
- },
504
- easeInOutQuad: function (t) {
505
- if ((t /= 1 / 2) < 1) return 1 / 2 * t * t;
506
- return -1 / 2 * ((--t) * (t - 2) - 1);
507
- },
508
- easeInCubic: function (t) {
509
- return t * t * t;
510
- },
511
- easeOutCubic: function (t) {
512
- return 1 * ((t = t / 1 - 1) * t * t + 1);
513
- },
514
- easeInOutCubic: function (t) {
515
- if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t;
516
- return 1 / 2 * ((t -= 2) * t * t + 2);
517
- },
518
- easeInQuart: function (t) {
519
- return t * t * t * t;
520
- },
521
- easeOutQuart: function (t) {
522
- return -1 * ((t = t / 1 - 1) * t * t * t - 1);
523
- },
524
- easeInOutQuart: function (t) {
525
- if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t;
526
- return -1 / 2 * ((t -= 2) * t * t * t - 2);
527
- },
528
- easeInQuint: function (t) {
529
- return 1 * (t /= 1) * t * t * t * t;
530
- },
531
- easeOutQuint: function (t) {
532
- return 1 * ((t = t / 1 - 1) * t * t * t * t + 1);
533
- },
534
- easeInOutQuint: function (t) {
535
- if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t * t;
536
- return 1 / 2 * ((t -= 2) * t * t * t * t + 2);
537
- },
538
- easeInSine: function (t) {
539
- return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;
540
- },
541
- easeOutSine: function (t) {
542
- return 1 * Math.sin(t / 1 * (Math.PI / 2));
543
- },
544
- easeInOutSine: function (t) {
545
- return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);
546
- },
547
- easeInExpo: function (t) {
548
- return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));
549
- },
550
- easeOutExpo: function (t) {
551
- return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);
552
- },
553
- easeInOutExpo: function (t) {
554
- if (t === 0) return 0;
555
- if (t === 1) return 1;
556
- if ((t /= 1 / 2) < 1) return 1 / 2 * Math.pow(2, 10 * (t - 1));
557
- return 1 / 2 * (-Math.pow(2, -10 * --t) + 2);
558
- },
559
- easeInCirc: function (t) {
560
- if (t >= 1) return t;
561
- return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);
562
- },
563
- easeOutCirc: function (t) {
564
- return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);
565
- },
566
- easeInOutCirc: function (t) {
567
- if ((t /= 1 / 2) < 1) return -1 / 2 * (Math.sqrt(1 - t * t) - 1);
568
- return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);
569
- },
570
- easeInElastic: function (t) {
571
- var s = 1.70158;
572
- var p = 0;
573
- var a = 1;
574
- if (t === 0) return 0;
575
- if ((t /= 1) == 1) return 1;
576
- if (!p) p = 1 * 0.3;
577
- if (a < Math.abs(1)) {
578
- a = 1;
579
- s = p / 4;
580
- } else s = p / (2 * Math.PI) * Math.asin(1 / a);
581
- return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
582
- },
583
- easeOutElastic: function (t) {
584
- var s = 1.70158;
585
- var p = 0;
586
- var a = 1;
587
- if (t === 0) return 0;
588
- if ((t /= 1) == 1) return 1;
589
- if (!p) p = 1 * 0.3;
590
- if (a < Math.abs(1)) {
591
- a = 1;
592
- s = p / 4;
593
- } else s = p / (2 * Math.PI) * Math.asin(1 / a);
594
- return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;
595
- },
596
- easeInOutElastic: function (t) {
597
- var s = 1.70158;
598
- var p = 0;
599
- var a = 1;
600
- if (t === 0) return 0;
601
- if ((t /= 1 / 2) == 2) return 1;
602
- if (!p) p = 1 * (0.3 * 1.5);
603
- if (a < Math.abs(1)) {
604
- a = 1;
605
- s = p / 4;
606
- } else s = p / (2 * Math.PI) * Math.asin(1 / a);
607
- if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
608
- return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;
609
- },
610
- easeInBack: function (t) {
611
- var s = 1.70158;
612
- return 1 * (t /= 1) * t * ((s + 1) * t - s);
613
- },
614
- easeOutBack: function (t) {
615
- var s = 1.70158;
616
- return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);
617
- },
618
- easeInOutBack: function (t) {
619
- var s = 1.70158;
620
- if ((t /= 1 / 2) < 1) return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));
621
- return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
622
- },
623
- easeInBounce: function (t) {
624
- return 1 - easingEffects.easeOutBounce(1 - t);
625
- },
626
- easeOutBounce: function (t) {
627
- if ((t /= 1) < (1 / 2.75)) {
628
- return 1 * (7.5625 * t * t);
629
- } else if (t < (2 / 2.75)) {
630
- return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);
631
- } else if (t < (2.5 / 2.75)) {
632
- return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);
633
- } else {
634
- return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);
635
- }
636
- },
637
- easeInOutBounce: function (t) {
638
- if (t < 1 / 2) return easingEffects.easeInBounce(t * 2) * 0.5;
639
- return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;
640
- }
641
- },
642
- //Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
643
- requestAnimFrame = helpers.requestAnimFrame = (function(){
644
- return window.requestAnimationFrame ||
645
- window.webkitRequestAnimationFrame ||
646
- window.mozRequestAnimationFrame ||
647
- window.oRequestAnimationFrame ||
648
- window.msRequestAnimationFrame ||
649
- function(callback) {
650
- return window.setTimeout(callback, 1000 / 60);
651
- };
652
- })(),
653
- cancelAnimFrame = helpers.cancelAnimFrame = (function(){
654
- return window.cancelAnimationFrame ||
655
- window.webkitCancelAnimationFrame ||
656
- window.mozCancelAnimationFrame ||
657
- window.oCancelAnimationFrame ||
658
- window.msCancelAnimationFrame ||
659
- function(callback) {
660
- return window.clearTimeout(callback, 1000 / 60);
661
- };
662
- })(),
663
- animationLoop = helpers.animationLoop = function(callback,totalSteps,easingString,onProgress,onComplete,chartInstance){
664
-
665
- var currentStep = 0,
666
- easingFunction = easingEffects[easingString] || easingEffects.linear;
667
-
668
- var animationFrame = function(){
669
- currentStep++;
670
- var stepDecimal = currentStep/totalSteps;
671
- var easeDecimal = easingFunction(stepDecimal);
672
-
673
- callback.call(chartInstance,easeDecimal,stepDecimal, currentStep);
674
- onProgress.call(chartInstance,easeDecimal,stepDecimal);
675
- if (currentStep < totalSteps){
676
- chartInstance.animationFrame = requestAnimFrame(animationFrame);
677
- } else{
678
- onComplete.apply(chartInstance);
679
- }
680
- };
681
- requestAnimFrame(animationFrame);
682
- },
683
- //-- DOM methods
684
- getRelativePosition = helpers.getRelativePosition = function(evt){
685
- var mouseX, mouseY;
686
- var e = evt.originalEvent || evt,
687
- canvas = evt.currentTarget || evt.srcElement,
688
- boundingRect = canvas.getBoundingClientRect();
689
-
690
- if (e.touches){
691
- mouseX = e.touches[0].clientX - boundingRect.left;
692
- mouseY = e.touches[0].clientY - boundingRect.top;
693
-
694
- }
695
- else{
696
- mouseX = e.clientX - boundingRect.left;
697
- mouseY = e.clientY - boundingRect.top;
698
- }
699
-
700
- return {
701
- x : mouseX,
702
- y : mouseY
703
- };
704
-
705
- },
706
- addEvent = helpers.addEvent = function(node,eventType,method){
707
- if (node.addEventListener){
708
- node.addEventListener(eventType,method);
709
- } else if (node.attachEvent){
710
- node.attachEvent("on"+eventType, method);
711
- } else {
712
- node["on"+eventType] = method;
713
- }
714
- },
715
- removeEvent = helpers.removeEvent = function(node, eventType, handler){
716
- if (node.removeEventListener){
717
- node.removeEventListener(eventType, handler, false);
718
- } else if (node.detachEvent){
719
- node.detachEvent("on"+eventType,handler);
720
- } else{
721
- node["on" + eventType] = noop;
722
- }
723
- },
724
- bindEvents = helpers.bindEvents = function(chartInstance, arrayOfEvents, handler){
725
- // Create the events object if it's not already present
726
- if (!chartInstance.events) chartInstance.events = {};
727
-
728
- each(arrayOfEvents,function(eventName){
729
- chartInstance.events[eventName] = function(){
730
- handler.apply(chartInstance, arguments);
731
- };
732
- addEvent(chartInstance.chart.canvas,eventName,chartInstance.events[eventName]);
733
- });
734
- },
735
- unbindEvents = helpers.unbindEvents = function (chartInstance, arrayOfEvents) {
736
- each(arrayOfEvents, function(handler,eventName){
737
- removeEvent(chartInstance.chart.canvas, eventName, handler);
738
- });
739
- },
740
- getMaximumWidth = helpers.getMaximumWidth = function(domNode){
741
- var container = domNode.parentNode;
742
- // TODO = check cross browser stuff with this.
743
- return container.clientWidth;
744
- },
745
- getMaximumHeight = helpers.getMaximumHeight = function(domNode){
746
- var container = domNode.parentNode;
747
- // TODO = check cross browser stuff with this.
748
- return container.clientHeight;
749
- },
750
- getMaximumSize = helpers.getMaximumSize = helpers.getMaximumWidth, // legacy support
751
- retinaScale = helpers.retinaScale = function(chart){
752
- var ctx = chart.ctx,
753
- width = chart.canvas.width,
754
- height = chart.canvas.height;
755
-
756
- if (window.devicePixelRatio) {
757
- ctx.canvas.style.width = width + "px";
758
- ctx.canvas.style.height = height + "px";
759
- ctx.canvas.height = height * window.devicePixelRatio;
760
- ctx.canvas.width = width * window.devicePixelRatio;
761
- ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
762
- }
763
- },
764
- //-- Canvas methods
765
- clear = helpers.clear = function(chart){
766
- chart.ctx.clearRect(0,0,chart.width,chart.height);
767
- },
768
- fontString = helpers.fontString = function(pixelSize,fontStyle,fontFamily){
769
- return fontStyle + " " + pixelSize+"px " + fontFamily;
770
- },
771
- longestText = helpers.longestText = function(ctx,font,arrayOfStrings){
772
- ctx.font = font;
773
- var longest = 0;
774
- each(arrayOfStrings,function(string){
775
- var textWidth = ctx.measureText(string).width;
776
- longest = (textWidth > longest) ? textWidth : longest;
777
- });
778
- return longest;
779
- },
780
- drawRoundedRectangle = helpers.drawRoundedRectangle = function(ctx,x,y,width,height,radius){
781
- ctx.beginPath();
782
- ctx.moveTo(x + radius, y);
783
- ctx.lineTo(x + width - radius, y);
784
- ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
785
- ctx.lineTo(x + width, y + height - radius);
786
- ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
787
- ctx.lineTo(x + radius, y + height);
788
- ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
789
- ctx.lineTo(x, y + radius);
790
- ctx.quadraticCurveTo(x, y, x + radius, y);
791
- ctx.closePath();
792
- };
793
-
794
-
795
- //Store a reference to each instance - allowing us to globally resize chart instances on window resize.
796
- //Destroy method on the chart will remove the instance of the chart from this reference.
797
- Chart.instances = {};
798
-
799
- Chart.Type = function(data,options,chart){
800
- this.options = options;
801
- this.chart = chart;
802
- this.id = uid();
803
- //Add the chart instance to the global namespace
804
- Chart.instances[this.id] = this;
805
-
806
- // Initialize is always called when a chart type is created
807
- // By default it is a no op, but it should be extended
808
- if (options.responsive){
809
- this.resize();
810
- }
811
- this.initialize.call(this,data);
812
- };
813
-
814
- //Core methods that'll be a part of every chart type
815
- extend(Chart.Type.prototype,{
816
- initialize : function(){return this;},
817
- clear : function(){
818
- clear(this.chart);
819
- return this;
820
- },
821
- stop : function(){
822
- // Stops any current animation loop occuring
823
- helpers.cancelAnimFrame.call(root, this.animationFrame);
824
- return this;
825
- },
826
- resize : function(callback){
827
- this.stop();
828
- var canvas = this.chart.canvas,
829
- newWidth = getMaximumWidth(this.chart.canvas),
830
- newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas);
831
-
832
- canvas.width = this.chart.width = newWidth;
833
- canvas.height = this.chart.height = newHeight;
834
-
835
- retinaScale(this.chart);
836
-
837
- if (typeof callback === "function"){
838
- callback.apply(this, Array.prototype.slice.call(arguments, 1));
839
- }
840
- return this;
841
- },
842
- reflow : noop,
843
- render : function(reflow){
844
- if (reflow){
845
- this.reflow();
846
- }
847
- if (this.options.animation && !reflow){
848
- helpers.animationLoop(
849
- this.draw,
850
- this.options.animationSteps,
851
- this.options.animationEasing,
852
- this.options.onAnimationProgress,
853
- this.options.onAnimationComplete,
854
- this
855
- );
856
- }
857
- else{
858
- this.draw();
859
- this.options.onAnimationComplete.call(this);
860
- }
861
- return this;
862
- },
863
- generateLegend : function(){
864
- return template(this.options.legendTemplate,this);
865
- },
866
- destroy : function(){
867
- this.clear();
868
- unbindEvents(this, this.events);
869
- delete Chart.instances[this.id];
870
- },
871
- showTooltip : function(ChartElements, forceRedraw){
872
- // Only redraw the chart if we've actually changed what we're hovering on.
873
- if (typeof this.activeElements === 'undefined') this.activeElements = [];
874
-
875
- var isChanged = (function(Elements){
876
- var changed = false;
877
-
878
- if (Elements.length !== this.activeElements.length){
879
- changed = true;
880
- return changed;
881
- }
882
-
883
- each(Elements, function(element, index){
884
- if (element !== this.activeElements[index]){
885
- changed = true;
886
- }
887
- }, this);
888
- return changed;
889
- }).call(this, ChartElements);
890
-
891
- if (!isChanged && !forceRedraw){
892
- return;
893
- }
894
- else{
895
- this.activeElements = ChartElements;
896
- }
897
- this.draw();
898
- if (ChartElements.length > 0){
899
- // If we have multiple datasets, show a MultiTooltip for all of the data points at that index
900
- if (this.datasets && this.datasets.length > 1) {
901
- var dataArray,
902
- dataIndex;
903
-
904
- for (var i = this.datasets.length - 1; i >= 0; i--) {
905
- dataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;
906
- dataIndex = indexOf(dataArray, ChartElements[0]);
907
- if (dataIndex !== -1){
908
- break;
909
- }
910
- }
911
- var tooltipLabels = [],
912
- tooltipColors = [],
913
- medianPosition = (function(index) {
914
-
915
- // Get all the points at that particular index
916
- var Elements = [],
917
- dataCollection,
918
- xPositions = [],
919
- yPositions = [],
920
- xMax,
921
- yMax,
922
- xMin,
923
- yMin;
924
- helpers.each(this.datasets, function(dataset){
925
- dataCollection = dataset.points || dataset.bars || dataset.segments;
926
- if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){
927
- Elements.push(dataCollection[dataIndex]);
928
- }
929
- });
930
-
931
- helpers.each(Elements, function(element) {
932
- xPositions.push(element.x);
933
- yPositions.push(element.y);
934
-
935
-
936
- //Include any colour information about the element
937
- tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element));
938
- tooltipColors.push({
939
- fill: element._saved.fillColor || element.fillColor,
940
- stroke: element._saved.strokeColor || element.strokeColor
941
- });
942
-
943
- }, this);
944
-
945
- yMin = min(yPositions);
946
- yMax = max(yPositions);
947
-
948
- xMin = min(xPositions);
949
- xMax = max(xPositions);
950
-
951
- return {
952
- x: (xMin > this.chart.width/2) ? xMin : xMax,
953
- y: (yMin + yMax)/2
954
- };
955
- }).call(this, dataIndex);
956
-
957
- new Chart.MultiTooltip({
958
- x: medianPosition.x,
959
- y: medianPosition.y,
960
- xPadding: this.options.tooltipXPadding,
961
- yPadding: this.options.tooltipYPadding,
962
- xOffset: this.options.tooltipXOffset,
963
- fillColor: this.options.tooltipFillColor,
964
- textColor: this.options.tooltipFontColor,
965
- fontFamily: this.options.tooltipFontFamily,
966
- fontStyle: this.options.tooltipFontStyle,
967
- fontSize: this.options.tooltipFontSize,
968
- titleTextColor: this.options.tooltipTitleFontColor,
969
- titleFontFamily: this.options.tooltipTitleFontFamily,
970
- titleFontStyle: this.options.tooltipTitleFontStyle,
971
- titleFontSize: this.options.tooltipTitleFontSize,
972
- cornerRadius: this.options.tooltipCornerRadius,
973
- labels: tooltipLabels,
974
- legendColors: tooltipColors,
975
- legendColorBackground : this.options.multiTooltipKeyBackground,
976
- title: ChartElements[0].label,
977
- chart: this.chart,
978
- ctx: this.chart.ctx
979
- }).draw();
980
-
981
- } else {
982
- each(ChartElements, function(Element) {
983
- var tooltipPosition = Element.tooltipPosition();
984
- new Chart.Tooltip({
985
- x: Math.round(tooltipPosition.x),
986
- y: Math.round(tooltipPosition.y),
987
- xPadding: this.options.tooltipXPadding,
988
- yPadding: this.options.tooltipYPadding,
989
- fillColor: this.options.tooltipFillColor,
990
- textColor: this.options.tooltipFontColor,
991
- fontFamily: this.options.tooltipFontFamily,
992
- fontStyle: this.options.tooltipFontStyle,
993
- fontSize: this.options.tooltipFontSize,
994
- caretHeight: this.options.tooltipCaretSize,
995
- cornerRadius: this.options.tooltipCornerRadius,
996
- text: template(this.options.tooltipTemplate, Element),
997
- chart: this.chart
998
- }).draw();
999
- }, this);
1000
- }
1001
- }
1002
- return this;
1003
- },
1004
- toBase64Image : function(){
1005
- return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
1006
- }
1007
- });
1008
-
1009
- Chart.Type.extend = function(extensions){
1010
-
1011
- var parent = this;
1012
-
1013
- var ChartType = function(){
1014
- return parent.apply(this,arguments);
1015
- };
1016
-
1017
- //Copy the prototype object of the this class
1018
- ChartType.prototype = clone(parent.prototype);
1019
- //Now overwrite some of the properties in the base class with the new extensions
1020
- extend(ChartType.prototype, extensions);
1021
-
1022
- ChartType.extend = Chart.Type.extend;
1023
-
1024
- if (extensions.name || parent.prototype.name){
1025
-
1026
- var chartName = extensions.name || parent.prototype.name;
1027
- //Assign any potential default values of the new chart type
1028
-
1029
- //If none are defined, we'll use a clone of the chart type this is being extended from.
1030
- //I.e. if we extend a line chart, we'll use the defaults from the line chart if our new chart
1031
- //doesn't define some defaults of their own.
1032
-
1033
- var baseDefaults = (Chart.defaults[parent.prototype.name]) ? clone(Chart.defaults[parent.prototype.name]) : {};
1034
-
1035
- Chart.defaults[chartName] = extend(baseDefaults,extensions.defaults);
1036
-
1037
- Chart.types[chartName] = ChartType;
1038
-
1039
- //Register this new chart type in the Chart prototype
1040
- Chart.prototype[chartName] = function(data,options){
1041
- var config = merge(Chart.defaults.global, Chart.defaults[chartName], options || {});
1042
- return new ChartType(data,config,this);
1043
- };
1044
- } else{
1045
- warn("Name not provided for this chart, so it hasn't been registered");
1046
- }
1047
- return parent;
1048
- };
1049
-
1050
- Chart.Element = function(configuration){
1051
- extend(this,configuration);
1052
- this.initialize.apply(this,arguments);
1053
- this.save();
1054
- };
1055
- extend(Chart.Element.prototype,{
1056
- initialize : function(){},
1057
- restore : function(props){
1058
- if (!props){
1059
- extend(this,this._saved);
1060
- } else {
1061
- each(props,function(key){
1062
- this[key] = this._saved[key];
1063
- },this);
1064
- }
1065
- return this;
1066
- },
1067
- save : function(){
1068
- this._saved = clone(this);
1069
- delete this._saved._saved;
1070
- return this;
1071
- },
1072
- update : function(newProps){
1073
- each(newProps,function(value,key){
1074
- this._saved[key] = this[key];
1075
- this[key] = value;
1076
- },this);
1077
- return this;
1078
- },
1079
- transition : function(props,ease){
1080
- each(props,function(value,key){
1081
- this[key] = ((value - this._saved[key]) * ease) + this._saved[key];
1082
- },this);
1083
- return this;
1084
- },
1085
- tooltipPosition : function(){
1086
- return {
1087
- x : this.x,
1088
- y : this.y
1089
- };
1090
- },
1091
- hasValue: function(){
1092
- return isNumber(this.value);
1093
- }
1094
- });
1095
-
1096
- Chart.Element.extend = inherits;
1097
-
1098
-
1099
- Chart.Point = Chart.Element.extend({
1100
- display: true,
1101
- inRange: function(chartX,chartY){
1102
- var hitDetectionRange = this.hitDetectionRadius + this.radius;
1103
- return ((Math.pow(chartX-this.x, 2)+Math.pow(chartY-this.y, 2)) < Math.pow(hitDetectionRange,2));
1104
- },
1105
- draw : function(){
1106
- if (this.display){
1107
- var ctx = this.ctx;
1108
- ctx.beginPath();
1109
-
1110
- ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
1111
- ctx.closePath();
1112
-
1113
- ctx.strokeStyle = this.strokeColor;
1114
- ctx.lineWidth = this.strokeWidth;
1115
-
1116
- ctx.fillStyle = this.fillColor;
1117
-
1118
- ctx.fill();
1119
- ctx.stroke();
1120
- }
1121
-
1122
-
1123
- //Quick debug for bezier curve splining
1124
- //Highlights control points and the line between them.
1125
- //Handy for dev - stripped in the min version.
1126
-
1127
- // ctx.save();
1128
- // ctx.fillStyle = "black";
1129
- // ctx.strokeStyle = "black"
1130
- // ctx.beginPath();
1131
- // ctx.arc(this.controlPoints.inner.x,this.controlPoints.inner.y, 2, 0, Math.PI*2);
1132
- // ctx.fill();
1133
-
1134
- // ctx.beginPath();
1135
- // ctx.arc(this.controlPoints.outer.x,this.controlPoints.outer.y, 2, 0, Math.PI*2);
1136
- // ctx.fill();
1137
-
1138
- // ctx.moveTo(this.controlPoints.inner.x,this.controlPoints.inner.y);
1139
- // ctx.lineTo(this.x, this.y);
1140
- // ctx.lineTo(this.controlPoints.outer.x,this.controlPoints.outer.y);
1141
- // ctx.stroke();
1142
-
1143
- // ctx.restore();
1144
-
1145
-
1146
-
1147
- }
1148
- });
1149
-
1150
- Chart.Arc = Chart.Element.extend({
1151
- inRange : function(chartX,chartY){
1152
-
1153
- var pointRelativePosition = helpers.getAngleFromPoint(this, {
1154
- x: chartX,
1155
- y: chartY
1156
- });
1157
-
1158
- //Check if within the range of the open/close angle
1159
- var betweenAngles = (pointRelativePosition.angle >= this.startAngle && pointRelativePosition.angle <= this.endAngle),
1160
- withinRadius = (pointRelativePosition.distance >= this.innerRadius && pointRelativePosition.distance <= this.outerRadius);
1161
-
1162
- return (betweenAngles && withinRadius);
1163
- //Ensure within the outside of the arc centre, but inside arc outer
1164
- },
1165
- tooltipPosition : function(){
1166
- var centreAngle = this.startAngle + ((this.endAngle - this.startAngle) / 2),
1167
- rangeFromCentre = (this.outerRadius - this.innerRadius) / 2 + this.innerRadius;
1168
- return {
1169
- x : this.x + (Math.cos(centreAngle) * rangeFromCentre),
1170
- y : this.y + (Math.sin(centreAngle) * rangeFromCentre)
1171
- };
1172
- },
1173
- draw : function(animationPercent){
1174
-
1175
- var easingDecimal = animationPercent || 1;
1176
-
1177
- var ctx = this.ctx;
1178
-
1179
- ctx.beginPath();
1180
-
1181
- ctx.arc(this.x, this.y, this.outerRadius, this.startAngle, this.endAngle);
1182
-
1183
- ctx.arc(this.x, this.y, this.innerRadius, this.endAngle, this.startAngle, true);
1184
-
1185
- ctx.closePath();
1186
- ctx.strokeStyle = this.strokeColor;
1187
- ctx.lineWidth = this.strokeWidth;
1188
-
1189
- ctx.fillStyle = this.fillColor;
1190
-
1191
- ctx.fill();
1192
- ctx.lineJoin = 'bevel';
1193
-
1194
- if (this.showStroke){
1195
- ctx.stroke();
1196
- }
1197
- }
1198
- });
1199
-
1200
- Chart.Rectangle = Chart.Element.extend({
1201
- draw : function(){
1202
- var ctx = this.ctx,
1203
- halfWidth = this.width/2,
1204
- leftX = this.x - halfWidth,
1205
- rightX = this.x + halfWidth,
1206
- top = this.base - (this.base - this.y),
1207
- halfStroke = this.strokeWidth / 2;
1208
-
1209
- // Canvas doesn't allow us to stroke inside the width so we can
1210
- // adjust the sizes to fit if we're setting a stroke on the line
1211
- if (this.showStroke){
1212
- leftX += halfStroke;
1213
- rightX -= halfStroke;
1214
- top += halfStroke;
1215
- }
1216
-
1217
- ctx.beginPath();
1218
-
1219
- ctx.fillStyle = this.fillColor;
1220
- ctx.strokeStyle = this.strokeColor;
1221
- ctx.lineWidth = this.strokeWidth;
1222
-
1223
- // It'd be nice to keep this class totally generic to any rectangle
1224
- // and simply specify which border to miss out.
1225
- ctx.moveTo(leftX, this.base);
1226
- ctx.lineTo(leftX, top);
1227
- ctx.lineTo(rightX, top);
1228
- ctx.lineTo(rightX, this.base);
1229
- ctx.fill();
1230
- if (this.showStroke){
1231
- ctx.stroke();
1232
- }
1233
- },
1234
- height : function(){
1235
- return this.base - this.y;
1236
- },
1237
- inRange : function(chartX,chartY){
1238
- return (chartX >= this.x - this.width/2 && chartX <= this.x + this.width/2) && (chartY >= this.y && chartY <= this.base);
1239
- }
1240
- });
1241
-
1242
- Chart.Tooltip = Chart.Element.extend({
1243
- draw : function(){
1244
-
1245
- var ctx = this.chart.ctx;
1246
-
1247
- ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
1248
-
1249
- this.xAlign = "center";
1250
- this.yAlign = "above";
1251
-
1252
- //Distance between the actual element.y position and the start of the tooltip caret
1253
- var caretPadding = 2;
1254
-
1255
- var tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding,
1256
- tooltipRectHeight = this.fontSize + 2*this.yPadding,
1257
- tooltipHeight = tooltipRectHeight + this.caretHeight + caretPadding;
1258
-
1259
- if (this.x + tooltipWidth/2 >this.chart.width){
1260
- this.xAlign = "left";
1261
- } else if (this.x - tooltipWidth/2 < 0){
1262
- this.xAlign = "right";
1263
- }
1264
-
1265
- if (this.y - tooltipHeight < 0){
1266
- this.yAlign = "below";
1267
- }
1268
-
1269
-
1270
- var tooltipX = this.x - tooltipWidth/2,
1271
- tooltipY = this.y - tooltipHeight;
1272
-
1273
- ctx.fillStyle = this.fillColor;
1274
-
1275
- switch(this.yAlign)
1276
- {
1277
- case "above":
1278
- //Draw a caret above the x/y
1279
- ctx.beginPath();
1280
- ctx.moveTo(this.x,this.y - caretPadding);
1281
- ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));
1282
- ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));
1283
- ctx.closePath();
1284
- ctx.fill();
1285
- break;
1286
- case "below":
1287
- tooltipY = this.y + caretPadding + this.caretHeight;
1288
- //Draw a caret below the x/y
1289
- ctx.beginPath();
1290
- ctx.moveTo(this.x, this.y + caretPadding);
1291
- ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);
1292
- ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);
1293
- ctx.closePath();
1294
- ctx.fill();
1295
- break;
1296
- }
1297
-
1298
- switch(this.xAlign)
1299
- {
1300
- case "left":
1301
- tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);
1302
- break;
1303
- case "right":
1304
- tooltipX = this.x - (this.cornerRadius + this.caretHeight);
1305
- break;
1306
- }
1307
-
1308
- drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);
1309
-
1310
- ctx.fill();
1311
-
1312
- ctx.fillStyle = this.textColor;
1313
- ctx.textAlign = "center";
1314
- ctx.textBaseline = "middle";
1315
- ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);
1316
- }
1317
- });
1318
-
1319
- Chart.MultiTooltip = Chart.Element.extend({
1320
- initialize : function(){
1321
- this.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
1322
-
1323
- this.titleFont = fontString(this.titleFontSize,this.titleFontStyle,this.titleFontFamily);
1324
-
1325
- this.height = (this.labels.length * this.fontSize) + ((this.labels.length-1) * (this.fontSize/2)) + (this.yPadding*2) + this.titleFontSize *1.5;
1326
-
1327
- this.ctx.font = this.titleFont;
1328
-
1329
- var titleWidth = this.ctx.measureText(this.title).width,
1330
- //Label has a legend square as well so account for this.
1331
- labelWidth = longestText(this.ctx,this.font,this.labels) + this.fontSize + 3,
1332
- longestTextWidth = max([labelWidth,titleWidth]);
1333
-
1334
- this.width = longestTextWidth + (this.xPadding*2);
1335
-
1336
-
1337
- var halfHeight = this.height/2;
1338
-
1339
- //Check to ensure the height will fit on the canvas
1340
- //The three is to buffer form the very
1341
- if (this.y - halfHeight < 0 ){
1342
- this.y = halfHeight;
1343
- } else if (this.y + halfHeight > this.chart.height){
1344
- this.y = this.chart.height - halfHeight;
1345
- }
1346
-
1347
- //Decide whether to align left or right based on position on canvas
1348
- if (this.x > this.chart.width/2){
1349
- this.x -= this.xOffset + this.width;
1350
- } else {
1351
- this.x += this.xOffset;
1352
- }
1353
-
1354
-
1355
- },
1356
- getLineHeight : function(index){
1357
- var baseLineHeight = this.y - (this.height/2) + this.yPadding,
1358
- afterTitleIndex = index-1;
1359
-
1360
- //If the index is zero, we're getting the title
1361
- if (index === 0){
1362
- return baseLineHeight + this.titleFontSize/2;
1363
- } else{
1364
- return baseLineHeight + ((this.fontSize*1.5*afterTitleIndex) + this.fontSize/2) + this.titleFontSize * 1.5;
1365
- }
1366
-
1367
- },
1368
- draw : function(){
1369
- drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);
1370
- var ctx = this.ctx;
1371
- ctx.fillStyle = this.fillColor;
1372
- ctx.fill();
1373
- ctx.closePath();
1374
-
1375
- ctx.textAlign = "left";
1376
- ctx.textBaseline = "middle";
1377
- ctx.fillStyle = this.titleTextColor;
1378
- ctx.font = this.titleFont;
1379
-
1380
- ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));
1381
-
1382
- ctx.font = this.font;
1383
- helpers.each(this.labels,function(label,index){
1384
- ctx.fillStyle = this.textColor;
1385
- ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));
1386
-
1387
- //A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)
1388
- //ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
1389
- //Instead we'll make a white filled block to put the legendColour palette over.
1390
-
1391
- ctx.fillStyle = this.legendColorBackground;
1392
- ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
1393
-
1394
- ctx.fillStyle = this.legendColors[index].fill;
1395
- ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
1396
-
1397
-
1398
- },this);
1399
- }
1400
- });
1401
-
1402
- Chart.Scale = Chart.Element.extend({
1403
- initialize : function(){
1404
- this.fit();
1405
- },
1406
- buildYLabels : function(){
1407
- this.yLabels = [];
1408
-
1409
- var stepDecimalPlaces = getDecimalPlaces(this.stepValue);
1410
-
1411
- for (var i=0; i<=this.steps; i++){
1412
- this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));
1413
- }
1414
- this.yLabelWidth = (this.display && this.showLabels) ? longestText(this.ctx,this.font,this.yLabels) : 0;
1415
- },
1416
- addXLabel : function(label){
1417
- this.xLabels.push(label);
1418
- this.valuesCount++;
1419
- this.fit();
1420
- },
1421
- removeXLabel : function(){
1422
- this.xLabels.shift();
1423
- this.valuesCount--;
1424
- this.fit();
1425
- },
1426
- // Fitting loop to rotate x Labels and figure out what fits there, and also calculate how many Y steps to use
1427
- fit: function(){
1428
- // First we need the width of the yLabels, assuming the xLabels aren't rotated
1429
-
1430
- // To do that we need the base line at the top and base of the chart, assuming there is no x label rotation
1431
- this.startPoint = (this.display) ? this.fontSize : 0;
1432
- this.endPoint = (this.display) ? this.height - (this.fontSize * 1.5) - 5 : this.height; // -5 to pad labels
1433
-
1434
- // Apply padding settings to the start and end point.
1435
- this.startPoint += this.padding;
1436
- this.endPoint -= this.padding;
1437
-
1438
- // Cache the starting height, so can determine if we need to recalculate the scale yAxis
1439
- var cachedHeight = this.endPoint - this.startPoint,
1440
- cachedYLabelWidth;
1441
-
1442
- // Build the current yLabels so we have an idea of what size they'll be to start
1443
- /*
1444
- * This sets what is returned from calculateScaleRange as static properties of this class:
1445
- *
1446
- this.steps;
1447
- this.stepValue;
1448
- this.min;
1449
- this.max;
1450
- *
1451
- */
1452
- this.calculateYRange(cachedHeight);
1453
-
1454
- // With these properties set we can now build the array of yLabels
1455
- // and also the width of the largest yLabel
1456
- this.buildYLabels();
1457
-
1458
- this.calculateXLabelRotation();
1459
-
1460
- while((cachedHeight > this.endPoint - this.startPoint)){
1461
- cachedHeight = this.endPoint - this.startPoint;
1462
- cachedYLabelWidth = this.yLabelWidth;
1463
-
1464
- this.calculateYRange(cachedHeight);
1465
- this.buildYLabels();
1466
-
1467
- // Only go through the xLabel loop again if the yLabel width has changed
1468
- if (cachedYLabelWidth < this.yLabelWidth){
1469
- this.calculateXLabelRotation();
1470
- }
1471
- }
1472
-
1473
- },
1474
- calculateXLabelRotation : function(){
1475
- //Get the width of each grid by calculating the difference
1476
- //between x offsets between 0 and 1.
1477
-
1478
- this.ctx.font = this.font;
1479
-
1480
- var firstWidth = this.ctx.measureText(this.xLabels[0]).width,
1481
- lastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width,
1482
- firstRotated,
1483
- lastRotated;
1484
-
1485
-
1486
- this.xScalePaddingRight = lastWidth/2 + 3;
1487
- this.xScalePaddingLeft = (firstWidth/2 > this.yLabelWidth + 10) ? firstWidth/2 : this.yLabelWidth + 10;
1488
-
1489
- this.xLabelRotation = 0;
1490
- if (this.display){
1491
- var originalLabelWidth = longestText(this.ctx,this.font,this.xLabels),
1492
- cosRotation,
1493
- firstRotatedWidth;
1494
- this.xLabelWidth = originalLabelWidth;
1495
- //Allow 3 pixels x2 padding either side for label readability
1496
- var xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6;
1497
-
1498
- //Max label rotate should be 90 - also act as a loop counter
1499
- while ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)){
1500
- cosRotation = Math.cos(toRadians(this.xLabelRotation));
1501
-
1502
- firstRotated = cosRotation * firstWidth;
1503
- lastRotated = cosRotation * lastWidth;
1504
-
1505
- // We're right aligning the text now.
1506
- if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8){
1507
- this.xScalePaddingLeft = firstRotated + this.fontSize / 2;
1508
- }
1509
- this.xScalePaddingRight = this.fontSize/2;
1510
-
1511
-
1512
- this.xLabelRotation++;
1513
- this.xLabelWidth = cosRotation * originalLabelWidth;
1514
-
1515
- }
1516
- if (this.xLabelRotation > 0){
1517
- this.endPoint -= Math.sin(toRadians(this.xLabelRotation))*originalLabelWidth + 3;
1518
- }
1519
- }
1520
- else{
1521
- this.xLabelWidth = 0;
1522
- this.xScalePaddingRight = this.padding;
1523
- this.xScalePaddingLeft = this.padding;
1524
- }
1525
-
1526
- },
1527
- // Needs to be overidden in each Chart type
1528
- // Otherwise we need to pass all the data into the scale class
1529
- calculateYRange: noop,
1530
- drawingArea: function(){
1531
- return this.startPoint - this.endPoint;
1532
- },
1533
- calculateY : function(value){
1534
- var scalingFactor = this.drawingArea() / (this.min - this.max);
1535
- return this.endPoint - (scalingFactor * (value - this.min));
1536
- },
1537
- calculateX : function(index){
1538
- var isRotated = (this.xLabelRotation > 0),
1539
- // innerWidth = (this.offsetGridLines) ? this.width - offsetLeft - this.padding : this.width - (offsetLeft + halfLabelWidth * 2) - this.padding,
1540
- innerWidth = this.width - (this.xScalePaddingLeft + this.xScalePaddingRight),
1541
- valueWidth = innerWidth/(this.valuesCount - ((this.offsetGridLines) ? 0 : 1)),
1542
- valueOffset = (valueWidth * index) + this.xScalePaddingLeft;
1543
-
1544
- if (this.offsetGridLines){
1545
- valueOffset += (valueWidth/2);
1546
- }
1547
-
1548
- return Math.round(valueOffset);
1549
- },
1550
- update : function(newProps){
1551
- helpers.extend(this, newProps);
1552
- this.fit();
1553
- },
1554
- draw : function(){
1555
- var ctx = this.ctx,
1556
- yLabelGap = (this.endPoint - this.startPoint) / this.steps,
1557
- xStart = Math.round(this.xScalePaddingLeft);
1558
- if (this.display){
1559
- ctx.fillStyle = this.textColor;
1560
- ctx.font = this.font;
1561
- each(this.yLabels,function(labelString,index){
1562
- var yLabelCenter = this.endPoint - (yLabelGap * index),
1563
- linePositionY = Math.round(yLabelCenter);
1564
-
1565
- ctx.textAlign = "right";
1566
- ctx.textBaseline = "middle";
1567
- if (this.showLabels){
1568
- ctx.fillText(labelString,xStart - 10,yLabelCenter);
1569
- }
1570
- ctx.beginPath();
1571
- if (index > 0){
1572
- // This is a grid line in the centre, so drop that
1573
- ctx.lineWidth = this.gridLineWidth;
1574
- ctx.strokeStyle = this.gridLineColor;
1575
- } else {
1576
- // This is the first line on the scale
1577
- ctx.lineWidth = this.lineWidth;
1578
- ctx.strokeStyle = this.lineColor;
1579
- }
1580
-
1581
- linePositionY += helpers.aliasPixel(ctx.lineWidth);
1582
-
1583
- ctx.moveTo(xStart, linePositionY);
1584
- ctx.lineTo(this.width, linePositionY);
1585
- ctx.stroke();
1586
- ctx.closePath();
1587
-
1588
- ctx.lineWidth = this.lineWidth;
1589
- ctx.strokeStyle = this.lineColor;
1590
- ctx.beginPath();
1591
- ctx.moveTo(xStart - 5, linePositionY);
1592
- ctx.lineTo(xStart, linePositionY);
1593
- ctx.stroke();
1594
- ctx.closePath();
1595
-
1596
- },this);
1597
-
1598
- each(this.xLabels,function(label,index){
1599
- var xPos = this.calculateX(index) + aliasPixel(this.lineWidth),
1600
- // Check to see if line/bar here and decide where to place the line
1601
- linePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth),
1602
- isRotated = (this.xLabelRotation > 0);
1603
-
1604
- ctx.beginPath();
1605
-
1606
- if (index > 0){
1607
- // This is a grid line in the centre, so drop that
1608
- ctx.lineWidth = this.gridLineWidth;
1609
- ctx.strokeStyle = this.gridLineColor;
1610
- } else {
1611
- // This is the first line on the scale
1612
- ctx.lineWidth = this.lineWidth;
1613
- ctx.strokeStyle = this.lineColor;
1614
- }
1615
- ctx.moveTo(linePos,this.endPoint);
1616
- ctx.lineTo(linePos,this.startPoint - 3);
1617
- ctx.stroke();
1618
- ctx.closePath();
1619
-
1620
-
1621
- ctx.lineWidth = this.lineWidth;
1622
- ctx.strokeStyle = this.lineColor;
1623
-
1624
-
1625
- // Small lines at the bottom of the base grid line
1626
- ctx.beginPath();
1627
- ctx.moveTo(linePos,this.endPoint);
1628
- ctx.lineTo(linePos,this.endPoint + 5);
1629
- ctx.stroke();
1630
- ctx.closePath();
1631
-
1632
- ctx.save();
1633
- ctx.translate(xPos,(isRotated) ? this.endPoint + 12 : this.endPoint + 8);
1634
- ctx.rotate(toRadians(this.xLabelRotation)*-1);
1635
- ctx.font = this.font;
1636
- ctx.textAlign = (isRotated) ? "right" : "center";
1637
- ctx.textBaseline = (isRotated) ? "middle" : "top";
1638
- ctx.fillText(label, 0, 0);
1639
- ctx.restore();
1640
- },this);
1641
-
1642
- }
1643
- }
1644
-
1645
- });
1646
-
1647
- Chart.RadialScale = Chart.Element.extend({
1648
- initialize: function(){
1649
- this.size = min([this.height, this.width]);
1650
- this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);
1651
- },
1652
- calculateCenterOffset: function(value){
1653
- // Take into account half font size + the yPadding of the top value
1654
- var scalingFactor = this.drawingArea / (this.max - this.min);
1655
-
1656
- return (value - this.min) * scalingFactor;
1657
- },
1658
- update : function(){
1659
- if (!this.lineArc){
1660
- this.setScaleSize();
1661
- } else {
1662
- this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);
1663
- }
1664
- this.buildYLabels();
1665
- },
1666
- buildYLabels: function(){
1667
- this.yLabels = [];
1668
-
1669
- var stepDecimalPlaces = getDecimalPlaces(this.stepValue);
1670
-
1671
- for (var i=0; i<=this.steps; i++){
1672
- this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));
1673
- }
1674
- },
1675
- getCircumference : function(){
1676
- return ((Math.PI*2) / this.valuesCount);
1677
- },
1678
- setScaleSize: function(){
1679
- /*
1680
- * Right, this is really confusing and there is a lot of maths going on here
1681
- * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
1682
- *
1683
- * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif
1684
- *
1685
- * Solution:
1686
- *
1687
- * We assume the radius of the polygon is half the size of the canvas at first
1688
- * at each index we check if the text overlaps.
1689
- *
1690
- * Where it does, we store that angle and that index.
1691
- *
1692
- * After finding the largest index and angle we calculate how much we need to remove
1693
- * from the shape radius to move the point inwards by that x.
1694
- *
1695
- * We average the left and right distances to get the maximum shape radius that can fit in the box
1696
- * along with labels.
1697
- *
1698
- * Once we have that, we can find the centre point for the chart, by taking the x text protrusion
1699
- * on each side, removing that from the size, halving it and adding the left x protrusion width.
1700
- *
1701
- * This will mean we have a shape fitted to the canvas, as large as it can be with the labels
1702
- * and position it in the most space efficient manner
1703
- *
1704
- * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif
1705
- */
1706
-
1707
-
1708
- // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.
1709
- // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points
1710
- var largestPossibleRadius = min([(this.height/2 - this.pointLabelFontSize - 5), this.width/2]),
1711
- pointPosition,
1712
- i,
1713
- textWidth,
1714
- halfTextWidth,
1715
- furthestRight = this.width,
1716
- furthestRightIndex,
1717
- furthestRightAngle,
1718
- furthestLeft = 0,
1719
- furthestLeftIndex,
1720
- furthestLeftAngle,
1721
- xProtrusionLeft,
1722
- xProtrusionRight,
1723
- radiusReductionRight,
1724
- radiusReductionLeft,
1725
- maxWidthRadius;
1726
- this.ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);
1727
- for (i=0;i<this.valuesCount;i++){
1728
- // 5px to space the text slightly out - similar to what we do in the draw function.
1729
- pointPosition = this.getPointPosition(i, largestPossibleRadius);
1730
- textWidth = this.ctx.measureText(template(this.templateString, { value: this.labels[i] })).width + 5;
1731
- if (i === 0 || i === this.valuesCount/2){
1732
- // If we're at index zero, or exactly the middle, we're at exactly the top/bottom
1733
- // of the radar chart, so text will be aligned centrally, so we'll half it and compare
1734
- // w/left and right text sizes
1735
- halfTextWidth = textWidth/2;
1736
- if (pointPosition.x + halfTextWidth > furthestRight) {
1737
- furthestRight = pointPosition.x + halfTextWidth;
1738
- furthestRightIndex = i;
1739
- }
1740
- if (pointPosition.x - halfTextWidth < furthestLeft) {
1741
- furthestLeft = pointPosition.x - halfTextWidth;
1742
- furthestLeftIndex = i;
1743
- }
1744
- }
1745
- else if (i < this.valuesCount/2) {
1746
- // Less than half the values means we'll left align the text
1747
- if (pointPosition.x + textWidth > furthestRight) {
1748
- furthestRight = pointPosition.x + textWidth;
1749
- furthestRightIndex = i;
1750
- }
1751
- }
1752
- else if (i > this.valuesCount/2){
1753
- // More than half the values means we'll right align the text
1754
- if (pointPosition.x - textWidth < furthestLeft) {
1755
- furthestLeft = pointPosition.x - textWidth;
1756
- furthestLeftIndex = i;
1757
- }
1758
- }
1759
- }
1760
-
1761
- xProtrusionLeft = furthestLeft;
1762
-
1763
- xProtrusionRight = Math.ceil(furthestRight - this.width);
1764
-
1765
- furthestRightAngle = this.getIndexAngle(furthestRightIndex);
1766
-
1767
- furthestLeftAngle = this.getIndexAngle(furthestLeftIndex);
1768
-
1769
- radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI/2);
1770
-
1771
- radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI/2);
1772
-
1773
- // Ensure we actually need to reduce the size of the chart
1774
- radiusReductionRight = (isNumber(radiusReductionRight)) ? radiusReductionRight : 0;
1775
- radiusReductionLeft = (isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;
1776
-
1777
- this.drawingArea = largestPossibleRadius - (radiusReductionLeft + radiusReductionRight)/2;
1778
-
1779
- //this.drawingArea = min([maxWidthRadius, (this.height - (2 * (this.pointLabelFontSize + 5)))/2])
1780
- this.setCenterPoint(radiusReductionLeft, radiusReductionRight);
1781
-
1782
- },
1783
- setCenterPoint: function(leftMovement, rightMovement){
1784
-
1785
- var maxRight = this.width - rightMovement - this.drawingArea,
1786
- maxLeft = leftMovement + this.drawingArea;
1787
-
1788
- this.xCenter = (maxLeft + maxRight)/2;
1789
- // Always vertically in the centre as the text height doesn't change
1790
- this.yCenter = (this.height/2);
1791
- },
1792
-
1793
- getIndexAngle : function(index){
1794
- var angleMultiplier = (Math.PI * 2) / this.valuesCount;
1795
- // Start from the top instead of right, so remove a quarter of the circle
1796
-
1797
- return index * angleMultiplier - (Math.PI/2);
1798
- },
1799
- getPointPosition : function(index, distanceFromCenter){
1800
- var thisAngle = this.getIndexAngle(index);
1801
- return {
1802
- x : (Math.cos(thisAngle) * distanceFromCenter) + this.xCenter,
1803
- y : (Math.sin(thisAngle) * distanceFromCenter) + this.yCenter
1804
- };
1805
- },
1806
- draw: function(){
1807
- if (this.display){
1808
- var ctx = this.ctx;
1809
- each(this.yLabels, function(label, index){
1810
- // Don't draw a centre value
1811
- if (index > 0){
1812
- var yCenterOffset = index * (this.drawingArea/this.steps),
1813
- yHeight = this.yCenter - yCenterOffset,
1814
- pointPosition;
1815
-
1816
- // Draw circular lines around the scale
1817
- if (this.lineWidth > 0){
1818
- ctx.strokeStyle = this.lineColor;
1819
- ctx.lineWidth = this.lineWidth;
1820
-
1821
- if(this.lineArc){
1822
- ctx.beginPath();
1823
- ctx.arc(this.xCenter, this.yCenter, yCenterOffset, 0, Math.PI*2);
1824
- ctx.closePath();
1825
- ctx.stroke();
1826
- } else{
1827
- ctx.beginPath();
1828
- for (var i=0;i<this.valuesCount;i++)
1829
- {
1830
- pointPosition = this.getPointPosition(i, this.calculateCenterOffset(this.min + (index * this.stepValue)));
1831
- if (i === 0){
1832
- ctx.moveTo(pointPosition.x, pointPosition.y);
1833
- } else {
1834
- ctx.lineTo(pointPosition.x, pointPosition.y);
1835
- }
1836
- }
1837
- ctx.closePath();
1838
- ctx.stroke();
1839
- }
1840
- }
1841
- if(this.showLabels){
1842
- ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
1843
- if (this.showLabelBackdrop){
1844
- var labelWidth = ctx.measureText(label).width;
1845
- ctx.fillStyle = this.backdropColor;
1846
- ctx.fillRect(
1847
- this.xCenter - labelWidth/2 - this.backdropPaddingX,
1848
- yHeight - this.fontSize/2 - this.backdropPaddingY,
1849
- labelWidth + this.backdropPaddingX*2,
1850
- this.fontSize + this.backdropPaddingY*2
1851
- );
1852
- }
1853
- ctx.textAlign = 'center';
1854
- ctx.textBaseline = "middle";
1855
- ctx.fillStyle = this.fontColor;
1856
- ctx.fillText(label, this.xCenter, yHeight);
1857
- }
1858
- }
1859
- }, this);
1860
-
1861
- if (!this.lineArc){
1862
- ctx.lineWidth = this.angleLineWidth;
1863
- ctx.strokeStyle = this.angleLineColor;
1864
- for (var i = this.valuesCount - 1; i >= 0; i--) {
1865
- if (this.angleLineWidth > 0){
1866
- var outerPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max));
1867
- ctx.beginPath();
1868
- ctx.moveTo(this.xCenter, this.yCenter);
1869
- ctx.lineTo(outerPosition.x, outerPosition.y);
1870
- ctx.stroke();
1871
- ctx.closePath();
1872
- }
1873
- // Extra 3px out for some label spacing
1874
- var pointLabelPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max) + 5);
1875
- ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);
1876
- ctx.fillStyle = this.pointLabelFontColor;
1877
-
1878
- var labelsCount = this.labels.length,
1879
- halfLabelsCount = this.labels.length/2,
1880
- quarterLabelsCount = halfLabelsCount/2,
1881
- upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
1882
- exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
1883
- if (i === 0){
1884
- ctx.textAlign = 'center';
1885
- } else if(i === halfLabelsCount){
1886
- ctx.textAlign = 'center';
1887
- } else if (i < halfLabelsCount){
1888
- ctx.textAlign = 'left';
1889
- } else {
1890
- ctx.textAlign = 'right';
1891
- }
1892
-
1893
- // Set the correct text baseline based on outer positioning
1894
- if (exactQuarter){
1895
- ctx.textBaseline = 'middle';
1896
- } else if (upperHalf){
1897
- ctx.textBaseline = 'bottom';
1898
- } else {
1899
- ctx.textBaseline = 'top';
1900
- }
1901
-
1902
- ctx.fillText(this.labels[i], pointLabelPosition.x, pointLabelPosition.y);
1903
- }
1904
- }
1905
- }
1906
- }
1907
- });
1908
-
1909
- // Attach global event to resize each chart instance when the browser resizes
1910
- helpers.addEvent(window, "resize", (function(){
1911
- // Basic debounce of resize function so it doesn't hurt performance when resizing browser.
1912
- var timeout;
1913
- return function(){
1914
- clearTimeout(timeout);
1915
- timeout = setTimeout(function(){
1916
- each(Chart.instances,function(instance){
1917
- // If the responsive flag is set in the chart instance config
1918
- // Cascade the resize event down to the chart.
1919
- if (instance.options.responsive){
1920
- instance.resize(instance.render, true);
1921
- }
1922
- });
1923
- }, 50);
1924
- };
1925
- })());
1926
-
1927
-
1928
- if (amd) {
1929
- define(function(){
1930
- return Chart;
1931
- });
1932
- } else if (typeof module === 'object' && module.exports) {
1933
- module.exports = Chart;
1934
- }
1935
-
1936
- root.Chart = Chart;
1937
-
1938
- Chart.noConflict = function(){
1939
- root.Chart = previous;
1940
- return Chart;
1941
- };
1942
-
1943
- }).call(this);
1944
-
1945
- (function(){
1946
- "use strict";
1947
-
1948
- var root = this,
1949
- Chart = root.Chart,
1950
- helpers = Chart.helpers;
1951
-
1952
-
1953
- var defaultConfig = {
1954
- //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
1955
- scaleBeginAtZero : true,
1956
-
1957
- //Boolean - Whether grid lines are shown across the chart
1958
- scaleShowGridLines : true,
1959
-
1960
- //String - Colour of the grid lines
1961
- scaleGridLineColor : "rgba(0,0,0,.05)",
1962
-
1963
- //Number - Width of the grid lines
1964
- scaleGridLineWidth : 1,
1965
-
1966
- //Boolean - If there is a stroke on each bar
1967
- barShowStroke : true,
1968
-
1969
- //Number - Pixel width of the bar stroke
1970
- barStrokeWidth : 2,
1971
-
1972
- //Number - Spacing between each of the X value sets
1973
- barValueSpacing : 5,
1974
-
1975
- //Number - Spacing between data sets within X values
1976
- barDatasetSpacing : 1,
1977
-
1978
- //String - A legend template
1979
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
1980
-
1981
- };
1982
-
1983
-
1984
- Chart.Type.extend({
1985
- name: "Bar",
1986
- defaults : defaultConfig,
1987
- initialize: function(data){
1988
-
1989
- //Expose options as a scope variable here so we can access it in the ScaleClass
1990
- var options = this.options;
1991
-
1992
- this.ScaleClass = Chart.Scale.extend({
1993
- offsetGridLines : true,
1994
- calculateBarX : function(datasetCount, datasetIndex, barIndex){
1995
- //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
1996
- var xWidth = this.calculateBaseWidth(),
1997
- xAbsolute = this.calculateX(barIndex) - (xWidth/2),
1998
- barWidth = this.calculateBarWidth(datasetCount);
1999
-
2000
- return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;
2001
- },
2002
- calculateBaseWidth : function(){
2003
- return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing);
2004
- },
2005
- calculateBarWidth : function(datasetCount){
2006
- //The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
2007
- var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);
2008
-
2009
- return (baseWidth / datasetCount);
2010
- }
2011
- });
2012
-
2013
- this.datasets = [];
2014
-
2015
- //Set up tooltip events on the chart
2016
- if (this.options.showTooltips){
2017
- helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
2018
- var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];
2019
-
2020
- this.eachBars(function(bar){
2021
- bar.restore(['fillColor', 'strokeColor']);
2022
- });
2023
- helpers.each(activeBars, function(activeBar){
2024
- activeBar.fillColor = activeBar.highlightFill;
2025
- activeBar.strokeColor = activeBar.highlightStroke;
2026
- });
2027
- this.showTooltip(activeBars);
2028
- });
2029
- }
2030
-
2031
- //Declare the extension of the default point, to cater for the options passed in to the constructor
2032
- this.BarClass = Chart.Rectangle.extend({
2033
- strokeWidth : this.options.barStrokeWidth,
2034
- showStroke : this.options.barShowStroke,
2035
- ctx : this.chart.ctx
2036
- });
2037
-
2038
- //Iterate through each of the datasets, and build this into a property of the chart
2039
- helpers.each(data.datasets,function(dataset,datasetIndex){
2040
-
2041
- var datasetObject = {
2042
- label : dataset.label || null,
2043
- fillColor : dataset.fillColor,
2044
- strokeColor : dataset.strokeColor,
2045
- bars : []
2046
- };
2047
-
2048
- this.datasets.push(datasetObject);
2049
-
2050
- helpers.each(dataset.data,function(dataPoint,index){
2051
- //Add a new point for each piece of data, passing any required data to draw.
2052
- datasetObject.bars.push(new this.BarClass({
2053
- value : dataPoint,
2054
- label : data.labels[index],
2055
- datasetLabel: dataset.label,
2056
- strokeColor : dataset.strokeColor,
2057
- fillColor : dataset.fillColor,
2058
- highlightFill : dataset.highlightFill || dataset.fillColor,
2059
- highlightStroke : dataset.highlightStroke || dataset.strokeColor
2060
- }));
2061
- },this);
2062
-
2063
- },this);
2064
-
2065
- this.buildScale(data.labels);
2066
-
2067
- this.BarClass.prototype.base = this.scale.endPoint;
2068
-
2069
- this.eachBars(function(bar, index, datasetIndex){
2070
- helpers.extend(bar, {
2071
- width : this.scale.calculateBarWidth(this.datasets.length),
2072
- x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
2073
- y: this.scale.endPoint
2074
- });
2075
- bar.save();
2076
- }, this);
2077
-
2078
- this.render();
2079
- },
2080
- update : function(){
2081
- this.scale.update();
2082
- // Reset any highlight colours before updating.
2083
- helpers.each(this.activeElements, function(activeElement){
2084
- activeElement.restore(['fillColor', 'strokeColor']);
2085
- });
2086
-
2087
- this.eachBars(function(bar){
2088
- bar.save();
2089
- });
2090
- this.render();
2091
- },
2092
- eachBars : function(callback){
2093
- helpers.each(this.datasets,function(dataset, datasetIndex){
2094
- helpers.each(dataset.bars, callback, this, datasetIndex);
2095
- },this);
2096
- },
2097
- getBarsAtEvent : function(e){
2098
- var barsArray = [],
2099
- eventPosition = helpers.getRelativePosition(e),
2100
- datasetIterator = function(dataset){
2101
- barsArray.push(dataset.bars[barIndex]);
2102
- },
2103
- barIndex;
2104
-
2105
- for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {
2106
- for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {
2107
- if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){
2108
- helpers.each(this.datasets, datasetIterator);
2109
- return barsArray;
2110
- }
2111
- }
2112
- }
2113
-
2114
- return barsArray;
2115
- },
2116
- buildScale : function(labels){
2117
- var self = this;
2118
-
2119
- var dataTotal = function(){
2120
- var values = [];
2121
- self.eachBars(function(bar){
2122
- values.push(bar.value);
2123
- });
2124
- return values;
2125
- };
2126
-
2127
- var scaleOptions = {
2128
- templateString : this.options.scaleLabel,
2129
- height : this.chart.height,
2130
- width : this.chart.width,
2131
- ctx : this.chart.ctx,
2132
- textColor : this.options.scaleFontColor,
2133
- fontSize : this.options.scaleFontSize,
2134
- fontStyle : this.options.scaleFontStyle,
2135
- fontFamily : this.options.scaleFontFamily,
2136
- valuesCount : labels.length,
2137
- beginAtZero : this.options.scaleBeginAtZero,
2138
- integersOnly : this.options.scaleIntegersOnly,
2139
- calculateYRange: function(currentHeight){
2140
- var updatedRanges = helpers.calculateScaleRange(
2141
- dataTotal(),
2142
- currentHeight,
2143
- this.fontSize,
2144
- this.beginAtZero,
2145
- this.integersOnly
2146
- );
2147
- helpers.extend(this, updatedRanges);
2148
- },
2149
- xLabels : labels,
2150
- font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
2151
- lineWidth : this.options.scaleLineWidth,
2152
- lineColor : this.options.scaleLineColor,
2153
- gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
2154
- gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
2155
- padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,
2156
- showLabels : this.options.scaleShowLabels,
2157
- display : this.options.showScale
2158
- };
2159
-
2160
- if (this.options.scaleOverride){
2161
- helpers.extend(scaleOptions, {
2162
- calculateYRange: helpers.noop,
2163
- steps: this.options.scaleSteps,
2164
- stepValue: this.options.scaleStepWidth,
2165
- min: this.options.scaleStartValue,
2166
- max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
2167
- });
2168
- }
2169
-
2170
- this.scale = new this.ScaleClass(scaleOptions);
2171
- },
2172
- addData : function(valuesArray,label){
2173
- //Map the values array for each of the datasets
2174
- helpers.each(valuesArray,function(value,datasetIndex){
2175
- //Add a new point for each piece of data, passing any required data to draw.
2176
- this.datasets[datasetIndex].bars.push(new this.BarClass({
2177
- value : value,
2178
- label : label,
2179
- x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1),
2180
- y: this.scale.endPoint,
2181
- width : this.scale.calculateBarWidth(this.datasets.length),
2182
- base : this.scale.endPoint,
2183
- strokeColor : this.datasets[datasetIndex].strokeColor,
2184
- fillColor : this.datasets[datasetIndex].fillColor
2185
- }));
2186
- },this);
2187
-
2188
- this.scale.addXLabel(label);
2189
- //Then re-render the chart.
2190
- this.update();
2191
- },
2192
- removeData : function(){
2193
- this.scale.removeXLabel();
2194
- //Then re-render the chart.
2195
- helpers.each(this.datasets,function(dataset){
2196
- dataset.bars.shift();
2197
- },this);
2198
- this.update();
2199
- },
2200
- reflow : function(){
2201
- helpers.extend(this.BarClass.prototype,{
2202
- y: this.scale.endPoint,
2203
- base : this.scale.endPoint
2204
- });
2205
- var newScaleProps = helpers.extend({
2206
- height : this.chart.height,
2207
- width : this.chart.width
2208
- });
2209
- this.scale.update(newScaleProps);
2210
- },
2211
- draw : function(ease){
2212
- var easingDecimal = ease || 1;
2213
- this.clear();
2214
-
2215
- var ctx = this.chart.ctx;
2216
-
2217
- this.scale.draw(easingDecimal);
2218
-
2219
- //Draw all the bars for each dataset
2220
- helpers.each(this.datasets,function(dataset,datasetIndex){
2221
- helpers.each(dataset.bars,function(bar,index){
2222
- if (bar.hasValue()){
2223
- bar.base = this.scale.endPoint;
2224
- //Transition then draw
2225
- bar.transition({
2226
- x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
2227
- y : this.scale.calculateY(bar.value),
2228
- width : this.scale.calculateBarWidth(this.datasets.length)
2229
- }, easingDecimal).draw();
2230
- }
2231
- },this);
2232
-
2233
- },this);
2234
- }
2235
- });
2236
-
2237
-
2238
- }).call(this);
2239
- (function(){
2240
- "use strict";
2241
-
2242
- var root = this,
2243
- Chart = root.Chart,
2244
- //Cache a local reference to Chart.helpers
2245
- helpers = Chart.helpers;
2246
-
2247
- var defaultConfig = {
2248
- //Boolean - Whether we should show a stroke on each segment
2249
- segmentShowStroke : true,
2250
-
2251
- //String - The colour of each segment stroke
2252
- segmentStrokeColor : "#fff",
2253
-
2254
- //Number - The width of each segment stroke
2255
- segmentStrokeWidth : 2,
2256
-
2257
- //The percentage of the chart that we cut out of the middle.
2258
- percentageInnerCutout : 50,
2259
-
2260
- //Number - Amount of animation steps
2261
- animationSteps : 100,
2262
-
2263
- //String - Animation easing effect
2264
- animationEasing : "easeOutBounce",
2265
-
2266
- //Boolean - Whether we animate the rotation of the Doughnut
2267
- animateRotate : true,
2268
-
2269
- //Boolean - Whether we animate scaling the Doughnut from the centre
2270
- animateScale : false,
2271
-
2272
- //String - A legend template
2273
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
2274
-
2275
- };
2276
-
2277
-
2278
- Chart.Type.extend({
2279
- //Passing in a name registers this chart in the Chart namespace
2280
- name: "Doughnut",
2281
- //Providing a defaults will also register the deafults in the chart namespace
2282
- defaults : defaultConfig,
2283
- //Initialize is fired when the chart is initialized - Data is passed in as a parameter
2284
- //Config is automatically merged by the core of Chart.js, and is available at this.options
2285
- initialize: function(data){
2286
-
2287
- //Declare segments as a static property to prevent inheriting across the Chart type prototype
2288
- this.segments = [];
2289
- this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
2290
-
2291
- this.SegmentArc = Chart.Arc.extend({
2292
- ctx : this.chart.ctx,
2293
- x : this.chart.width/2,
2294
- y : this.chart.height/2
2295
- });
2296
-
2297
- //Set up tooltip events on the chart
2298
- if (this.options.showTooltips){
2299
- helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
2300
- var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
2301
-
2302
- helpers.each(this.segments,function(segment){
2303
- segment.restore(["fillColor"]);
2304
- });
2305
- helpers.each(activeSegments,function(activeSegment){
2306
- activeSegment.fillColor = activeSegment.highlightColor;
2307
- });
2308
- this.showTooltip(activeSegments);
2309
- });
2310
- }
2311
- this.calculateTotal(data);
2312
-
2313
- helpers.each(data,function(datapoint, index){
2314
- this.addData(datapoint, index, true);
2315
- },this);
2316
-
2317
- this.render();
2318
- },
2319
- getSegmentsAtEvent : function(e){
2320
- var segmentsArray = [];
2321
-
2322
- var location = helpers.getRelativePosition(e);
2323
-
2324
- helpers.each(this.segments,function(segment){
2325
- if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
2326
- },this);
2327
- return segmentsArray;
2328
- },
2329
- addData : function(segment, atIndex, silent){
2330
- var index = atIndex || this.segments.length;
2331
- this.segments.splice(index, 0, new this.SegmentArc({
2332
- value : segment.value,
2333
- outerRadius : (this.options.animateScale) ? 0 : this.outerRadius,
2334
- innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,
2335
- fillColor : segment.color,
2336
- highlightColor : segment.highlight || segment.color,
2337
- showStroke : this.options.segmentShowStroke,
2338
- strokeWidth : this.options.segmentStrokeWidth,
2339
- strokeColor : this.options.segmentStrokeColor,
2340
- startAngle : Math.PI * 1.5,
2341
- circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
2342
- label : segment.label
2343
- }));
2344
- if (!silent){
2345
- this.reflow();
2346
- this.update();
2347
- }
2348
- },
2349
- calculateCircumference : function(value){
2350
- return (Math.PI*2)*(value / this.total);
2351
- },
2352
- calculateTotal : function(data){
2353
- this.total = 0;
2354
- helpers.each(data,function(segment){
2355
- this.total += segment.value;
2356
- },this);
2357
- },
2358
- update : function(){
2359
- this.calculateTotal(this.segments);
2360
-
2361
- // Reset any highlight colours before updating.
2362
- helpers.each(this.activeElements, function(activeElement){
2363
- activeElement.restore(['fillColor']);
2364
- });
2365
-
2366
- helpers.each(this.segments,function(segment){
2367
- segment.save();
2368
- });
2369
- this.render();
2370
- },
2371
-
2372
- removeData: function(atIndex){
2373
- var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
2374
- this.segments.splice(indexToDelete, 1);
2375
- this.reflow();
2376
- this.update();
2377
- },
2378
-
2379
- reflow : function(){
2380
- helpers.extend(this.SegmentArc.prototype,{
2381
- x : this.chart.width/2,
2382
- y : this.chart.height/2
2383
- });
2384
- this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
2385
- helpers.each(this.segments, function(segment){
2386
- segment.update({
2387
- outerRadius : this.outerRadius,
2388
- innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
2389
- });
2390
- }, this);
2391
- },
2392
- draw : function(easeDecimal){
2393
- var animDecimal = (easeDecimal) ? easeDecimal : 1;
2394
- this.clear();
2395
- helpers.each(this.segments,function(segment,index){
2396
- segment.transition({
2397
- circumference : this.calculateCircumference(segment.value),
2398
- outerRadius : this.outerRadius,
2399
- innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
2400
- },animDecimal);
2401
-
2402
- segment.endAngle = segment.startAngle + segment.circumference;
2403
-
2404
- segment.draw();
2405
- if (index === 0){
2406
- segment.startAngle = Math.PI * 1.5;
2407
- }
2408
- //Check to see if it's the last segment, if not get the next and update the start angle
2409
- if (index < this.segments.length-1){
2410
- this.segments[index+1].startAngle = segment.endAngle;
2411
- }
2412
- },this);
2413
-
2414
- }
2415
- });
2416
-
2417
- Chart.types.Doughnut.extend({
2418
- name : "Pie",
2419
- defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0})
2420
- });
2421
-
2422
- }).call(this);
2423
- (function(){
2424
- "use strict";
2425
-
2426
- var root = this,
2427
- Chart = root.Chart,
2428
- helpers = Chart.helpers;
2429
-
2430
- var defaultConfig = {
2431
-
2432
- ///Boolean - Whether grid lines are shown across the chart
2433
- scaleShowGridLines : true,
2434
-
2435
- //String - Colour of the grid lines
2436
- scaleGridLineColor : "rgba(0,0,0,.05)",
2437
-
2438
- //Number - Width of the grid lines
2439
- scaleGridLineWidth : 1,
2440
-
2441
- //Boolean - Whether the line is curved between points
2442
- bezierCurve : true,
2443
-
2444
- //Number - Tension of the bezier curve between points
2445
- bezierCurveTension : 0.4,
2446
-
2447
- //Boolean - Whether to show a dot for each point
2448
- pointDot : true,
2449
-
2450
- //Number - Radius of each point dot in pixels
2451
- pointDotRadius : 4,
2452
-
2453
- //Number - Pixel width of point dot stroke
2454
- pointDotStrokeWidth : 1,
2455
-
2456
- //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
2457
- pointHitDetectionRadius : 20,
2458
-
2459
- //Boolean - Whether to show a stroke for datasets
2460
- datasetStroke : true,
2461
-
2462
- //Number - Pixel width of dataset stroke
2463
- datasetStrokeWidth : 2,
2464
-
2465
- //Boolean - Whether to fill the dataset with a colour
2466
- datasetFill : true,
2467
-
2468
- //String - A legend template
2469
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
2470
-
2471
- };
2472
-
2473
-
2474
- Chart.Type.extend({
2475
- name: "Line",
2476
- defaults : defaultConfig,
2477
- initialize: function(data){
2478
- //Declare the extension of the default point, to cater for the options passed in to the constructor
2479
- this.PointClass = Chart.Point.extend({
2480
- strokeWidth : this.options.pointDotStrokeWidth,
2481
- radius : this.options.pointDotRadius,
2482
- display: this.options.pointDot,
2483
- hitDetectionRadius : this.options.pointHitDetectionRadius,
2484
- ctx : this.chart.ctx,
2485
- inRange : function(mouseX){
2486
- return (Math.pow(mouseX-this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius,2));
2487
- }
2488
- });
2489
-
2490
- this.datasets = [];
2491
-
2492
- //Set up tooltip events on the chart
2493
- if (this.options.showTooltips){
2494
- helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
2495
- var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
2496
- this.eachPoints(function(point){
2497
- point.restore(['fillColor', 'strokeColor']);
2498
- });
2499
- helpers.each(activePoints, function(activePoint){
2500
- activePoint.fillColor = activePoint.highlightFill;
2501
- activePoint.strokeColor = activePoint.highlightStroke;
2502
- });
2503
- this.showTooltip(activePoints);
2504
- });
2505
- }
2506
-
2507
- //Iterate through each of the datasets, and build this into a property of the chart
2508
- helpers.each(data.datasets,function(dataset){
2509
-
2510
- var datasetObject = {
2511
- label : dataset.label || null,
2512
- fillColor : dataset.fillColor,
2513
- strokeColor : dataset.strokeColor,
2514
- pointColor : dataset.pointColor,
2515
- pointStrokeColor : dataset.pointStrokeColor,
2516
- points : []
2517
- };
2518
-
2519
- this.datasets.push(datasetObject);
2520
-
2521
-
2522
- helpers.each(dataset.data,function(dataPoint,index){
2523
- //Add a new point for each piece of data, passing any required data to draw.
2524
- datasetObject.points.push(new this.PointClass({
2525
- value : dataPoint,
2526
- label : data.labels[index],
2527
- datasetLabel: dataset.label,
2528
- strokeColor : dataset.pointStrokeColor,
2529
- fillColor : dataset.pointColor,
2530
- highlightFill : dataset.pointHighlightFill || dataset.pointColor,
2531
- highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
2532
- }));
2533
- },this);
2534
-
2535
- this.buildScale(data.labels);
2536
-
2537
-
2538
- this.eachPoints(function(point, index){
2539
- helpers.extend(point, {
2540
- x: this.scale.calculateX(index),
2541
- y: this.scale.endPoint
2542
- });
2543
- point.save();
2544
- }, this);
2545
-
2546
- },this);
2547
-
2548
-
2549
- this.render();
2550
- },
2551
- update : function(){
2552
- this.scale.update();
2553
- // Reset any highlight colours before updating.
2554
- helpers.each(this.activeElements, function(activeElement){
2555
- activeElement.restore(['fillColor', 'strokeColor']);
2556
- });
2557
- this.eachPoints(function(point){
2558
- point.save();
2559
- });
2560
- this.render();
2561
- },
2562
- eachPoints : function(callback){
2563
- helpers.each(this.datasets,function(dataset){
2564
- helpers.each(dataset.points,callback,this);
2565
- },this);
2566
- },
2567
- getPointsAtEvent : function(e){
2568
- var pointsArray = [],
2569
- eventPosition = helpers.getRelativePosition(e);
2570
- helpers.each(this.datasets,function(dataset){
2571
- helpers.each(dataset.points,function(point){
2572
- if (point.inRange(eventPosition.x,eventPosition.y)) pointsArray.push(point);
2573
- });
2574
- },this);
2575
- return pointsArray;
2576
- },
2577
- buildScale : function(labels){
2578
- var self = this;
2579
-
2580
- var dataTotal = function(){
2581
- var values = [];
2582
- self.eachPoints(function(point){
2583
- values.push(point.value);
2584
- });
2585
-
2586
- return values;
2587
- };
2588
-
2589
- var scaleOptions = {
2590
- templateString : this.options.scaleLabel,
2591
- height : this.chart.height,
2592
- width : this.chart.width,
2593
- ctx : this.chart.ctx,
2594
- textColor : this.options.scaleFontColor,
2595
- fontSize : this.options.scaleFontSize,
2596
- fontStyle : this.options.scaleFontStyle,
2597
- fontFamily : this.options.scaleFontFamily,
2598
- valuesCount : labels.length,
2599
- beginAtZero : this.options.scaleBeginAtZero,
2600
- integersOnly : this.options.scaleIntegersOnly,
2601
- calculateYRange : function(currentHeight){
2602
- var updatedRanges = helpers.calculateScaleRange(
2603
- dataTotal(),
2604
- currentHeight,
2605
- this.fontSize,
2606
- this.beginAtZero,
2607
- this.integersOnly
2608
- );
2609
- helpers.extend(this, updatedRanges);
2610
- },
2611
- xLabels : labels,
2612
- font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
2613
- lineWidth : this.options.scaleLineWidth,
2614
- lineColor : this.options.scaleLineColor,
2615
- gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
2616
- gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
2617
- padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
2618
- showLabels : this.options.scaleShowLabels,
2619
- display : this.options.showScale
2620
- };
2621
-
2622
- if (this.options.scaleOverride){
2623
- helpers.extend(scaleOptions, {
2624
- calculateYRange: helpers.noop,
2625
- steps: this.options.scaleSteps,
2626
- stepValue: this.options.scaleStepWidth,
2627
- min: this.options.scaleStartValue,
2628
- max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
2629
- });
2630
- }
2631
-
2632
-
2633
- this.scale = new Chart.Scale(scaleOptions);
2634
- },
2635
- addData : function(valuesArray,label){
2636
- //Map the values array for each of the datasets
2637
-
2638
- helpers.each(valuesArray,function(value,datasetIndex){
2639
- //Add a new point for each piece of data, passing any required data to draw.
2640
- this.datasets[datasetIndex].points.push(new this.PointClass({
2641
- value : value,
2642
- label : label,
2643
- x: this.scale.calculateX(this.scale.valuesCount+1),
2644
- y: this.scale.endPoint,
2645
- strokeColor : this.datasets[datasetIndex].pointStrokeColor,
2646
- fillColor : this.datasets[datasetIndex].pointColor
2647
- }));
2648
- },this);
2649
-
2650
- this.scale.addXLabel(label);
2651
- //Then re-render the chart.
2652
- this.update();
2653
- },
2654
- removeData : function(){
2655
- this.scale.removeXLabel();
2656
- //Then re-render the chart.
2657
- helpers.each(this.datasets,function(dataset){
2658
- dataset.points.shift();
2659
- },this);
2660
- this.update();
2661
- },
2662
- reflow : function(){
2663
- var newScaleProps = helpers.extend({
2664
- height : this.chart.height,
2665
- width : this.chart.width
2666
- });
2667
- this.scale.update(newScaleProps);
2668
- },
2669
- draw : function(ease){
2670
- var easingDecimal = ease || 1;
2671
- this.clear();
2672
-
2673
- var ctx = this.chart.ctx;
2674
-
2675
- // Some helper methods for getting the next/prev points
2676
- var hasValue = function(item){
2677
- return item.value !== null;
2678
- },
2679
- nextPoint = function(point, collection, index){
2680
- return helpers.findNextWhere(collection, hasValue, index) || point;
2681
- },
2682
- previousPoint = function(point, collection, index){
2683
- return helpers.findPreviousWhere(collection, hasValue, index) || point;
2684
- };
2685
-
2686
- this.scale.draw(easingDecimal);
2687
-
2688
-
2689
- helpers.each(this.datasets,function(dataset){
2690
- var pointsWithValues = helpers.where(dataset.points, hasValue);
2691
-
2692
- //Transition each point first so that the line and point drawing isn't out of sync
2693
- //We can use this extra loop to calculate the control points of this dataset also in this loop
2694
-
2695
- helpers.each(dataset.points, function(point, index){
2696
- if (point.hasValue()){
2697
- point.transition({
2698
- y : this.scale.calculateY(point.value),
2699
- x : this.scale.calculateX(index)
2700
- }, easingDecimal);
2701
- }
2702
- },this);
2703
-
2704
-
2705
- // Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point
2706
- // This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed
2707
- if (this.options.bezierCurve){
2708
- helpers.each(pointsWithValues, function(point, index){
2709
- var tension = (index > 0 && index < pointsWithValues.length - 1) ? this.options.bezierCurveTension : 0;
2710
- point.controlPoints = helpers.splineCurve(
2711
- previousPoint(point, pointsWithValues, index),
2712
- point,
2713
- nextPoint(point, pointsWithValues, index),
2714
- tension
2715
- );
2716
-
2717
- // Prevent the bezier going outside of the bounds of the graph
2718
-
2719
- // Cap puter bezier handles to the upper/lower scale bounds
2720
- if (point.controlPoints.outer.y > this.scale.endPoint){
2721
- point.controlPoints.outer.y = this.scale.endPoint;
2722
- }
2723
- else if (point.controlPoints.outer.y < this.scale.startPoint){
2724
- point.controlPoints.outer.y = this.scale.startPoint;
2725
- }
2726
-
2727
- // Cap inner bezier handles to the upper/lower scale bounds
2728
- if (point.controlPoints.inner.y > this.scale.endPoint){
2729
- point.controlPoints.inner.y = this.scale.endPoint;
2730
- }
2731
- else if (point.controlPoints.inner.y < this.scale.startPoint){
2732
- point.controlPoints.inner.y = this.scale.startPoint;
2733
- }
2734
- },this);
2735
- }
2736
-
2737
-
2738
- //Draw the line between all the points
2739
- ctx.lineWidth = this.options.datasetStrokeWidth;
2740
- ctx.strokeStyle = dataset.strokeColor;
2741
- ctx.beginPath();
2742
-
2743
- helpers.each(pointsWithValues, function(point, index){
2744
- if (index === 0){
2745
- ctx.moveTo(point.x, point.y);
2746
- }
2747
- else{
2748
- if(this.options.bezierCurve){
2749
- var previous = previousPoint(point, pointsWithValues, index);
2750
-
2751
- ctx.bezierCurveTo(
2752
- previous.controlPoints.outer.x,
2753
- previous.controlPoints.outer.y,
2754
- point.controlPoints.inner.x,
2755
- point.controlPoints.inner.y,
2756
- point.x,
2757
- point.y
2758
- );
2759
- }
2760
- else{
2761
- ctx.lineTo(point.x,point.y);
2762
- }
2763
- }
2764
- }, this);
2765
-
2766
- ctx.stroke();
2767
-
2768
- if (this.options.datasetFill && pointsWithValues.length > 0){
2769
- //Round off the line by going to the base of the chart, back to the start, then fill.
2770
- ctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint);
2771
- ctx.lineTo(pointsWithValues[0].x, this.scale.endPoint);
2772
- ctx.fillStyle = dataset.fillColor;
2773
- ctx.closePath();
2774
- ctx.fill();
2775
- }
2776
-
2777
- //Now draw the points over the line
2778
- //A little inefficient double looping, but better than the line
2779
- //lagging behind the point positions
2780
- helpers.each(pointsWithValues,function(point){
2781
- point.draw();
2782
- });
2783
- },this);
2784
- }
2785
- });
2786
-
2787
-
2788
- }).call(this);
2789
- (function(){
2790
- "use strict";
2791
-
2792
- var root = this,
2793
- Chart = root.Chart,
2794
- //Cache a local reference to Chart.helpers
2795
- helpers = Chart.helpers;
2796
-
2797
- var defaultConfig = {
2798
- //Boolean - Show a backdrop to the scale label
2799
- scaleShowLabelBackdrop : true,
2800
-
2801
- //String - The colour of the label backdrop
2802
- scaleBackdropColor : "rgba(255,255,255,0.75)",
2803
-
2804
- // Boolean - Whether the scale should begin at zero
2805
- scaleBeginAtZero : true,
2806
-
2807
- //Number - The backdrop padding above & below the label in pixels
2808
- scaleBackdropPaddingY : 2,
2809
-
2810
- //Number - The backdrop padding to the side of the label in pixels
2811
- scaleBackdropPaddingX : 2,
2812
-
2813
- //Boolean - Show line for each value in the scale
2814
- scaleShowLine : true,
2815
-
2816
- //Boolean - Stroke a line around each segment in the chart
2817
- segmentShowStroke : true,
2818
-
2819
- //String - The colour of the stroke on each segement.
2820
- segmentStrokeColor : "#fff",
2821
-
2822
- //Number - The width of the stroke value in pixels
2823
- segmentStrokeWidth : 2,
2824
-
2825
- //Number - Amount of animation steps
2826
- animationSteps : 100,
2827
-
2828
- //String - Animation easing effect.
2829
- animationEasing : "easeOutBounce",
2830
-
2831
- //Boolean - Whether to animate the rotation of the chart
2832
- animateRotate : true,
2833
-
2834
- //Boolean - Whether to animate scaling the chart from the centre
2835
- animateScale : false,
2836
-
2837
- //String - A legend template
2838
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
2839
- };
2840
-
2841
-
2842
- Chart.Type.extend({
2843
- //Passing in a name registers this chart in the Chart namespace
2844
- name: "PolarArea",
2845
- //Providing a defaults will also register the deafults in the chart namespace
2846
- defaults : defaultConfig,
2847
- //Initialize is fired when the chart is initialized - Data is passed in as a parameter
2848
- //Config is automatically merged by the core of Chart.js, and is available at this.options
2849
- initialize: function(data){
2850
- this.segments = [];
2851
- //Declare segment class as a chart instance specific class, so it can share props for this instance
2852
- this.SegmentArc = Chart.Arc.extend({
2853
- showStroke : this.options.segmentShowStroke,
2854
- strokeWidth : this.options.segmentStrokeWidth,
2855
- strokeColor : this.options.segmentStrokeColor,
2856
- ctx : this.chart.ctx,
2857
- innerRadius : 0,
2858
- x : this.chart.width/2,
2859
- y : this.chart.height/2
2860
- });
2861
- this.scale = new Chart.RadialScale({
2862
- display: this.options.showScale,
2863
- fontStyle: this.options.scaleFontStyle,
2864
- fontSize: this.options.scaleFontSize,
2865
- fontFamily: this.options.scaleFontFamily,
2866
- fontColor: this.options.scaleFontColor,
2867
- showLabels: this.options.scaleShowLabels,
2868
- showLabelBackdrop: this.options.scaleShowLabelBackdrop,
2869
- backdropColor: this.options.scaleBackdropColor,
2870
- backdropPaddingY : this.options.scaleBackdropPaddingY,
2871
- backdropPaddingX: this.options.scaleBackdropPaddingX,
2872
- lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
2873
- lineColor: this.options.scaleLineColor,
2874
- lineArc: true,
2875
- width: this.chart.width,
2876
- height: this.chart.height,
2877
- xCenter: this.chart.width/2,
2878
- yCenter: this.chart.height/2,
2879
- ctx : this.chart.ctx,
2880
- templateString: this.options.scaleLabel,
2881
- valuesCount: data.length
2882
- });
2883
-
2884
- this.updateScaleRange(data);
2885
-
2886
- this.scale.update();
2887
-
2888
- helpers.each(data,function(segment,index){
2889
- this.addData(segment,index,true);
2890
- },this);
2891
-
2892
- //Set up tooltip events on the chart
2893
- if (this.options.showTooltips){
2894
- helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
2895
- var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
2896
- helpers.each(this.segments,function(segment){
2897
- segment.restore(["fillColor"]);
2898
- });
2899
- helpers.each(activeSegments,function(activeSegment){
2900
- activeSegment.fillColor = activeSegment.highlightColor;
2901
- });
2902
- this.showTooltip(activeSegments);
2903
- });
2904
- }
2905
-
2906
- this.render();
2907
- },
2908
- getSegmentsAtEvent : function(e){
2909
- var segmentsArray = [];
2910
-
2911
- var location = helpers.getRelativePosition(e);
2912
-
2913
- helpers.each(this.segments,function(segment){
2914
- if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
2915
- },this);
2916
- return segmentsArray;
2917
- },
2918
- addData : function(segment, atIndex, silent){
2919
- var index = atIndex || this.segments.length;
2920
-
2921
- this.segments.splice(index, 0, new this.SegmentArc({
2922
- fillColor: segment.color,
2923
- highlightColor: segment.highlight || segment.color,
2924
- label: segment.label,
2925
- value: segment.value,
2926
- outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),
2927
- circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),
2928
- startAngle: Math.PI * 1.5
2929
- }));
2930
- if (!silent){
2931
- this.reflow();
2932
- this.update();
2933
- }
2934
- },
2935
- removeData: function(atIndex){
2936
- var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
2937
- this.segments.splice(indexToDelete, 1);
2938
- this.reflow();
2939
- this.update();
2940
- },
2941
- calculateTotal: function(data){
2942
- this.total = 0;
2943
- helpers.each(data,function(segment){
2944
- this.total += segment.value;
2945
- },this);
2946
- this.scale.valuesCount = this.segments.length;
2947
- },
2948
- updateScaleRange: function(datapoints){
2949
- var valuesArray = [];
2950
- helpers.each(datapoints,function(segment){
2951
- valuesArray.push(segment.value);
2952
- });
2953
-
2954
- var scaleSizes = (this.options.scaleOverride) ?
2955
- {
2956
- steps: this.options.scaleSteps,
2957
- stepValue: this.options.scaleStepWidth,
2958
- min: this.options.scaleStartValue,
2959
- max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
2960
- } :
2961
- helpers.calculateScaleRange(
2962
- valuesArray,
2963
- helpers.min([this.chart.width, this.chart.height])/2,
2964
- this.options.scaleFontSize,
2965
- this.options.scaleBeginAtZero,
2966
- this.options.scaleIntegersOnly
2967
- );
2968
-
2969
- helpers.extend(
2970
- this.scale,
2971
- scaleSizes,
2972
- {
2973
- size: helpers.min([this.chart.width, this.chart.height]),
2974
- xCenter: this.chart.width/2,
2975
- yCenter: this.chart.height/2
2976
- }
2977
- );
2978
-
2979
- },
2980
- update : function(){
2981
- this.calculateTotal(this.segments);
2982
-
2983
- helpers.each(this.segments,function(segment){
2984
- segment.save();
2985
- });
2986
- this.render();
2987
- },
2988
- reflow : function(){
2989
- helpers.extend(this.SegmentArc.prototype,{
2990
- x : this.chart.width/2,
2991
- y : this.chart.height/2
2992
- });
2993
- this.updateScaleRange(this.segments);
2994
- this.scale.update();
2995
-
2996
- helpers.extend(this.scale,{
2997
- xCenter: this.chart.width/2,
2998
- yCenter: this.chart.height/2
2999
- });
3000
-
3001
- helpers.each(this.segments, function(segment){
3002
- segment.update({
3003
- outerRadius : this.scale.calculateCenterOffset(segment.value)
3004
- });
3005
- }, this);
3006
-
3007
- },
3008
- draw : function(ease){
3009
- var easingDecimal = ease || 1;
3010
- //Clear & draw the canvas
3011
- this.clear();
3012
- helpers.each(this.segments,function(segment, index){
3013
- segment.transition({
3014
- circumference : this.scale.getCircumference(),
3015
- outerRadius : this.scale.calculateCenterOffset(segment.value)
3016
- },easingDecimal);
3017
-
3018
- segment.endAngle = segment.startAngle + segment.circumference;
3019
-
3020
- // If we've removed the first segment we need to set the first one to
3021
- // start at the top.
3022
- if (index === 0){
3023
- segment.startAngle = Math.PI * 1.5;
3024
- }
3025
-
3026
- //Check to see if it's the last segment, if not get the next and update the start angle
3027
- if (index < this.segments.length - 1){
3028
- this.segments[index+1].startAngle = segment.endAngle;
3029
- }
3030
- segment.draw();
3031
- }, this);
3032
- this.scale.draw();
3033
- }
3034
- });
3035
-
3036
- }).call(this);
3037
- (function(){
3038
- "use strict";
3039
-
3040
- var root = this,
3041
- Chart = root.Chart,
3042
- helpers = Chart.helpers;
3043
-
3044
-
3045
-
3046
- Chart.Type.extend({
3047
- name: "Radar",
3048
- defaults:{
3049
- //Boolean - Whether to show lines for each scale point
3050
- scaleShowLine : true,
3051
-
3052
- //Boolean - Whether we show the angle lines out of the radar
3053
- angleShowLineOut : true,
3054
-
3055
- //Boolean - Whether to show labels on the scale
3056
- scaleShowLabels : false,
3057
-
3058
- // Boolean - Whether the scale should begin at zero
3059
- scaleBeginAtZero : true,
3060
-
3061
- //String - Colour of the angle line
3062
- angleLineColor : "rgba(0,0,0,.1)",
3063
-
3064
- //Number - Pixel width of the angle line
3065
- angleLineWidth : 1,
3066
-
3067
- //String - Point label font declaration
3068
- pointLabelFontFamily : "'Arial'",
3069
-
3070
- //String - Point label font weight
3071
- pointLabelFontStyle : "normal",
3072
-
3073
- //Number - Point label font size in pixels
3074
- pointLabelFontSize : 10,
3075
-
3076
- //String - Point label font colour
3077
- pointLabelFontColor : "#666",
3078
-
3079
- //Boolean - Whether to show a dot for each point
3080
- pointDot : true,
3081
-
3082
- //Number - Radius of each point dot in pixels
3083
- pointDotRadius : 3,
3084
-
3085
- //Number - Pixel width of point dot stroke
3086
- pointDotStrokeWidth : 1,
3087
-
3088
- //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
3089
- pointHitDetectionRadius : 20,
3090
-
3091
- //Boolean - Whether to show a stroke for datasets
3092
- datasetStroke : true,
3093
-
3094
- //Number - Pixel width of dataset stroke
3095
- datasetStrokeWidth : 2,
3096
-
3097
- //Boolean - Whether to fill the dataset with a colour
3098
- datasetFill : true,
3099
-
3100
- //String - A legend template
3101
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
3102
-
3103
- },
3104
-
3105
- initialize: function(data){
3106
- this.PointClass = Chart.Point.extend({
3107
- strokeWidth : this.options.pointDotStrokeWidth,
3108
- radius : this.options.pointDotRadius,
3109
- display: this.options.pointDot,
3110
- hitDetectionRadius : this.options.pointHitDetectionRadius,
3111
- ctx : this.chart.ctx
3112
- });
3113
-
3114
- this.datasets = [];
3115
-
3116
- this.buildScale(data);
3117
-
3118
- //Set up tooltip events on the chart
3119
- if (this.options.showTooltips){
3120
- helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
3121
- var activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
3122
-
3123
- this.eachPoints(function(point){
3124
- point.restore(['fillColor', 'strokeColor']);
3125
- });
3126
- helpers.each(activePointsCollection, function(activePoint){
3127
- activePoint.fillColor = activePoint.highlightFill;
3128
- activePoint.strokeColor = activePoint.highlightStroke;
3129
- });
3130
-
3131
- this.showTooltip(activePointsCollection);
3132
- });
3133
- }
3134
-
3135
- //Iterate through each of the datasets, and build this into a property of the chart
3136
- helpers.each(data.datasets,function(dataset){
3137
-
3138
- var datasetObject = {
3139
- label: dataset.label || null,
3140
- fillColor : dataset.fillColor,
3141
- strokeColor : dataset.strokeColor,
3142
- pointColor : dataset.pointColor,
3143
- pointStrokeColor : dataset.pointStrokeColor,
3144
- points : []
3145
- };
3146
-
3147
- this.datasets.push(datasetObject);
3148
-
3149
- helpers.each(dataset.data,function(dataPoint,index){
3150
- //Add a new point for each piece of data, passing any required data to draw.
3151
- var pointPosition;
3152
- if (!this.scale.animation){
3153
- pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));
3154
- }
3155
- datasetObject.points.push(new this.PointClass({
3156
- value : dataPoint,
3157
- label : data.labels[index],
3158
- datasetLabel: dataset.label,
3159
- x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
3160
- y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
3161
- strokeColor : dataset.pointStrokeColor,
3162
- fillColor : dataset.pointColor,
3163
- highlightFill : dataset.pointHighlightFill || dataset.pointColor,
3164
- highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
3165
- }));
3166
- },this);
3167
-
3168
- },this);
3169
-
3170
- this.render();
3171
- },
3172
- eachPoints : function(callback){
3173
- helpers.each(this.datasets,function(dataset){
3174
- helpers.each(dataset.points,callback,this);
3175
- },this);
3176
- },
3177
-
3178
- getPointsAtEvent : function(evt){
3179
- var mousePosition = helpers.getRelativePosition(evt),
3180
- fromCenter = helpers.getAngleFromPoint({
3181
- x: this.scale.xCenter,
3182
- y: this.scale.yCenter
3183
- }, mousePosition);
3184
-
3185
- var anglePerIndex = (Math.PI * 2) /this.scale.valuesCount,
3186
- pointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex),
3187
- activePointsCollection = [];
3188
-
3189
- // If we're at the top, make the pointIndex 0 to get the first of the array.
3190
- if (pointIndex >= this.scale.valuesCount || pointIndex < 0){
3191
- pointIndex = 0;
3192
- }
3193
-
3194
- if (fromCenter.distance <= this.scale.drawingArea){
3195
- helpers.each(this.datasets, function(dataset){
3196
- activePointsCollection.push(dataset.points[pointIndex]);
3197
- });
3198
- }
3199
-
3200
- return activePointsCollection;
3201
- },
3202
-
3203
- buildScale : function(data){
3204
- this.scale = new Chart.RadialScale({
3205
- display: this.options.showScale,
3206
- fontStyle: this.options.scaleFontStyle,
3207
- fontSize: this.options.scaleFontSize,
3208
- fontFamily: this.options.scaleFontFamily,
3209
- fontColor: this.options.scaleFontColor,
3210
- showLabels: this.options.scaleShowLabels,
3211
- showLabelBackdrop: this.options.scaleShowLabelBackdrop,
3212
- backdropColor: this.options.scaleBackdropColor,
3213
- backdropPaddingY : this.options.scaleBackdropPaddingY,
3214
- backdropPaddingX: this.options.scaleBackdropPaddingX,
3215
- lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
3216
- lineColor: this.options.scaleLineColor,
3217
- angleLineColor : this.options.angleLineColor,
3218
- angleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0,
3219
- // Point labels at the edge of each line
3220
- pointLabelFontColor : this.options.pointLabelFontColor,
3221
- pointLabelFontSize : this.options.pointLabelFontSize,
3222
- pointLabelFontFamily : this.options.pointLabelFontFamily,
3223
- pointLabelFontStyle : this.options.pointLabelFontStyle,
3224
- height : this.chart.height,
3225
- width: this.chart.width,
3226
- xCenter: this.chart.width/2,
3227
- yCenter: this.chart.height/2,
3228
- ctx : this.chart.ctx,
3229
- templateString: this.options.scaleLabel,
3230
- labels: data.labels,
3231
- valuesCount: data.datasets[0].data.length
3232
- });
3233
-
3234
- this.scale.setScaleSize();
3235
- this.updateScaleRange(data.datasets);
3236
- this.scale.buildYLabels();
3237
- },
3238
- updateScaleRange: function(datasets){
3239
- var valuesArray = (function(){
3240
- var totalDataArray = [];
3241
- helpers.each(datasets,function(dataset){
3242
- if (dataset.data){
3243
- totalDataArray = totalDataArray.concat(dataset.data);
3244
- }
3245
- else {
3246
- helpers.each(dataset.points, function(point){
3247
- totalDataArray.push(point.value);
3248
- });
3249
- }
3250
- });
3251
- return totalDataArray;
3252
- })();
3253
-
3254
-
3255
- var scaleSizes = (this.options.scaleOverride) ?
3256
- {
3257
- steps: this.options.scaleSteps,
3258
- stepValue: this.options.scaleStepWidth,
3259
- min: this.options.scaleStartValue,
3260
- max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
3261
- } :
3262
- helpers.calculateScaleRange(
3263
- valuesArray,
3264
- helpers.min([this.chart.width, this.chart.height])/2,
3265
- this.options.scaleFontSize,
3266
- this.options.scaleBeginAtZero,
3267
- this.options.scaleIntegersOnly
3268
- );
3269
-
3270
- helpers.extend(
3271
- this.scale,
3272
- scaleSizes
3273
- );
3274
-
3275
- },
3276
- addData : function(valuesArray,label){
3277
- //Map the values array for each of the datasets
3278
- this.scale.valuesCount++;
3279
- helpers.each(valuesArray,function(value,datasetIndex){
3280
- var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));
3281
- this.datasets[datasetIndex].points.push(new this.PointClass({
3282
- value : value,
3283
- label : label,
3284
- x: pointPosition.x,
3285
- y: pointPosition.y,
3286
- strokeColor : this.datasets[datasetIndex].pointStrokeColor,
3287
- fillColor : this.datasets[datasetIndex].pointColor
3288
- }));
3289
- },this);
3290
-
3291
- this.scale.labels.push(label);
3292
-
3293
- this.reflow();
3294
-
3295
- this.update();
3296
- },
3297
- removeData : function(){
3298
- this.scale.valuesCount--;
3299
- this.scale.labels.shift();
3300
- helpers.each(this.datasets,function(dataset){
3301
- dataset.points.shift();
3302
- },this);
3303
- this.reflow();
3304
- this.update();
3305
- },
3306
- update : function(){
3307
- this.eachPoints(function(point){
3308
- point.save();
3309
- });
3310
- this.reflow();
3311
- this.render();
3312
- },
3313
- reflow: function(){
3314
- helpers.extend(this.scale, {
3315
- width : this.chart.width,
3316
- height: this.chart.height,
3317
- size : helpers.min([this.chart.width, this.chart.height]),
3318
- xCenter: this.chart.width/2,
3319
- yCenter: this.chart.height/2
3320
- });
3321
- this.updateScaleRange(this.datasets);
3322
- this.scale.setScaleSize();
3323
- this.scale.buildYLabels();
3324
- },
3325
- draw : function(ease){
3326
- var easeDecimal = ease || 1,
3327
- ctx = this.chart.ctx;
3328
- this.clear();
3329
- this.scale.draw();
3330
-
3331
- helpers.each(this.datasets,function(dataset){
3332
-
3333
- //Transition each point first so that the line and point drawing isn't out of sync
3334
- helpers.each(dataset.points,function(point,index){
3335
- if (point.hasValue()){
3336
- point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);
3337
- }
3338
- },this);
3339
-
3340
-
3341
-
3342
- //Draw the line between all the points
3343
- ctx.lineWidth = this.options.datasetStrokeWidth;
3344
- ctx.strokeStyle = dataset.strokeColor;
3345
- ctx.beginPath();
3346
- helpers.each(dataset.points,function(point,index){
3347
- if (index === 0){
3348
- ctx.moveTo(point.x,point.y);
3349
- }
3350
- else{
3351
- ctx.lineTo(point.x,point.y);
3352
- }
3353
- },this);
3354
- ctx.closePath();
3355
- ctx.stroke();
3356
-
3357
- ctx.fillStyle = dataset.fillColor;
3358
- ctx.fill();
3359
-
3360
- //Now draw the points over the line
3361
- //A little inefficient double looping, but better than the line
3362
- //lagging behind the point positions
3363
- helpers.each(dataset.points,function(point){
3364
- if (point.hasValue()){
3365
- point.draw();
3366
- }
3367
- });
3368
-
3369
- },this);
3370
-
3371
- }
3372
-
3373
- });
3374
-
3375
-
3376
-
3377
-
3378
-
3379
- }).call(this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/Chart.min.js CHANGED
@@ -1,11 +1,7 @@
1
  /*!
2
- * Chart.js
3
- * http://chartjs.org/
4
- * Version: 1.0.1-beta.4
5
- *
6
- * Copyright 2014 Nick Downie
7
- * Released under the MIT license
8
- * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
9
  */
10
- (function(){"use strict";var t=this,i=t.Chart,e=function(t){this.canvas=t.canvas,this.ctx=t;this.width=t.canvas.width,this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,s.retinaScale(this),this};e.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},e.types={};var s=e.helpers={},n=s.each=function(t,i,e){var s=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var n;for(n=0;n<t.length;n++)i.apply(e,[t[n],n].concat(s))}else for(var o in t)i.apply(e,[t[o],o].concat(s))},o=s.clone=function(t){var i={};return n(t,function(e,s){t.hasOwnProperty(s)&&(i[s]=e)}),i},a=s.extend=function(t){return n(Array.prototype.slice.call(arguments,1),function(i){n(i,function(e,s){i.hasOwnProperty(s)&&(t[s]=e)})}),t},h=s.merge=function(){var t=Array.prototype.slice.call(arguments,0);return t.unshift({}),a.apply(null,t)},l=s.indexOf=function(t,i){if(Array.prototype.indexOf)return t.indexOf(i);for(var e=0;e<t.length;e++)if(t[e]===i)return e;return-1},r=(s.where=function(t,i){var e=[];return s.each(t,function(t){i(t)&&e.push(t)}),e},s.findNextWhere=function(t,i,e){e||(e=-1);for(var s=e+1;s<t.length;s++){var n=t[s];if(i(n))return n}},s.findPreviousWhere=function(t,i,e){e||(e=t.length);for(var s=e-1;s>=0;s--){var n=t[s];if(i(n))return n}},s.inherits=function(t){var i=this,e=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return i.apply(this,arguments)},s=function(){this.constructor=e};return s.prototype=i.prototype,e.prototype=new s,e.extend=r,t&&a(e.prototype,t),e.__super__=i.prototype,e}),c=s.noop=function(){},u=s.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=s.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},p=s.amd="function"==typeof t.define&&t.define.amd,f=s.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=s.max=function(t){return Math.max.apply(Math,t)},m=s.min=function(t){return Math.min.apply(Math,t)},v=(s.cap=function(t,i,e){if(f(i)){if(t>i)return i}else if(f(e)&&e>t)return e;return t},s.getDecimalPlaces=function(t){return t%1!==0&&f(t)?t.toString().split(".")[1].length:0}),x=s.radians=function(t){return t*(Math.PI/180)},S=(s.getAngleFromPoint=function(t,i){var e=i.x-t.x,s=i.y-t.y,n=Math.sqrt(e*e+s*s),o=2*Math.PI+Math.atan2(s,e);return 0>e&&0>s&&(o+=2*Math.PI),{angle:o,distance:n}},s.aliasPixel=function(t){return t%2===0?0:.5}),y=(s.splineCurve=function(t,i,e,s){var n=Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2)),o=Math.sqrt(Math.pow(e.x-i.x,2)+Math.pow(e.y-i.y,2)),a=s*n/(n+o),h=s*o/(n+o);return{inner:{x:i.x-a*(e.x-t.x),y:i.y-a*(e.y-t.y)},outer:{x:i.x+h*(e.x-t.x),y:i.y+h*(e.y-t.y)}}},s.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}),C=(s.calculateScaleRange=function(t,i,e,s,n){var o=2,a=Math.floor(i/(1.5*e)),h=o>=a,l=g(t),r=m(t);l===r&&(l+=.5,r>=.5&&!s?r-=.5:l+=.5);for(var c=Math.abs(l-r),u=y(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),p=s?0:Math.floor(r/(1*Math.pow(10,u)))*Math.pow(10,u),f=d-p,v=Math.pow(10,u),x=Math.round(f/v);(x>a||a>2*x)&&!h;)if(x>a)v*=2,x=Math.round(f/v),x%1!==0&&(h=!0);else if(n&&u>=0){if(v/2%1!==0)break;v/=2,x=Math.round(f/v)}else v/=2,x=Math.round(f/v);return h&&(x=o,v=f/x),{steps:x,stepValue:v,min:p,max:p+x*v}},s.template=function(t,i){function e(t,i){var e=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join(" ").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split(" ").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):s[t]=s[t];return i?e(i):e}if(t instanceof Function)return t(i);var s={};return e(t,i)}),b=(s.generateLabels=function(t,i,e,s){var o=new Array(i);return labelTemplateString&&n(o,function(i,n){o[n]=C(t,{value:e+s*(n+1)})}),o},s.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){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-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){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/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),-(s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)))},easeOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),s*Math.pow(2,-10*t)*Math.sin(2*(1*t-i)*Math.PI/e)+1)},easeInOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:2==(t/=.5)?1:(e||(e=.3*1.5),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),1>t?-.5*s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e):s*Math.pow(2,-10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)*.5+1)},easeInBack:function(t){var i=1.70158;return 1*(t/=1)*t*((i+1)*t-i)},easeOutBack:function(t){var i=1.70158;return 1*((t=t/1-1)*t*((i+1)*t+i)+1)},easeInOutBack:function(t){var i=1.70158;return(t/=.5)<1?.5*t*t*(((i*=1.525)+1)*t-i):.5*((t-=2)*t*(((i*=1.525)+1)*t+i)+2)},easeInBounce:function(t){return 1-b.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t:2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*b.easeInBounce(2*t):.5*b.easeOutBounce(2*t-1)+.5}}),w=s.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=(s.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),s.animationLoop=function(t,i,e,s,n,o){var a=0,h=b[e]||b.linear,l=function(){a++;var e=a/i,r=h(e);t.call(o,r,e,a),s.call(o,r,e),i>a?o.animationFrame=w(l):n.apply(o)};w(l)},s.getRelativePosition=function(t){var i,e,s=t.originalEvent||t,n=t.currentTarget||t.srcElement,o=n.getBoundingClientRect();return s.touches?(i=s.touches[0].clientX-o.left,e=s.touches[0].clientY-o.top):(i=s.clientX-o.left,e=s.clientY-o.top),{x:i,y:e}},s.addEvent=function(t,i,e){t.addEventListener?t.addEventListener(i,e):t.attachEvent?t.attachEvent("on"+i,e):t["on"+i]=e}),L=s.removeEvent=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e,!1):t.detachEvent?t.detachEvent("on"+i,e):t["on"+i]=c},k=(s.bindEvents=function(t,i,e){t.events||(t.events={}),n(i,function(i){t.events[i]=function(){e.apply(t,arguments)},P(t.chart.canvas,i,t.events[i])})},s.unbindEvents=function(t,i){n(i,function(i,e){L(t.chart.canvas,e,i)})}),F=s.getMaximumWidth=function(t){var i=t.parentNode;return i.clientWidth},R=s.getMaximumHeight=function(t){var i=t.parentNode;return i.clientHeight},A=(s.getMaximumSize=s.getMaximumWidth,s.retinaScale=function(t){var i=t.ctx,e=t.canvas.width,s=t.canvas.height;window.devicePixelRatio&&(i.canvas.style.width=e+"px",i.canvas.style.height=s+"px",i.canvas.height=s*window.devicePixelRatio,i.canvas.width=e*window.devicePixelRatio,i.scale(window.devicePixelRatio,window.devicePixelRatio))}),T=s.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},M=s.fontString=function(t,i,e){return i+" "+t+"px "+e},W=s.longestText=function(t,i,e){t.font=i;var s=0;return n(e,function(i){var e=t.measureText(i).width;s=e>s?e:s}),s},z=s.drawRoundedRectangle=function(t,i,e,s,n,o){t.beginPath(),t.moveTo(i+o,e),t.lineTo(i+s-o,e),t.quadraticCurveTo(i+s,e,i+s,e+o),t.lineTo(i+s,e+n-o),t.quadraticCurveTo(i+s,e+n,i+s-o,e+n),t.lineTo(i+o,e+n),t.quadraticCurveTo(i,e+n,i,e+n-o),t.lineTo(i,e+o),t.quadraticCurveTo(i,e,i+o,e),t.closePath()};e.instances={},e.Type=function(t,i,s){this.options=i,this.chart=s,this.id=u(),e.instances[this.id]=this,i.responsive&&this.resize(),this.initialize.call(this,t)},a(e.Type.prototype,{initialize:function(){return this},clear:function(){return T(this.chart),this},stop:function(){return s.cancelAnimFrame.call(t,this.animationFrame),this},resize:function(t){this.stop();var i=this.chart.canvas,e=F(this.chart.canvas),s=this.options.maintainAspectRatio?e/this.chart.aspectRatio:R(this.chart.canvas);return i.width=this.chart.width=e,i.height=this.chart.height=s,A(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?s.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return C(this.options.legendTemplate,this)},destroy:function(){this.clear(),k(this,this.events),delete e.instances[this.id]},showTooltip:function(t,i){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var i=!1;return t.length!==this.activeElements.length?i=!0:(n(t,function(t,e){t!==this.activeElements[e]&&(i=!0)},this),i)}.call(this,t);if(o||i){if(this.activeElements=t,this.draw(),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,h,r=this.datasets.length-1;r>=0&&(a=this.datasets[r].points||this.datasets[r].bars||this.datasets[r].segments,h=l(a,t[0]),-1===h);r--);var c=[],u=[],d=function(){var t,i,e,n,o,a=[],l=[],r=[];return s.each(this.datasets,function(i){t=i.points||i.bars||i.segments,t[h]&&t[h].hasValue()&&a.push(t[h])}),s.each(a,function(t){l.push(t.x),r.push(t.y),c.push(s.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),o=m(r),e=g(r),n=m(l),i=g(l),{x:n>this.chart.width/2?n:i,y:(o+e)/2}}.call(this,h);new e.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx}).draw()}else n(t,function(t){var i=t.tooltipPosition();new e.Tooltip({x:Math.round(i.x),y:Math.round(i.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:C(this.options.tooltipTemplate,t),chart:this.chart}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),e.Type.extend=function(t){var i=this,s=function(){return i.apply(this,arguments)};if(s.prototype=o(i.prototype),a(s.prototype,t),s.extend=e.Type.extend,t.name||i.prototype.name){var n=t.name||i.prototype.name,l=e.defaults[i.prototype.name]?o(e.defaults[i.prototype.name]):{};e.defaults[n]=a(l,t.defaults),e.types[n]=s,e.prototype[n]=function(t,i){var o=h(e.defaults.global,e.defaults[n],i||{});return new s(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return i},e.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(e.Element.prototype,{initialize:function(){},restore:function(t){return t?n(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return n(t,function(t,i){this._saved[i]=this[i],this[i]=t},this),this},transition:function(t,i){return n(t,function(t,e){this[e]=(t-this._saved[e])*i+this._saved[e]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}},hasValue:function(){return f(this.value)}}),e.Element.extend=r,e.Point=e.Element.extend({display:!0,inRange:function(t,i){var e=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(i-this.y,2)<Math.pow(e,2)},draw:function(){if(this.display){var t=this.ctx;t.beginPath(),t.arc(this.x,this.y,this.radius,0,2*Math.PI),t.closePath(),t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.fillStyle=this.fillColor,t.fill(),t.stroke()}}}),e.Arc=e.Element.extend({inRange:function(t,i){var e=s.getAngleFromPoint(this,{x:t,y:i}),n=e.angle>=this.startAngle&&e.angle<=this.endAngle,o=e.distance>=this.innerRadius&&e.distance<=this.outerRadius;return n&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,i=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*i,y:this.y+Math.sin(t)*i}},draw:function(t){var i=this.ctx;i.beginPath(),i.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),i.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),i.closePath(),i.strokeStyle=this.strokeColor,i.lineWidth=this.strokeWidth,i.fillStyle=this.fillColor,i.fill(),i.lineJoin="bevel",this.showStroke&&i.stroke()}}),e.Rectangle=e.Element.extend({draw:function(){var t=this.ctx,i=this.width/2,e=this.x-i,s=this.x+i,n=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(e+=o,s-=o,n+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(e,this.base),t.lineTo(e,n),t.lineTo(s,n),t.lineTo(s,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,i){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&i>=this.y&&i<=this.base}}),e.Tooltip=e.Element.extend({draw:function(){var t=this.chart.ctx;t.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var i=2,e=t.measureText(this.text).width+2*this.xPadding,s=this.fontSize+2*this.yPadding,n=s+this.caretHeight+i;this.x+e/2>this.chart.width?this.xAlign="left":this.x-e/2<0&&(this.xAlign="right"),this.y-n<0&&(this.yAlign="below");var o=this.x-e/2,a=this.y-n;switch(t.fillStyle=this.fillColor,this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-i),t.lineTo(this.x+this.caretHeight,this.y-(i+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(i+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+i+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+i),t.lineTo(this.x+this.caretHeight,this.y+i+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+i+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-e+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}z(t,o,a,e,s,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+e/2,a+s/2)}}),e.MultiTooltip=e.Element.extend({initialize:function(){this.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=M(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,i=W(this.ctx,this.font,this.labels)+this.fontSize+3,e=g([i,t]);this.width=e+2*this.xPadding;var s=this.height/2;this.y-s<0?this.y=s:this.y+s>this.chart.height&&(this.y=this.chart.height-s),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var i=this.y-this.height/2+this.yPadding,e=t-1;return 0===t?i+this.titleFontSize/2:i+(1.5*this.fontSize*e+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){z(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,s.each(this.labels,function(i,e){t.fillStyle=this.textColor,t.fillText(i,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(e+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[e].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}),e.Scale=e.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?W(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,i=this.endPoint-this.startPoint;for(this.calculateYRange(i),this.buildYLabels(),this.calculateXLabelRotation();i>this.endPoint-this.startPoint;)i=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(i),this.buildYLabels(),t<this.yLabelWidth&&this.calculateXLabelRotation()},calculateXLabelRotation:function(){this.ctx.font=this.font;var t,i,e=this.ctx.measureText(this.xLabels[0]).width,s=this.ctx.measureText(this.xLabels[this.xLabels.length-1]).width;if(this.xScalePaddingRight=s/2+3,this.xScalePaddingLeft=e/2>this.yLabelWidth+10?e/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var n,o=W(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)n=Math.cos(x(this.xLabelRotation)),t=n*e,i=n*s,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=n*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(x(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var i=this.drawingArea()/(this.min-this.max);return this.endPoint-i*(t-this.min)},calculateX:function(t){var i=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),e=i/(this.valuesCount-(this.offsetGridLines?0:1)),s=e*t+this.xScalePaddingLeft;return this.offsetGridLines&&(s+=e/2),Math.round(s)},update:function(t){s.extend(this,t),this.fit()},draw:function(){var t=this.ctx,i=(this.endPoint-this.startPoint)/this.steps,e=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,n(this.yLabels,function(n,o){var a=this.endPoint-i*o,h=Math.round(a);t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(n,e-10,a),t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),h+=s.aliasPixel(t.lineWidth),t.moveTo(e,h),t.lineTo(this.width,h),t.stroke(),t.closePath(),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(e-5,h),t.lineTo(e,h),t.stroke(),t.closePath()},this),n(this.xLabels,function(i,e){var s=this.calculateX(e)+S(this.lineWidth),n=this.calculateX(e-(this.offsetGridLines?.5:0))+S(this.lineWidth),o=this.xLabelRotation>0;t.beginPath(),e>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),t.moveTo(n,this.endPoint),t.lineTo(n,this.startPoint-3),t.stroke(),t.closePath(),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(n,this.endPoint),t.lineTo(n,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(s,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*x(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(i,0,0),t.restore()},this))}}),e.RadialScale=e.Element.extend({initialize:function(){this.size=m([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var i=this.drawingArea/(this.max-this.min);return(t-this.min)*i},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,i,e,s,n,o,a,h,l,r,c,u,d=m([this.height/2-this.pointLabelFontSize-5,this.width/2]),p=this.width,g=0;for(this.ctx.font=M(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),i=0;i<this.valuesCount;i++)t=this.getPointPosition(i,d),e=this.ctx.measureText(C(this.templateString,{value:this.labels[i]})).width+5,0===i||i===this.valuesCount/2?(s=e/2,t.x+s>p&&(p=t.x+s,n=i),t.x-s<g&&(g=t.x-s,a=i)):i<this.valuesCount/2?t.x+e>p&&(p=t.x+e,n=i):i>this.valuesCount/2&&t.x-e<g&&(g=t.x-e,a=i);l=g,r=Math.ceil(p-this.width),o=this.getIndexAngle(n),h=this.getIndexAngle(a),c=r/Math.sin(o+Math.PI/2),u=l/Math.sin(h+Math.PI/2),c=f(c)?c:0,u=f(u)?u:0,this.drawingArea=d-(u+c)/2,this.setCenterPoint(u,c)},setCenterPoint:function(t,i){var e=this.width-i-this.drawingArea,s=t+this.drawingArea;this.xCenter=(s+e)/2,this.yCenter=this.height/2},getIndexAngle:function(t){var i=2*Math.PI/this.valuesCount;return t*i-Math.PI/2},getPointPosition:function(t,i){var e=this.getIndexAngle(t);return{x:Math.cos(e)*i+this.xCenter,y:Math.sin(e)*i+this.yCenter}},draw:function(){if(this.display){var t=this.ctx;if(n(this.yLabels,function(i,e){if(e>0){var s,n=e*(this.drawingArea/this.steps),o=this.yCenter-n;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a<this.valuesCount;a++)s=this.getPointPosition(a,this.calculateCenterOffset(this.min+e*this.stepValue)),0===a?t.moveTo(s.x,s.y):t.lineTo(s.x,s.y);t.closePath(),t.stroke()}if(this.showLabels){if(t.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.showLabelBackdrop){var h=t.measureText(i).width;t.fillStyle=this.backdropColor,t.fillRect(this.xCenter-h/2-this.backdropPaddingX,o-this.fontSize/2-this.backdropPaddingY,h+2*this.backdropPaddingX,this.fontSize+2*this.backdropPaddingY)}t.textAlign="center",t.textBaseline="middle",t.fillStyle=this.fontColor,t.fillText(i,this.xCenter,o)}}},this),!this.lineArc){t.lineWidth=this.angleLineWidth,t.strokeStyle=this.angleLineColor;for(var i=this.valuesCount-1;i>=0;i--){if(this.angleLineWidth>0){var e=this.getPointPosition(i,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(e.x,e.y),t.stroke(),t.closePath()}var s=this.getPointPosition(i,this.calculateCenterOffset(this.max)+5);t.font=M(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,h=a/2,l=h>i||i>o-h,r=i===h||i===o-h;t.textAlign=0===i?"center":i===a?"center":a>i?"left":"right",t.textBaseline=r?"middle":l?"bottom":"top",t.fillText(this.labels[i],s.x,s.y)}}}}}),s.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){n(e.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),p?define(function(){return e}):"object"==typeof module&&module.exports&&(module.exports=e),t.Chart=e,e.noConflict=function(){return t.Chart=i,e}}).call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].fillColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Bar",defaults:s,initialize:function(t){var s=this.options;this.ScaleClass=i.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,i,e){var n=this.calculateBaseWidth(),o=this.calculateX(e)-n/2,a=this.calculateBarWidth(t);return o+a*i+i*s.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*s.barValueSpacing},calculateBarWidth:function(t){var i=this.calculateBaseWidth()-(t-1)*s.barDatasetSpacing;return i/t}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),this.BarClass=i.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,bars:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.bars.push(new this.BarClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.strokeColor,fillColor:i.fillColor,highlightFill:i.highlightFill||i.fillColor,highlightStroke:i.highlightStroke||i.strokeColor}))},this)},this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,i,s){e.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,s,i),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){e.each(this.datasets,function(i,s){e.each(i.bars,t,this,s)},this)},getBarsAtEvent:function(t){for(var i,s=[],n=e.getRelativePosition(t),o=function(t){s.push(t.bars[i])},a=0;a<this.datasets.length;a++)for(i=0;i<this.datasets[a].bars.length;i++)if(this.datasets[a].bars[i].inRange(n.x,n.y))return e.each(this.datasets,o),s;return s},buildScale:function(t){var i=this,s=function(){var t=[];return i.eachBars(function(i){t.push(i.value)}),t},n={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(s(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.barShowStroke?this.options.barStrokeWidth:0,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(n,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new this.ScaleClass(n)},addData:function(t,i){e.each(t,function(t,e){this.datasets[e].bars.push(new this.BarClass({value:t,label:i,x:this.scale.calculateBarX(this.datasets.length,e,this.scale.valuesCount+1),y:this.scale.endPoint,width:this.scale.calculateBarWidth(this.datasets.length),base:this.scale.endPoint,strokeColor:this.datasets[e].strokeColor,fillColor:this.datasets[e].fillColor}))},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.bars.shift()},this),this.update()},reflow:function(){e.extend(this.BarClass.prototype,{y:this.scale.endPoint,base:this.scale.endPoint});var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();this.chart.ctx;this.scale.draw(i),e.each(this.datasets,function(t,s){e.each(t.bars,function(t,e){t.hasValue()&&(t.base=this.scale.endPoint,t.transition({x:this.scale.calculateBarX(this.datasets.length,s,e),y:this.scale.calculateY(t.value),width:this.scale.calculateBarWidth(this.datasets.length)},i).draw())},this)},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,percentageInnerCutout:50,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};
11
- i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(t/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle)},this)}}),i.types.Doughnut.extend({name:"Pie",defaults:e.merge(s,{percentageInnerCutout:0})})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,bezierCurve:!0,bezierCurveTension:.4,pointDot:!0,pointDotRadius:4,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)<Math.pow(this.radius+this.hitDetectionRadius,2)}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this),this.buildScale(t.labels),this.eachPoints(function(t,i){e.extend(t,{x:this.scale.calculateX(i),y:this.scale.endPoint}),t.save()},this)},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachPoints(function(t){t.save()}),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.datasets,function(t){e.each(t.points,function(t){t.inRange(s.x,s.y)&&i.push(t)})},this),i},buildScale:function(t){var s=this,n=function(){var t=[];return s.eachPoints(function(i){t.push(i.value)}),t},o={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(n(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.pointDotRadius+this.options.pointDotStrokeWidth,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(o,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new i.Scale(o)},addData:function(t,i){e.each(t,function(t,e){this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:this.scale.calculateX(this.scale.valuesCount+1),y:this.scale.endPoint,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.points.shift()},this),this.update()},reflow:function(){var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();var s=this.chart.ctx,n=function(t){return null!==t.value},o=function(t,i,s){return e.findNextWhere(i,n,s)||t},a=function(t,i,s){return e.findPreviousWhere(i,n,s)||t};this.scale.draw(i),e.each(this.datasets,function(t){var h=e.where(t.points,n);e.each(t.points,function(t,e){t.hasValue()&&t.transition({y:this.scale.calculateY(t.value),x:this.scale.calculateX(e)},i)},this),this.options.bezierCurve&&e.each(h,function(t,i){var s=i>0&&i<h.length-1?this.options.bezierCurveTension:0;t.controlPoints=e.splineCurve(a(t,h,i),t,o(t,h,i),s),t.controlPoints.outer.y>this.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.y<this.scale.startPoint&&(t.controlPoints.outer.y=this.scale.startPoint),t.controlPoints.inner.y>this.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y<this.scale.startPoint&&(t.controlPoints.inner.y=this.scale.startPoint)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(h,function(t,i){if(0===i)s.moveTo(t.x,t.y);else if(this.options.bezierCurve){var e=a(t,h,i);s.bezierCurveTo(e.controlPoints.outer.x,e.controlPoints.outer.y,t.controlPoints.inner.x,t.controlPoints.inner.y,t.x,t.y)}else s.lineTo(t.x,t.y)},this),s.stroke(),this.options.datasetFill&&h.length>0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle),t.draw()},this),this.scale.draw()}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers;i.Type.extend({name:"Radar",defaults:{scaleShowLine:!0,angleShowLineOut:!0,scaleShowLabels:!1,scaleBeginAtZero:!0,angleLineColor:"rgba(0,0,0,.1)",angleLineWidth:1,pointLabelFontFamily:"'Arial'",pointLabelFontStyle:"normal",pointLabelFontSize:10,pointLabelFontColor:"#666",pointDot:!0,pointDotRadius:3,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this);
1
  /*!
2
+ * Chart.js v2.9.3
3
+ * https://www.chartjs.org
4
+ * (c) 2019 Chart.js Contributors
5
+ * Released under the MIT License
 
 
 
6
  */
7
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(function(){try{return require("moment")}catch(t){}}()):"function"==typeof define&&define.amd?define(["require"],(function(t){return e(function(){try{return t("moment")}catch(t){}}())})):(t=t||self).Chart=e(t.moment)}(this,(function(t){"use strict";t=t&&t.hasOwnProperty("default")?t.default:t;var e={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]},n=function(t,e){return t(e={exports:{}},e.exports),e.exports}((function(t){var n={};for(var i in e)e.hasOwnProperty(i)&&(n[e[i]]=i);var a=t.exports={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};for(var r in a)if(a.hasOwnProperty(r)){if(!("channels"in a[r]))throw new Error("missing channels property: "+r);if(!("labels"in a[r]))throw new Error("missing channel labels property: "+r);if(a[r].labels.length!==a[r].channels)throw new Error("channel and label counts mismatch: "+r);var o=a[r].channels,s=a[r].labels;delete a[r].channels,delete a[r].labels,Object.defineProperty(a[r],"channels",{value:o}),Object.defineProperty(a[r],"labels",{value:s})}a.rgb.hsl=function(t){var e,n,i=t[0]/255,a=t[1]/255,r=t[2]/255,o=Math.min(i,a,r),s=Math.max(i,a,r),l=s-o;return s===o?e=0:i===s?e=(a-r)/l:a===s?e=2+(r-i)/l:r===s&&(e=4+(i-a)/l),(e=Math.min(60*e,360))<0&&(e+=360),n=(o+s)/2,[e,100*(s===o?0:n<=.5?l/(s+o):l/(2-s-o)),100*n]},a.rgb.hsv=function(t){var e,n,i,a,r,o=t[0]/255,s=t[1]/255,l=t[2]/255,u=Math.max(o,s,l),d=u-Math.min(o,s,l),h=function(t){return(u-t)/6/d+.5};return 0===d?a=r=0:(r=d/u,e=h(o),n=h(s),i=h(l),o===u?a=i-n:s===u?a=1/3+e-i:l===u&&(a=2/3+n-e),a<0?a+=1:a>1&&(a-=1)),[360*a,100*r,100*u]},a.rgb.hwb=function(t){var e=t[0],n=t[1],i=t[2];return[a.rgb.hsl(t)[0],100*(1/255*Math.min(e,Math.min(n,i))),100*(i=1-1/255*Math.max(e,Math.max(n,i)))]},a.rgb.cmyk=function(t){var e,n=t[0]/255,i=t[1]/255,a=t[2]/255;return[100*((1-n-(e=Math.min(1-n,1-i,1-a)))/(1-e)||0),100*((1-i-e)/(1-e)||0),100*((1-a-e)/(1-e)||0),100*e]},a.rgb.keyword=function(t){var i=n[t];if(i)return i;var a,r,o,s=1/0;for(var l in e)if(e.hasOwnProperty(l)){var u=e[l],d=(r=t,o=u,Math.pow(r[0]-o[0],2)+Math.pow(r[1]-o[1],2)+Math.pow(r[2]-o[2],2));d<s&&(s=d,a=l)}return a},a.keyword.rgb=function(t){return e[t]},a.rgb.xyz=function(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)]},a.rgb.lab=function(t){var e=a.rgb.xyz(t),n=e[0],i=e[1],r=e[2];return i/=100,r/=108.883,n=(n/=95.047)>.008856?Math.pow(n,1/3):7.787*n+16/116,[116*(i=i>.008856?Math.pow(i,1/3):7.787*i+16/116)-16,500*(n-i),200*(i-(r=r>.008856?Math.pow(r,1/3):7.787*r+16/116))]},a.hsl.rgb=function(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];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},a.hsl.hsv=function(t){var e=t[0],n=t[1]/100,i=t[2]/100,a=n,r=Math.max(i,.01);return n*=(i*=2)<=1?i:2-i,a*=r<=1?r:2-r,[e,100*(0===i?2*a/(r+a):2*n/(i+n)),100*((i+n)/2)]},a.hsv.rgb=function(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));switch(i*=255,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]}},a.hsv.hsl=function(t){var e,n,i,a=t[0],r=t[1]/100,o=t[2]/100,s=Math.max(o,.01);return i=(2-r)*o,n=r*s,[a,100*(n=(n/=(e=(2-r)*s)<=1?e:2-e)||0),100*(i/=2)]},a.hwb.rgb=function(t){var e,n,i,a,r,o,s,l=t[0]/360,u=t[1]/100,d=t[2]/100,h=u+d;switch(h>1&&(u/=h,d/=h),i=6*l-(e=Math.floor(6*l)),0!=(1&e)&&(i=1-i),a=u+i*((n=1-d)-u),e){default:case 6:case 0:r=n,o=a,s=u;break;case 1:r=a,o=n,s=u;break;case 2:r=u,o=n,s=a;break;case 3:r=u,o=a,s=n;break;case 4:r=a,o=u,s=n;break;case 5:r=n,o=u,s=a}return[255*r,255*o,255*s]},a.cmyk.rgb=function(t){var e=t[0]/100,n=t[1]/100,i=t[2]/100,a=t[3]/100;return[255*(1-Math.min(1,e*(1-a)+a)),255*(1-Math.min(1,n*(1-a)+a)),255*(1-Math.min(1,i*(1-a)+a))]},a.xyz.rgb=function(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100;return n=-.9689*a+1.8758*r+.0415*o,i=.0557*a+-.204*r+1.057*o,e=(e=3.2406*a+-1.5372*r+-.4986*o)>.0031308?1.055*Math.pow(e,1/2.4)-.055:12.92*e,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:12.92*n,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:12.92*i,[255*(e=Math.min(Math.max(0,e),1)),255*(n=Math.min(Math.max(0,n),1)),255*(i=Math.min(Math.max(0,i),1))]},a.xyz.lab=function(t){var e=t[0],n=t[1],i=t[2];return n/=100,i/=108.883,e=(e/=95.047)>.008856?Math.pow(e,1/3):7.787*e+16/116,[116*(n=n>.008856?Math.pow(n,1/3):7.787*n+16/116)-16,500*(e-n),200*(n-(i=i>.008856?Math.pow(i,1/3):7.787*i+16/116))]},a.lab.xyz=function(t){var e,n,i,a=t[0];e=t[1]/500+(n=(a+16)/116),i=n-t[2]/200;var r=Math.pow(n,3),o=Math.pow(e,3),s=Math.pow(i,3);return n=r>.008856?r:(n-16/116)/7.787,e=o>.008856?o:(e-16/116)/7.787,i=s>.008856?s:(i-16/116)/7.787,[e*=95.047,n*=100,i*=108.883]},a.lab.lch=function(t){var e,n=t[0],i=t[1],a=t[2];return(e=360*Math.atan2(a,i)/2/Math.PI)<0&&(e+=360),[n,Math.sqrt(i*i+a*a),e]},a.lch.lab=function(t){var e,n=t[0],i=t[1];return e=t[2]/360*2*Math.PI,[n,i*Math.cos(e),i*Math.sin(e)]},a.rgb.ansi16=function(t){var e=t[0],n=t[1],i=t[2],r=1 in arguments?arguments[1]:a.rgb.hsv(t)[2];if(0===(r=Math.round(r/50)))return 30;var o=30+(Math.round(i/255)<<2|Math.round(n/255)<<1|Math.round(e/255));return 2===r&&(o+=60),o},a.hsv.ansi16=function(t){return a.rgb.ansi16(a.hsv.rgb(t),t[2])},a.rgb.ansi256=function(t){var e=t[0],n=t[1],i=t[2];return e===n&&n===i?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(n/255*5)+Math.round(i/255*5)},a.ansi16.rgb=function(t){var e=t%10;if(0===e||7===e)return t>50&&(e+=3.5),[e=e/10.5*255,e,e];var n=.5*(1+~~(t>50));return[(1&e)*n*255,(e>>1&1)*n*255,(e>>2&1)*n*255]},a.ansi256.rgb=function(t){if(t>=232){var e=10*(t-232)+8;return[e,e,e]}var n;return t-=16,[Math.floor(t/36)/5*255,Math.floor((n=t%36)/6)/5*255,n%6/5*255]},a.rgb.hex=function(t){var e=(((255&Math.round(t[0]))<<16)+((255&Math.round(t[1]))<<8)+(255&Math.round(t[2]))).toString(16).toUpperCase();return"000000".substring(e.length)+e},a.hex.rgb=function(t){var e=t.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!e)return[0,0,0];var n=e[0];3===e[0].length&&(n=n.split("").map((function(t){return t+t})).join(""));var i=parseInt(n,16);return[i>>16&255,i>>8&255,255&i]},a.rgb.hcg=function(t){var e,n=t[0]/255,i=t[1]/255,a=t[2]/255,r=Math.max(Math.max(n,i),a),o=Math.min(Math.min(n,i),a),s=r-o;return e=s<=0?0:r===n?(i-a)/s%6:r===i?2+(a-n)/s:4+(n-i)/s+4,e/=6,[360*(e%=1),100*s,100*(s<1?o/(1-s):0)]},a.hsl.hcg=function(t){var e=t[1]/100,n=t[2]/100,i=1,a=0;return(i=n<.5?2*e*n:2*e*(1-n))<1&&(a=(n-.5*i)/(1-i)),[t[0],100*i,100*a]},a.hsv.hcg=function(t){var e=t[1]/100,n=t[2]/100,i=e*n,a=0;return i<1&&(a=(n-i)/(1-i)),[t[0],100*i,100*a]},a.hcg.rgb=function(t){var e=t[0]/360,n=t[1]/100,i=t[2]/100;if(0===n)return[255*i,255*i,255*i];var a,r=[0,0,0],o=e%1*6,s=o%1,l=1-s;switch(Math.floor(o)){case 0:r[0]=1,r[1]=s,r[2]=0;break;case 1:r[0]=l,r[1]=1,r[2]=0;break;case 2:r[0]=0,r[1]=1,r[2]=s;break;case 3:r[0]=0,r[1]=l,r[2]=1;break;case 4:r[0]=s,r[1]=0,r[2]=1;break;default:r[0]=1,r[1]=0,r[2]=l}return a=(1-n)*i,[255*(n*r[0]+a),255*(n*r[1]+a),255*(n*r[2]+a)]},a.hcg.hsv=function(t){var e=t[1]/100,n=e+t[2]/100*(1-e),i=0;return n>0&&(i=e/n),[t[0],100*i,100*n]},a.hcg.hsl=function(t){var e=t[1]/100,n=t[2]/100*(1-e)+.5*e,i=0;return n>0&&n<.5?i=e/(2*n):n>=.5&&n<1&&(i=e/(2*(1-n))),[t[0],100*i,100*n]},a.hcg.hwb=function(t){var e=t[1]/100,n=e+t[2]/100*(1-e);return[t[0],100*(n-e),100*(1-n)]},a.hwb.hcg=function(t){var e=t[1]/100,n=1-t[2]/100,i=n-e,a=0;return i<1&&(a=(n-i)/(1-i)),[t[0],100*i,100*a]},a.apple.rgb=function(t){return[t[0]/65535*255,t[1]/65535*255,t[2]/65535*255]},a.rgb.apple=function(t){return[t[0]/255*65535,t[1]/255*65535,t[2]/255*65535]},a.gray.rgb=function(t){return[t[0]/100*255,t[0]/100*255,t[0]/100*255]},a.gray.hsl=a.gray.hsv=function(t){return[0,0,t[0]]},a.gray.hwb=function(t){return[0,100,t[0]]},a.gray.cmyk=function(t){return[0,0,0,t[0]]},a.gray.lab=function(t){return[t[0],0,0]},a.gray.hex=function(t){var e=255&Math.round(t[0]/100*255),n=((e<<16)+(e<<8)+e).toString(16).toUpperCase();return"000000".substring(n.length)+n},a.rgb.gray=function(t){return[(t[0]+t[1]+t[2])/3/255*100]}}));n.rgb,n.hsl,n.hsv,n.hwb,n.cmyk,n.xyz,n.lab,n.lch,n.hex,n.keyword,n.ansi16,n.ansi256,n.hcg,n.apple,n.gray;function i(t){var e=function(){for(var t={},e=Object.keys(n),i=e.length,a=0;a<i;a++)t[e[a]]={distance:-1,parent:null};return t}(),i=[t];for(e[t].distance=0;i.length;)for(var a=i.pop(),r=Object.keys(n[a]),o=r.length,s=0;s<o;s++){var l=r[s],u=e[l];-1===u.distance&&(u.distance=e[a].distance+1,u.parent=a,i.unshift(l))}return e}function a(t,e){return function(n){return e(t(n))}}function r(t,e){for(var i=[e[t].parent,t],r=n[e[t].parent][t],o=e[t].parent;e[o].parent;)i.unshift(e[o].parent),r=a(n[e[o].parent][o],r),o=e[o].parent;return r.conversion=i,r}var o={};Object.keys(n).forEach((function(t){o[t]={},Object.defineProperty(o[t],"channels",{value:n[t].channels}),Object.defineProperty(o[t],"labels",{value:n[t].labels});var e=function(t){for(var e=i(t),n={},a=Object.keys(e),o=a.length,s=0;s<o;s++){var l=a[s];null!==e[l].parent&&(n[l]=r(l,e))}return n}(t);Object.keys(e).forEach((function(n){var i=e[n];o[t][n]=function(t){var e=function(e){if(null==e)return e;arguments.length>1&&(e=Array.prototype.slice.call(arguments));var n=t(e);if("object"==typeof n)for(var i=n.length,a=0;a<i;a++)n[a]=Math.round(n[a]);return n};return"conversion"in t&&(e.conversion=t.conversion),e}(i),o[t][n].raw=function(t){var e=function(e){return null==e?e:(arguments.length>1&&(e=Array.prototype.slice.call(arguments)),t(e))};return"conversion"in t&&(e.conversion=t.conversion),e}(i)}))}));var s=o,l={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]},u={getRgba:d,getHsla:h,getRgb:function(t){var e=d(t);return e&&e.slice(0,3)},getHsl:function(t){var e=h(t);return e&&e.slice(0,3)},getHwb:c,getAlpha:function(t){var e=d(t);if(e)return e[3];if(e=h(t))return e[3];if(e=c(t))return e[3]},hexString:function(t,e){e=void 0!==e&&3===t.length?e:t[3];return"#"+v(t[0])+v(t[1])+v(t[2])+(e>=0&&e<1?v(Math.round(255*e)):"")},rgbString:function(t,e){if(e<1||t[3]&&t[3]<1)return f(t,e);return"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:f,percentString:function(t,e){if(e<1||t[3]&&t[3]<1)return g(t,e);var n=Math.round(t[0]/255*100),i=Math.round(t[1]/255*100),a=Math.round(t[2]/255*100);return"rgb("+n+"%, "+i+"%, "+a+"%)"},percentaString:g,hslString:function(t,e){if(e<1||t[3]&&t[3]<1)return p(t,e);return"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:p,hwbString:function(t,e){void 0===e&&(e=void 0!==t[3]?t[3]:1);return"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return b[t.slice(0,3)]}};function d(t){if(t){var e=[0,0,0],n=1,i=t.match(/^#([a-fA-F0-9]{3,4})$/i),a="";if(i){a=(i=i[1])[3];for(var r=0;r<e.length;r++)e[r]=parseInt(i[r]+i[r],16);a&&(n=Math.round(parseInt(a+a,16)/255*100)/100)}else if(i=t.match(/^#([a-fA-F0-9]{6}([a-fA-F0-9]{2})?)$/i)){a=i[2],i=i[1];for(r=0;r<e.length;r++)e[r]=parseInt(i.slice(2*r,2*r+2),16);a&&(n=Math.round(parseInt(a,16)/255*100)/100)}else if(i=t.match(/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(r=0;r<e.length;r++)e[r]=parseInt(i[r+1]);n=parseFloat(i[4])}else if(i=t.match(/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(r=0;r<e.length;r++)e[r]=Math.round(2.55*parseFloat(i[r+1]));n=parseFloat(i[4])}else if(i=t.match(/(\w+)/)){if("transparent"==i[1])return[0,0,0,0];if(!(e=l[i[1]]))return}for(r=0;r<e.length;r++)e[r]=m(e[r],0,255);return n=n||0==n?m(n,0,1):1,e[3]=n,e}}function h(t){if(t){var e=t.match(/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[m(parseInt(e[1]),0,360),m(parseFloat(e[2]),0,100),m(parseFloat(e[3]),0,100),m(isNaN(n)?1:n,0,1)]}}}function c(t){if(t){var e=t.match(/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[m(parseInt(e[1]),0,360),m(parseFloat(e[2]),0,100),m(parseFloat(e[3]),0,100),m(isNaN(n)?1:n,0,1)]}}}function f(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function g(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 p(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function m(t,e,n){return Math.min(Math.max(e,t),n)}function v(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var b={};for(var x in l)b[l[x]]=x;var y=function(t){return t instanceof y?t:this instanceof y?(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},void("string"==typeof t?(e=u.getRgba(t))?this.setValues("rgb",e):(e=u.getHsla(t))?this.setValues("hsl",e):(e=u.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)))):new y(t);var e};y.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 u.hexString(this.values.rgb)},rgbString:function(){return u.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return u.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return u.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return u.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return u.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return u.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return u.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=t,i=void 0===e?.5:e,a=2*i-1,r=this.alpha()-n.alpha(),o=((a*r==-1?a:(a+r)/(1+a*r))+1)/2,s=1-o;return this.rgb(o*this.red()+s*n.red(),o*this.green()+s*n.green(),o*this.blue()+s*n.blue()).alpha(this.alpha()*i+n.alpha()*(1-i))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new y,i=this.values,a=n.values;for(var r in i)i.hasOwnProperty(r)&&(t=i[r],"[object Array]"===(e={}.toString.call(t))?a[r]=t.slice(0):"[object Number]"===e?a[r]=t:console.error("unexpected color value:",t));return n}},y.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},y.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},y.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},y.prototype.setValues=function(t,e){var n,i,a=this.values,r=this.spaces,o=this.maxes,l=1;if(this.valid=!0,"alpha"===t)l=e;else if(e.length)a[t]=e.slice(0,t.length),l=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)];l=e.a}else if(void 0!==e[r[t][0]]){var u=r[t];for(n=0;n<t.length;n++)a[t][n]=e[u[n]];l=e.alpha}if(a.alpha=Math.max(0,Math.min(1,void 0===l?a.alpha:l)),"alpha"===t)return!1;for(n=0;n<t.length;n++)i=Math.max(0,Math.min(o[t][n],a[t][n])),a[t][n]=Math.round(i);for(var d in r)d!==t&&(a[d]=s[t][d](a[t]));return!0},y.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)},y.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=y);var _,k=y,w={noop:function(){},uid:(_=0,function(){return _++}),isNullOrUndef:function(t){return null==t},isArray:function(t){if(Array.isArray&&Array.isArray(t))return!0;var e=Object.prototype.toString.call(t);return"[object"===e.substr(0,7)&&"Array]"===e.substr(-6)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},isFinite:function(t){return("number"==typeof t||t instanceof Number)&&isFinite(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return w.valueOrDefault(w.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,i){var a,r,o;if(w.isArray(t))if(r=t.length,i)for(a=r-1;a>=0;a--)e.call(n,t[a],a);else for(a=0;a<r;a++)e.call(n,t[a],a);else if(w.isObject(t))for(r=(o=Object.keys(t)).length,a=0;a<r;a++)e.call(n,t[o[a]],o[a])},arrayEquals:function(t,e){var n,i,a,r;if(!t||!e||t.length!==e.length)return!1;for(n=0,i=t.length;n<i;++n)if(a=t[n],r=e[n],a instanceof Array&&r instanceof Array){if(!w.arrayEquals(a,r))return!1}else if(a!==r)return!1;return!0},clone:function(t){if(w.isArray(t))return t.map(w.clone);if(w.isObject(t)){for(var e={},n=Object.keys(t),i=n.length,a=0;a<i;++a)e[n[a]]=w.clone(t[n[a]]);return e}return t},_merger:function(t,e,n,i){var a=e[t],r=n[t];w.isObject(a)&&w.isObject(r)?w.merge(a,r,i):e[t]=w.clone(r)},_mergerIf:function(t,e,n){var i=e[t],a=n[t];w.isObject(i)&&w.isObject(a)?w.mergeIf(i,a):e.hasOwnProperty(t)||(e[t]=w.clone(a))},merge:function(t,e,n){var i,a,r,o,s,l=w.isArray(e)?e:[e],u=l.length;if(!w.isObject(t))return t;for(i=(n=n||{}).merger||w._merger,a=0;a<u;++a)if(e=l[a],w.isObject(e))for(s=0,o=(r=Object.keys(e)).length;s<o;++s)i(r[s],t,e,n);return t},mergeIf:function(t,e){return w.merge(t,e,{merger:w._mergerIf})},extend:Object.assign||function(t){return w.merge(t,[].slice.call(arguments,1),{merger:function(t,e,n){e[t]=n[t]}})},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=w.inherits,t&&w.extend(n.prototype,t),n.__super__=e.prototype,n},_deprecated:function(t,e,n,i){void 0!==e&&console.warn(t+': "'+n+'" is deprecated. Please use "'+i+'" instead')}},M=w;w.callCallback=w.callback,w.indexOf=function(t,e,n){return Array.prototype.indexOf.call(t,e,n)},w.getValueOrDefault=w.valueOrDefault,w.getValueAtIndexOrDefault=w.valueAtIndexOrDefault;var S={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-S.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*S.easeInBounce(2*t):.5*S.easeOutBounce(2*t-1)+.5}},C={effects:S};M.easingEffects=S;var P=Math.PI,A=P/180,D=2*P,T=P/2,I=P/4,F=2*P/3,L={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,a/2,i/2),s=e+o,l=n+o,u=e+i-o,d=n+a-o;t.moveTo(e,l),s<u&&l<d?(t.arc(s,l,o,-P,-T),t.arc(u,l,o,-T,0),t.arc(u,d,o,0,T),t.arc(s,d,o,T,P)):s<u?(t.moveTo(s,n),t.arc(u,l,o,-T,T),t.arc(s,l,o,T,P+T)):l<d?(t.arc(s,l,o,-P,0),t.arc(s,d,o,0,P)):t.arc(s,l,o,-P,P),t.closePath(),t.moveTo(e,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a,r){var o,s,l,u,d,h=(r||0)*A;if(e&&"object"==typeof e&&("[object HTMLImageElement]"===(o=e.toString())||"[object HTMLCanvasElement]"===o))return t.save(),t.translate(i,a),t.rotate(h),t.drawImage(e,-e.width/2,-e.height/2,e.width,e.height),void t.restore();if(!(isNaN(n)||n<=0)){switch(t.beginPath(),e){default:t.arc(i,a,n,0,D),t.closePath();break;case"triangle":t.moveTo(i+Math.sin(h)*n,a-Math.cos(h)*n),h+=F,t.lineTo(i+Math.sin(h)*n,a-Math.cos(h)*n),h+=F,t.lineTo(i+Math.sin(h)*n,a-Math.cos(h)*n),t.closePath();break;case"rectRounded":u=n-(d=.516*n),s=Math.cos(h+I)*u,l=Math.sin(h+I)*u,t.arc(i-s,a-l,d,h-P,h-T),t.arc(i+l,a-s,d,h-T,h),t.arc(i+s,a+l,d,h,h+T),t.arc(i-l,a+s,d,h+T,h+P),t.closePath();break;case"rect":if(!r){u=Math.SQRT1_2*n,t.rect(i-u,a-u,2*u,2*u);break}h+=I;case"rectRot":s=Math.cos(h)*n,l=Math.sin(h)*n,t.moveTo(i-s,a-l),t.lineTo(i+l,a-s),t.lineTo(i+s,a+l),t.lineTo(i-l,a+s),t.closePath();break;case"crossRot":h+=I;case"cross":s=Math.cos(h)*n,l=Math.sin(h)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i+l,a-s),t.lineTo(i-l,a+s);break;case"star":s=Math.cos(h)*n,l=Math.sin(h)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i+l,a-s),t.lineTo(i-l,a+s),h+=I,s=Math.cos(h)*n,l=Math.sin(h)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i+l,a-s),t.lineTo(i-l,a+s);break;case"line":s=Math.cos(h)*n,l=Math.sin(h)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l);break;case"dash":t.moveTo(i,a),t.lineTo(i+Math.cos(h)*n,a+Math.sin(h)*n)}t.fill(),t.stroke()}},_isPointInArea:function(t,e){return t.x>e.left-1e-6&&t.x<e.right+1e-6&&t.y>e.top-1e-6&&t.y<e.bottom+1e-6},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){var a=n.steppedLine;if(a){if("middle"===a){var r=(e.x+n.x)/2;t.lineTo(r,i?n.y:e.y),t.lineTo(r,i?e.y:n.y)}else"after"===a&&!i||"after"!==a&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y);t.lineTo(n.x,n.y)}else 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)}},O=L;M.clear=L.clear,M.drawRoundedRectangle=function(t){t.beginPath(),L.roundedRect.apply(L,arguments)};var R={_set:function(t,e){return M.merge(this[t]||(this[t]={}),e)}};R._set("global",{defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",defaultLineHeight:1.2,showLines:!0});var z=R,N=M.valueOrDefault;var B={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,i,a;return M.isObject(t)?(e=+t.top||0,n=+t.right||0,i=+t.bottom||0,a=+t.left||0):e=n=i=a=+t||0,{top:e,right:n,bottom:i,left:a,height:e+i,width:a+n}},_parseFont:function(t){var e=z.global,n=N(t.fontSize,e.defaultFontSize),i={family:N(t.fontFamily,e.defaultFontFamily),lineHeight:M.options.toLineHeight(N(t.lineHeight,e.defaultLineHeight),n),size:n,style:N(t.fontStyle,e.defaultFontStyle),weight:null,string:""};return i.string=function(t){return!t||M.isNullOrUndef(t.size)||M.isNullOrUndef(t.family)?null:(t.style?t.style+" ":"")+(t.weight?t.weight+" ":"")+t.size+"px "+t.family}(i),i},resolve:function(t,e,n,i){var a,r,o,s=!0;for(a=0,r=t.length;a<r;++a)if(void 0!==(o=t[a])&&(void 0!==e&&"function"==typeof o&&(o=o(e),s=!1),void 0!==n&&M.isArray(o)&&(o=o[n],s=!1),void 0!==o))return i&&!s&&(i.cacheable=!1),o}},E={_factorize:function(t){var e,n=[],i=Math.sqrt(t);for(e=1;e<i;e++)t%e==0&&(n.push(e),n.push(t/e));return i===(0|i)&&n.push(i),n.sort((function(t,e){return t-e})).pop(),n},log10:Math.log10||function(t){var e=Math.log(t)*Math.LOG10E,n=Math.round(e);return t===Math.pow(10,n)?n:e}},W=E;M.log10=E.log10;var V=M,H=C,j=O,q=B,U=W,Y={getRtlAdapter:function(t,e,n){return t?function(t,e){return{x:function(n){return t+t+e-n},setWidth:function(t){e=t},textAlign:function(t){return"center"===t?t:"right"===t?"left":"right"},xPlus:function(t,e){return t-e},leftForLtr:function(t,e){return t-e}}}(e,n):{x:function(t){return t},setWidth:function(t){},textAlign:function(t){return t},xPlus:function(t,e){return t+e},leftForLtr:function(t,e){return t}}},overrideTextDirection:function(t,e){var n,i;"ltr"!==e&&"rtl"!==e||(i=[(n=t.canvas.style).getPropertyValue("direction"),n.getPropertyPriority("direction")],n.setProperty("direction",e,"important"),t.prevTextDirection=i)},restoreTextDirection:function(t){var e=t.prevTextDirection;void 0!==e&&(delete t.prevTextDirection,t.canvas.style.setProperty("direction",e[0],e[1]))}};V.easing=H,V.canvas=j,V.options=q,V.math=U,V.rtl=Y;var G=function(t){V.extend(this,t),this.initialize.apply(this,arguments)};V.extend(G.prototype,{_type:void 0,initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=V.extend({},t._model)),t._start={},t},transition:function(t){var e=this,n=e._model,i=e._start,a=e._view;return n&&1!==t?(a||(a=e._view={}),i||(i=e._start={}),function(t,e,n,i){var a,r,o,s,l,u,d,h,c,f=Object.keys(n);for(a=0,r=f.length;a<r;++a)if(u=n[o=f[a]],e.hasOwnProperty(o)||(e[o]=u),(s=e[o])!==u&&"_"!==o[0]){if(t.hasOwnProperty(o)||(t[o]=s),(d=typeof u)===typeof(l=t[o]))if("string"===d){if((h=k(l)).valid&&(c=k(u)).valid){e[o]=c.mix(h,i).rgbString();continue}}else if(V.isFinite(l)&&V.isFinite(u)){e[o]=l+(u-l)*i;continue}e[o]=u}}(i,a,n,t),e):(e._view=V.extend({},n),e._start=null,e)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return V.isNumber(this._model.x)&&V.isNumber(this._model.y)}}),G.extend=V.inherits;var X=G,K=X.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),Z=K;Object.defineProperty(K.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(K.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}}),z._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:V.noop,onComplete:V.noop}});var $={animations:[],request:null,addAnimation:function(t,e,n,i){var a,r,o=this.animations;for(e.chart=t,e.startTime=Date.now(),e.duration=n,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=V.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=V.requestAnimFrame.call(window,(function(){t.request=null,t.startDigest()})))},startDigest:function(){this.advance(),this.animations.length>0&&this.requestAnimationFrame()},advance:function(){for(var t,e,n,i,a=this.animations,r=0;r<a.length;)e=(t=a[r]).chart,n=t.numSteps,i=Math.floor((Date.now()-t.startTime)/t.duration*n)+1,t.currentStep=Math.min(i,n),V.callback(t.render,[e,t],e),V.callback(t.onAnimationProgress,[t],e),t.currentStep>=n?(V.callback(t.onAnimationComplete,[t],e),e.animating=!1,a.splice(r,1)):++r}},J=V.options.resolve,Q=["push","pop","shift","splice","unshift"];function tt(t,e){var n=t._chartjs;if(n){var i=n.listeners,a=i.indexOf(e);-1!==a&&i.splice(a,1),i.length>0||(Q.forEach((function(e){delete t[e]})),delete t._chartjs)}}var et=function(t,e){this.initialize(t,e)};V.extend(et.prototype,{datasetElementType:null,dataElementType:null,_datasetElementOptions:["backgroundColor","borderCapStyle","borderColor","borderDash","borderDashOffset","borderJoinStyle","borderWidth"],_dataElementOptions:["backgroundColor","borderColor","borderWidth","pointStyle"],initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements(),n._type=n.getMeta().type},updateIndex:function(t){this.index=t},linkScales:function(){var t=this.getMeta(),e=this.chart,n=e.scales,i=this.getDataset(),a=e.options.scales;null!==t.xAxisID&&t.xAxisID in n&&!i.xAxisID||(t.xAxisID=i.xAxisID||a.xAxes[0].id),null!==t.yAxisID&&t.yAxisID in n&&!i.yAxisID||(t.yAxisID=i.yAxisID||a.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]},_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())},reset:function(){this._update(!0)},destroy:function(){this._data&&tt(this._data,this)},createMetaDataset:function(){var t=this.datasetElementType;return t&&new t({_chart:this.chart,_datasetIndex:this.index})},createMetaData:function(t){var e=this.dataElementType;return e&&new e({_chart:this.chart,_datasetIndex:this.index,_index:t})},addElements:function(){var t,e,n=this.getMeta(),i=this.getDataset().data||[],a=n.data;for(t=0,e=i.length;t<e;++t)a[t]=a[t]||this.createMetaData(t);n.dataset=n.dataset||this.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,e,n=this,i=n.getDataset(),a=i.data||(i.data=[]);n._data!==a&&(n._data&&tt(n._data,n),a&&Object.isExtensible(a)&&(e=n,(t=a)._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),Q.forEach((function(e){var n="onData"+e.charAt(0).toUpperCase()+e.slice(1),i=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),a=i.apply(this,e);return V.each(t._chartjs.listeners,(function(t){"function"==typeof t[n]&&t[n].apply(t,e)})),a}})})))),n._data=a),n.resyncElements()},_configure:function(){this._config=V.merge({},[this.chart.options.datasets[this._type],this.getDataset()],{merger:function(t,e,n){"_meta"!==t&&"data"!==t&&V._merger(t,e,n)}})},_update:function(t){this._configure(),this._cachedDataOpts=null,this.update(t)},update:V.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()},getStyle:function(t){var e,n=this.getMeta(),i=n.dataset;return this._configure(),i&&void 0===t?e=this._resolveDatasetElementOptions(i||{}):(t=t||0,e=this._resolveDataElementOptions(n.data[t]||{},t)),!1!==e.fill&&null!==e.fill||(e.backgroundColor=e.borderColor),e},_resolveDatasetElementOptions:function(t,e){var n,i,a,r,o=this,s=o.chart,l=o._config,u=t.custom||{},d=s.options.elements[o.datasetElementType.prototype._type]||{},h=o._datasetElementOptions,c={},f={chart:s,dataset:o.getDataset(),datasetIndex:o.index,hover:e};for(n=0,i=h.length;n<i;++n)a=h[n],r=e?"hover"+a.charAt(0).toUpperCase()+a.slice(1):a,c[a]=J([u[r],l[r],d[r]],f);return c},_resolveDataElementOptions:function(t,e){var n=this,i=t&&t.custom,a=n._cachedDataOpts;if(a&&!i)return a;var r,o,s,l,u=n.chart,d=n._config,h=u.options.elements[n.dataElementType.prototype._type]||{},c=n._dataElementOptions,f={},g={chart:u,dataIndex:e,dataset:n.getDataset(),datasetIndex:n.index},p={cacheable:!i};if(i=i||{},V.isArray(c))for(o=0,s=c.length;o<s;++o)f[l=c[o]]=J([i[l],d[l],h[l]],g,e,p);else for(o=0,s=(r=Object.keys(c)).length;o<s;++o)f[l=r[o]]=J([i[l],d[c[l]],d[l],h[l]],g,e,p);return p.cacheable&&(n._cachedDataOpts=Object.freeze(f)),f},removeHoverStyle:function(t){V.merge(t._model,t.$previousStyle||{}),delete t.$previousStyle},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model,r=V.getHoverColor;t.$previousStyle={backgroundColor:a.backgroundColor,borderColor:a.borderColor,borderWidth:a.borderWidth},a.backgroundColor=J([i.hoverBackgroundColor,e.hoverBackgroundColor,r(a.backgroundColor)],void 0,n),a.borderColor=J([i.hoverBorderColor,e.hoverBorderColor,r(a.borderColor)],void 0,n),a.borderWidth=J([i.hoverBorderWidth,e.hoverBorderWidth,a.borderWidth],void 0,n)},_removeDatasetHoverStyle:function(){var t=this.getMeta().dataset;t&&this.removeHoverStyle(t)},_setDatasetHoverStyle:function(){var t,e,n,i,a,r,o=this.getMeta().dataset,s={};if(o){for(r=o._model,a=this._resolveDatasetElementOptions(o,!0),t=0,e=(i=Object.keys(a)).length;t<e;++t)s[n=i[t]]=r[n],r[n]=a[n];o.$previousStyle=s}},resyncElements:function(){var t=this.getMeta(),e=this.getDataset().data,n=t.data.length,i=e.length;i<n?t.data.splice(i,n-i):i>n&&this.insertElements(n,i-n)},insertElements:function(t,e){for(var n=0;n<e;++n)this.addElementAndReset(t+n)},onDataPush:function(){var t=arguments.length;this.insertElements(this.getDataset().data.length-t,t)},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)}}),et.extend=V.inherits;var nt=et,it=2*Math.PI;function at(t,e){var n=e.startAngle,i=e.endAngle,a=e.pixelMargin,r=a/e.outerRadius,o=e.x,s=e.y;t.beginPath(),t.arc(o,s,e.outerRadius,n-r,i+r),e.innerRadius>a?(r=a/e.innerRadius,t.arc(o,s,e.innerRadius-a,i+r,n-r,!0)):t.arc(o,s,a,i+Math.PI/2,n-Math.PI/2),t.closePath(),t.clip()}function rt(t,e,n){var i="inner"===e.borderAlign;i?(t.lineWidth=2*e.borderWidth,t.lineJoin="round"):(t.lineWidth=e.borderWidth,t.lineJoin="bevel"),n.fullCircles&&function(t,e,n,i){var a,r=n.endAngle;for(i&&(n.endAngle=n.startAngle+it,at(t,n),n.endAngle=r,n.endAngle===n.startAngle&&n.fullCircles&&(n.endAngle+=it,n.fullCircles--)),t.beginPath(),t.arc(n.x,n.y,n.innerRadius,n.startAngle+it,n.startAngle,!0),a=0;a<n.fullCircles;++a)t.stroke();for(t.beginPath(),t.arc(n.x,n.y,e.outerRadius,n.startAngle,n.startAngle+it),a=0;a<n.fullCircles;++a)t.stroke()}(t,e,n,i),i&&at(t,n),t.beginPath(),t.arc(n.x,n.y,e.outerRadius,n.startAngle,n.endAngle),t.arc(n.x,n.y,n.innerRadius,n.endAngle,n.startAngle,!0),t.closePath(),t.stroke()}z._set("global",{elements:{arc:{backgroundColor:z.global.defaultColor,borderColor:"#fff",borderWidth:2,borderAlign:"center"}}});var ot=X.extend({_type:"arc",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=V.getAngleFromPoint(n,{x:t,y:e}),a=i.angle,r=i.distance,o=n.startAngle,s=n.endAngle;s<o;)s+=it;for(;a>s;)a-=it;for(;a<o;)a+=it;var l=a>=o&&a<=s,u=r>=n.innerRadius&&r<=n.outerRadius;return l&&u}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,e=this._chart.ctx,n=this._view,i="inner"===n.borderAlign?.33:0,a={x:n.x,y:n.y,innerRadius:n.innerRadius,outerRadius:Math.max(n.outerRadius-i,0),pixelMargin:i,startAngle:n.startAngle,endAngle:n.endAngle,fullCircles:Math.floor(n.circumference/it)};if(e.save(),e.fillStyle=n.backgroundColor,e.strokeStyle=n.borderColor,a.fullCircles){for(a.endAngle=a.startAngle+it,e.beginPath(),e.arc(a.x,a.y,a.outerRadius,a.startAngle,a.endAngle),e.arc(a.x,a.y,a.innerRadius,a.endAngle,a.startAngle,!0),e.closePath(),t=0;t<a.fullCircles;++t)e.fill();a.endAngle=a.startAngle+n.circumference%it}e.beginPath(),e.arc(a.x,a.y,a.outerRadius,a.startAngle,a.endAngle),e.arc(a.x,a.y,a.innerRadius,a.endAngle,a.startAngle,!0),e.closePath(),e.fill(),n.borderWidth&&rt(e,n,a),e.restore()}}),st=V.valueOrDefault,lt=z.global.defaultColor;z._set("global",{elements:{line:{tension:.4,backgroundColor:lt,borderWidth:3,borderColor:lt,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}});var ut=X.extend({_type:"line",draw:function(){var t,e,n,i=this,a=i._view,r=i._chart.ctx,o=a.spanGaps,s=i._children.slice(),l=z.global,u=l.elements.line,d=-1,h=i._loop;if(s.length){if(i._loop){for(t=0;t<s.length;++t)if(e=V.previousItem(s,t),!s[t]._view.skip&&e._view.skip){s=s.slice(t).concat(s.slice(0,t)),h=o;break}h&&s.push(s[0])}for(r.save(),r.lineCap=a.borderCapStyle||u.borderCapStyle,r.setLineDash&&r.setLineDash(a.borderDash||u.borderDash),r.lineDashOffset=st(a.borderDashOffset,u.borderDashOffset),r.lineJoin=a.borderJoinStyle||u.borderJoinStyle,r.lineWidth=st(a.borderWidth,u.borderWidth),r.strokeStyle=a.borderColor||l.defaultColor,r.beginPath(),(n=s[0]._view).skip||(r.moveTo(n.x,n.y),d=0),t=1;t<s.length;++t)n=s[t]._view,e=-1===d?V.previousItem(s,t):s[d],n.skip||(d!==t-1&&!o||-1===d?r.moveTo(n.x,n.y):V.canvas.lineTo(r,e._view,n),d=t);h&&r.closePath(),r.stroke(),r.restore()}}}),dt=V.valueOrDefault,ht=z.global.defaultColor;function ct(t){var e=this._view;return!!e&&Math.abs(t-e.x)<e.radius+e.hitRadius}z._set("global",{elements:{point:{radius:3,pointStyle:"circle",backgroundColor:ht,borderColor:ht,borderWidth:1,hitRadius:1,hoverRadius:4,hoverBorderWidth:1}}});var ft=X.extend({_type:"point",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:ct,inXRange:ct,inYRange:function(t){var e=this._view;return!!e&&Math.abs(t-e.y)<e.radius+e.hitRadius},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._chart.ctx,i=e.pointStyle,a=e.rotation,r=e.radius,o=e.x,s=e.y,l=z.global,u=l.defaultColor;e.skip||(void 0===t||V.canvas._isPointInArea(e,t))&&(n.strokeStyle=e.borderColor||u,n.lineWidth=dt(e.borderWidth,l.elements.point.borderWidth),n.fillStyle=e.backgroundColor||u,V.canvas.drawPoint(n,i,r,o,s,a))}}),gt=z.global.defaultColor;function pt(t){return t&&void 0!==t.width}function mt(t){var e,n,i,a,r;return pt(t)?(r=t.width/2,e=t.x-r,n=t.x+r,i=Math.min(t.y,t.base),a=Math.max(t.y,t.base)):(r=t.height/2,e=Math.min(t.x,t.base),n=Math.max(t.x,t.base),i=t.y-r,a=t.y+r),{left:e,top:i,right:n,bottom:a}}function vt(t,e,n){return t===e?n:t===n?e:t}function bt(t,e,n){var i,a,r,o,s=t.borderWidth,l=function(t){var e=t.borderSkipped,n={};return e?(t.horizontal?t.base>t.x&&(e=vt(e,"left","right")):t.base<t.y&&(e=vt(e,"bottom","top")),n[e]=!0,n):n}(t);return V.isObject(s)?(i=+s.top||0,a=+s.right||0,r=+s.bottom||0,o=+s.left||0):i=a=r=o=+s||0,{t:l.top||i<0?0:i>n?n:i,r:l.right||a<0?0:a>e?e:a,b:l.bottom||r<0?0:r>n?n:r,l:l.left||o<0?0:o>e?e:o}}function xt(t,e,n){var i=null===e,a=null===n,r=!(!t||i&&a)&&mt(t);return r&&(i||e>=r.left&&e<=r.right)&&(a||n>=r.top&&n<=r.bottom)}z._set("global",{elements:{rectangle:{backgroundColor:gt,borderColor:gt,borderSkipped:"bottom",borderWidth:0}}});var yt=X.extend({_type:"rectangle",draw:function(){var t=this._chart.ctx,e=this._view,n=function(t){var e=mt(t),n=e.right-e.left,i=e.bottom-e.top,a=bt(t,n/2,i/2);return{outer:{x:e.left,y:e.top,w:n,h:i},inner:{x:e.left+a.l,y:e.top+a.t,w:n-a.l-a.r,h:i-a.t-a.b}}}(e),i=n.outer,a=n.inner;t.fillStyle=e.backgroundColor,t.fillRect(i.x,i.y,i.w,i.h),i.w===a.w&&i.h===a.h||(t.save(),t.beginPath(),t.rect(i.x,i.y,i.w,i.h),t.clip(),t.fillStyle=e.borderColor,t.rect(a.x,a.y,a.w,a.h),t.fill("evenodd"),t.restore())},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){return xt(this._view,t,e)},inLabelRange:function(t,e){var n=this._view;return pt(n)?xt(n,t,null):xt(n,null,e)},inXRange:function(t){return xt(this._view,t,null)},inYRange:function(t){return xt(this._view,null,t)},getCenterPoint:function(){var t,e,n=this._view;return pt(n)?(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 pt(t)?t.width*Math.abs(t.y-t.base):t.height*Math.abs(t.x-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}}),_t={},kt=ot,wt=ut,Mt=ft,St=yt;_t.Arc=kt,_t.Line=wt,_t.Point=Mt,_t.Rectangle=St;var Ct=V._deprecated,Pt=V.valueOrDefault;function At(t,e,n){var i,a,r=n.barThickness,o=e.stackCount,s=e.pixels[t],l=V.isNullOrUndef(r)?function(t,e){var n,i,a,r,o=t._length;for(a=1,r=e.length;a<r;++a)o=Math.min(o,Math.abs(e[a]-e[a-1]));for(a=0,r=t.getTicks().length;a<r;++a)i=t.getPixelForTick(a),o=a>0?Math.min(o,Math.abs(i-n)):o,n=i;return o}(e.scale,e.pixels):-1;return V.isNullOrUndef(r)?(i=l*n.categoryPercentage,a=n.barPercentage):(i=r*o,a=1),{chunk:i/o,ratio:a,start:s-i/2}}z._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),z._set("global",{datasets:{bar:{categoryPercentage:.8,barPercentage:.9}}});var Dt=nt.extend({dataElementType:_t.Rectangle,_dataElementOptions:["backgroundColor","borderColor","borderSkipped","borderWidth","barPercentage","barThickness","categoryPercentage","maxBarThickness","minBarLength"],initialize:function(){var t,e,n=this;nt.prototype.initialize.apply(n,arguments),(t=n.getMeta()).stack=n.getDataset().stack,t.bar=!0,e=n._getIndexScale().options,Ct("bar chart",e.barPercentage,"scales.[x/y]Axes.barPercentage","dataset.barPercentage"),Ct("bar chart",e.barThickness,"scales.[x/y]Axes.barThickness","dataset.barThickness"),Ct("bar chart",e.categoryPercentage,"scales.[x/y]Axes.categoryPercentage","dataset.categoryPercentage"),Ct("bar chart",n._getValueScale().options.minBarLength,"scales.[x/y]Axes.minBarLength","dataset.minBarLength"),Ct("bar chart",e.maxBarThickness,"scales.[x/y]Axes.maxBarThickness","dataset.maxBarThickness")},update:function(t){var e,n,i=this.getMeta().data;for(this._ruler=this.getRuler(),e=0,n=i.length;e<n;++e)this.updateElement(i[e],e,t)},updateElement:function(t,e,n){var i=this,a=i.getMeta(),r=i.getDataset(),o=i._resolveDataElementOptions(t,e);t._xScale=i.getScaleForId(a.xAxisID),t._yScale=i.getScaleForId(a.yAxisID),t._datasetIndex=i.index,t._index=e,t._model={backgroundColor:o.backgroundColor,borderColor:o.borderColor,borderSkipped:o.borderSkipped,borderWidth:o.borderWidth,datasetLabel:r.label,label:i.chart.data.labels[e]},V.isArray(r.data[e])&&(t._model.borderSkipped=null),i._updateElementGeometry(t,e,n,o),t.pivot()},_updateElementGeometry:function(t,e,n,i){var a=this,r=t._model,o=a._getValueScale(),s=o.getBasePixel(),l=o.isHorizontal(),u=a._ruler||a.getRuler(),d=a.calculateBarValuePixels(a.index,e,i),h=a.calculateBarIndexPixels(a.index,e,u,i);r.horizontal=l,r.base=n?s:d.base,r.x=l?n?s:d.head:h.center,r.y=l?h.center:n?s:d.head,r.height=l?h.size:void 0,r.width=l?void 0:h.size},_getStacks:function(t){var e,n,i=this._getIndexScale(),a=i._getMatchingVisibleMetas(this._type),r=i.options.stacked,o=a.length,s=[];for(e=0;e<o&&(n=a[e],(!1===r||-1===s.indexOf(n.stack)||void 0===r&&void 0===n.stack)&&s.push(n.stack),n.index!==t);++e);return s},getStackCount:function(){return this._getStacks().length},getStackIndex:function(t,e){var n=this._getStacks(t),i=void 0!==e?n.indexOf(e):-1;return-1===i?n.length-1:i},getRuler:function(){var t,e,n=this._getIndexScale(),i=[];for(t=0,e=this.getMeta().data.length;t<e;++t)i.push(n.getPixelForValue(null,t,this.index));return{pixels:i,start:n._startPixel,end:n._endPixel,stackCount:this.getStackCount(),scale:n}},calculateBarValuePixels:function(t,e,n){var i,a,r,o,s,l,u,d=this.chart,h=this._getValueScale(),c=h.isHorizontal(),f=d.data.datasets,g=h._getMatchingVisibleMetas(this._type),p=h._parseValue(f[t].data[e]),m=n.minBarLength,v=h.options.stacked,b=this.getMeta().stack,x=void 0===p.start?0:p.max>=0&&p.min>=0?p.min:p.max,y=void 0===p.start?p.end:p.max>=0&&p.min>=0?p.max-p.min:p.min-p.max,_=g.length;if(v||void 0===v&&void 0!==b)for(i=0;i<_&&(a=g[i]).index!==t;++i)a.stack===b&&(r=void 0===(u=h._parseValue(f[a.index].data[e])).start?u.end:u.min>=0&&u.max>=0?u.max:u.min,(p.min<0&&r<0||p.max>=0&&r>0)&&(x+=r));return o=h.getPixelForValue(x),l=(s=h.getPixelForValue(x+y))-o,void 0!==m&&Math.abs(l)<m&&(l=m,s=y>=0&&!c||y<0&&c?o-m:o+m),{size:l,base:o,head:s,center:s+l/2}},calculateBarIndexPixels:function(t,e,n,i){var a="flex"===i.barThickness?function(t,e,n){var i,a=e.pixels,r=a[t],o=t>0?a[t-1]:null,s=t<a.length-1?a[t+1]:null,l=n.categoryPercentage;return null===o&&(o=r-(null===s?e.end-e.start:s-r)),null===s&&(s=r+r-o),i=r-(r-Math.min(o,s))/2*l,{chunk:Math.abs(s-o)/2*l/e.stackCount,ratio:n.barPercentage,start:i}}(e,n,i):At(e,n,i),r=this.getStackIndex(t,this.getMeta().stack),o=a.start+a.chunk*r+a.chunk/2,s=Math.min(Pt(i.maxBarThickness,1/0),a.chunk*a.ratio);return{base:o-s/2,head:o+s/2,center:o,size:s}},draw:function(){var t=this.chart,e=this._getValueScale(),n=this.getMeta().data,i=this.getDataset(),a=n.length,r=0;for(V.canvas.clipArea(t.ctx,t.chartArea);r<a;++r){var o=e._parseValue(i.data[r]);isNaN(o.min)||isNaN(o.max)||n[r].draw()}V.canvas.unclipArea(t.ctx)},_resolveDataElementOptions:function(){var t=this,e=V.extend({},nt.prototype._resolveDataElementOptions.apply(t,arguments)),n=t._getIndexScale().options,i=t._getValueScale().options;return e.barPercentage=Pt(n.barPercentage,e.barPercentage),e.barThickness=Pt(n.barThickness,e.barThickness),e.categoryPercentage=Pt(n.categoryPercentage,e.categoryPercentage),e.maxBarThickness=Pt(n.maxBarThickness,e.maxBarThickness),e.minBarLength=Pt(i.minBarLength,e.minBarLength),e}}),Tt=V.valueOrDefault,It=V.options.resolve;z._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+")"}}}});var Ft=nt.extend({dataElementType:_t.Point,_dataElementOptions:["backgroundColor","borderColor","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","pointStyle","rotation"],update:function(t){var e=this,n=e.getMeta().data;V.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._resolveDataElementOptions(t,e),u=i.getDataset().data[e],d=i.index,h=n?o.getPixelForDecimal(.5):o.getPixelForValue("object"==typeof u?u:NaN,e,d),c=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,rotation:l.rotation,radius:n?0:l.radius,skip:r.skip||isNaN(h)||isNaN(c),x:h,y:c},t.pivot()},setHoverStyle:function(t){var e=t._model,n=t._options,i=V.getHoverColor;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth,radius:e.radius},e.backgroundColor=Tt(n.hoverBackgroundColor,i(n.backgroundColor)),e.borderColor=Tt(n.hoverBorderColor,i(n.borderColor)),e.borderWidth=Tt(n.hoverBorderWidth,n.borderWidth),e.radius=n.radius+n.hoverRadius},_resolveDataElementOptions:function(t,e){var n=this,i=n.chart,a=n.getDataset(),r=t.custom||{},o=a.data[e]||{},s=nt.prototype._resolveDataElementOptions.apply(n,arguments),l={chart:i,dataIndex:e,dataset:a,datasetIndex:n.index};return n._cachedDataOpts===s&&(s=V.extend({},s)),s.radius=It([r.radius,o.r,n._config.radius,i.options.elements.point.radius],l,e),s}}),Lt=V.valueOrDefault,Ot=Math.PI,Rt=2*Ot,zt=Ot/2;z._set("doughnut",{animation:{animateRotate:!0,animateScale:!1},hover:{mode:"single"},legendCallback:function(t){var e,n,i,a=document.createElement("ul"),r=t.data,o=r.datasets,s=r.labels;if(a.setAttribute("class",t.id+"-legend"),o.length)for(e=0,n=o[0].data.length;e<n;++e)(i=a.appendChild(document.createElement("li"))).appendChild(document.createElement("span")).style.backgroundColor=o[0].backgroundColor[e],s[e]&&i.appendChild(document.createTextNode(s[e]));return a.outerHTML},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),r=a.controller.getStyle(i);return{text:n,fillStyle:r.backgroundColor,strokeStyle:r.borderColor,lineWidth:r.borderWidth,hidden:isNaN(e.datasets[0].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:-zt,circumference:Rt,tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.labels[t.index],i=": "+e.datasets[t.datasetIndex].data[t.index];return V.isArray(n)?(n=n.slice())[0]+=i:n+=i,n}}}});var Nt=nt.extend({dataElementType:_t.Arc,linkScales:V.noop,_dataElementOptions:["backgroundColor","borderColor","borderWidth","borderAlign","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth"],getRingIndex:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var e,n,i,a,r=this,o=r.chart,s=o.chartArea,l=o.options,u=1,d=1,h=0,c=0,f=r.getMeta(),g=f.data,p=l.cutoutPercentage/100||0,m=l.circumference,v=r._getRingWeight(r.index);if(m<Rt){var b=l.rotation%Rt,x=(b+=b>=Ot?-Rt:b<-Ot?Rt:0)+m,y=Math.cos(b),_=Math.sin(b),k=Math.cos(x),w=Math.sin(x),M=b<=0&&x>=0||x>=Rt,S=b<=zt&&x>=zt||x>=Rt+zt,C=b<=-zt&&x>=-zt||x>=Ot+zt,P=b===-Ot||x>=Ot?-1:Math.min(y,y*p,k,k*p),A=C?-1:Math.min(_,_*p,w,w*p),D=M?1:Math.max(y,y*p,k,k*p),T=S?1:Math.max(_,_*p,w,w*p);u=(D-P)/2,d=(T-A)/2,h=-(D+P)/2,c=-(T+A)/2}for(i=0,a=g.length;i<a;++i)g[i]._options=r._resolveDataElementOptions(g[i],i);for(o.borderWidth=r.getMaxBorderWidth(),e=(s.right-s.left-o.borderWidth)/u,n=(s.bottom-s.top-o.borderWidth)/d,o.outerRadius=Math.max(Math.min(e,n)/2,0),o.innerRadius=Math.max(o.outerRadius*p,0),o.radiusLength=(o.outerRadius-o.innerRadius)/(r._getVisibleDatasetWeightTotal()||1),o.offsetX=h*o.outerRadius,o.offsetY=c*o.outerRadius,f.total=r.calculateTotal(),r.outerRadius=o.outerRadius-o.radiusLength*r._getRingWeightOffset(r.index),r.innerRadius=Math.max(r.outerRadius-o.radiusLength*v,0),i=0,a=g.length;i<a;++i)r.updateElement(g[i],i,t)},updateElement:function(t,e,n){var i=this,a=i.chart,r=a.chartArea,o=a.options,s=o.animation,l=(r.left+r.right)/2,u=(r.top+r.bottom)/2,d=o.rotation,h=o.rotation,c=i.getDataset(),f=n&&s.animateRotate?0:t.hidden?0:i.calculateCircumference(c.data[e])*(o.circumference/Rt),g=n&&s.animateScale?0:i.innerRadius,p=n&&s.animateScale?0:i.outerRadius,m=t._options||{};V.extend(t,{_datasetIndex:i.index,_index:e,_model:{backgroundColor:m.backgroundColor,borderColor:m.borderColor,borderWidth:m.borderWidth,borderAlign:m.borderAlign,x:l+a.offsetX,y:u+a.offsetY,startAngle:d,endAngle:h,circumference:f,outerRadius:p,innerRadius:g,label:V.valueAtIndexOrDefault(c.label,e,a.data.labels[e])}});var v=t._model;n&&s.animateRotate||(v.startAngle=0===e?o.rotation:i.getMeta().data[e-1]._model.endAngle,v.endAngle=v.startAngle+v.circumference),t.pivot()},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),i=0;return V.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)?Rt*(Math.abs(t)/e):0},getMaxBorderWidth:function(t){var e,n,i,a,r,o,s,l,u=0,d=this.chart;if(!t)for(e=0,n=d.data.datasets.length;e<n;++e)if(d.isDatasetVisible(e)){t=(i=d.getDatasetMeta(e)).data,e!==this.index&&(r=i.controller);break}if(!t)return 0;for(e=0,n=t.length;e<n;++e)a=t[e],r?(r._configure(),o=r._resolveDataElementOptions(a,e)):o=a._options,"inner"!==o.borderAlign&&(s=o.borderWidth,u=(l=o.hoverBorderWidth)>(u=s>u?s:u)?l:u);return u},setHoverStyle:function(t){var e=t._model,n=t._options,i=V.getHoverColor;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth},e.backgroundColor=Lt(n.hoverBackgroundColor,i(n.backgroundColor)),e.borderColor=Lt(n.hoverBorderColor,i(n.borderColor)),e.borderWidth=Lt(n.hoverBorderWidth,n.borderWidth)},_getRingWeightOffset:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&(e+=this._getRingWeight(n));return e},_getRingWeight:function(t){return Math.max(Lt(this.chart.data.datasets[t].weight,1),0)},_getVisibleDatasetWeightTotal:function(){return this._getRingWeightOffset(this.chart.data.datasets.length)}});z._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{type:"category",position:"left",offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{mode:"index",axis:"y"}}),z._set("global",{datasets:{horizontalBar:{categoryPercentage:.8,barPercentage:.9}}});var Bt=Dt.extend({_getValueScaleId:function(){return this.getMeta().xAxisID},_getIndexScaleId:function(){return this.getMeta().yAxisID}}),Et=V.valueOrDefault,Wt=V.options.resolve,Vt=V.canvas._isPointInArea;function Ht(t,e){var n=t&&t.options.ticks||{},i=n.reverse,a=void 0===n.min?e:0,r=void 0===n.max?e:0;return{start:i?r:a,end:i?a:r}}function jt(t,e,n){var i=n/2,a=Ht(t,i),r=Ht(e,i);return{top:r.end,right:a.end,bottom:r.start,left:a.start}}function qt(t){var e,n,i,a;return V.isObject(t)?(e=t.top,n=t.right,i=t.bottom,a=t.left):e=n=i=a=t,{top:e,right:n,bottom:i,left:a}}z._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}});var Ut=nt.extend({datasetElementType:_t.Line,dataElementType:_t.Point,_datasetElementOptions:["backgroundColor","borderCapStyle","borderColor","borderDash","borderDashOffset","borderJoinStyle","borderWidth","cubicInterpolationMode","fill"],_dataElementOptions:{backgroundColor:"pointBackgroundColor",borderColor:"pointBorderColor",borderWidth:"pointBorderWidth",hitRadius:"pointHitRadius",hoverBackgroundColor:"pointHoverBackgroundColor",hoverBorderColor:"pointHoverBorderColor",hoverBorderWidth:"pointHoverBorderWidth",hoverRadius:"pointHoverRadius",pointStyle:"pointStyle",radius:"pointRadius",rotation:"pointRotation"},update:function(t){var e,n,i=this,a=i.getMeta(),r=a.dataset,o=a.data||[],s=i.chart.options,l=i._config,u=i._showLine=Et(l.showLine,s.showLines);for(i._xScale=i.getScaleForId(a.xAxisID),i._yScale=i.getScaleForId(a.yAxisID),u&&(void 0!==l.tension&&void 0===l.lineTension&&(l.lineTension=l.tension),r._scale=i._yScale,r._datasetIndex=i.index,r._children=o,r._model=i._resolveDatasetElementOptions(r),r.pivot()),e=0,n=o.length;e<n;++e)i.updateElement(o[e],e,t);for(u&&0!==r._model.tension&&i.updateBezierControlPoints(),e=0,n=o.length;e<n;++e)o[e].pivot()},updateElement:function(t,e,n){var i,a,r=this,o=r.getMeta(),s=t.custom||{},l=r.getDataset(),u=r.index,d=l.data[e],h=r._xScale,c=r._yScale,f=o.dataset._model,g=r._resolveDataElementOptions(t,e);i=h.getPixelForValue("object"==typeof d?d:NaN,e,u),a=n?c.getBasePixel():r.calculatePointY(d,e,u),t._xScale=h,t._yScale=c,t._options=g,t._datasetIndex=u,t._index=e,t._model={x:i,y:a,skip:s.skip||isNaN(i)||isNaN(a),radius:g.radius,pointStyle:g.pointStyle,rotation:g.rotation,backgroundColor:g.backgroundColor,borderColor:g.borderColor,borderWidth:g.borderWidth,tension:Et(s.tension,f?f.tension:0),steppedLine:!!f&&f.steppedLine,hitRadius:g.hitRadius}},_resolveDatasetElementOptions:function(t){var e=this,n=e._config,i=t.custom||{},a=e.chart.options,r=a.elements.line,o=nt.prototype._resolveDatasetElementOptions.apply(e,arguments);return o.spanGaps=Et(n.spanGaps,a.spanGaps),o.tension=Et(n.lineTension,r.tension),o.steppedLine=Wt([i.steppedLine,n.steppedLine,r.stepped]),o.clip=qt(Et(n.clip,jt(e._xScale,e._yScale,o.borderWidth))),o},calculatePointY:function(t,e,n){var i,a,r,o,s,l,u,d=this.chart,h=this._yScale,c=0,f=0;if(h.options.stacked){for(s=+h.getRightValue(t),u=(l=d._getSortedVisibleDatasetMetas()).length,i=0;i<u&&(r=l[i]).index!==n;++i)a=d.data.datasets[r.index],"line"===r.type&&r.yAxisID===h.id&&((o=+h.getRightValue(a.data[e]))<0?f+=o||0:c+=o||0);return s<0?h.getPixelForValue(f+s):h.getPixelForValue(c+s)}return h.getPixelForValue(t)},updateBezierControlPoints:function(){var t,e,n,i,a=this.chart,r=this.getMeta(),o=r.dataset._model,s=a.chartArea,l=r.data||[];function u(t,e,n){return Math.max(Math.min(t,n),e)}if(o.spanGaps&&(l=l.filter((function(t){return!t._model.skip}))),"monotone"===o.cubicInterpolationMode)V.splineCurveMonotone(l);else for(t=0,e=l.length;t<e;++t)n=l[t]._model,i=V.splineCurve(V.previousItem(l,t)._model,n,V.nextItem(l,t)._model,o.tension),n.controlPointPreviousX=i.previous.x,n.controlPointPreviousY=i.previous.y,n.controlPointNextX=i.next.x,n.controlPointNextY=i.next.y;if(a.options.elements.line.capBezierPoints)for(t=0,e=l.length;t<e;++t)n=l[t]._model,Vt(n,s)&&(t>0&&Vt(l[t-1]._model,s)&&(n.controlPointPreviousX=u(n.controlPointPreviousX,s.left,s.right),n.controlPointPreviousY=u(n.controlPointPreviousY,s.top,s.bottom)),t<l.length-1&&Vt(l[t+1]._model,s)&&(n.controlPointNextX=u(n.controlPointNextX,s.left,s.right),n.controlPointNextY=u(n.controlPointNextY,s.top,s.bottom)))},draw:function(){var t,e=this.chart,n=this.getMeta(),i=n.data||[],a=e.chartArea,r=e.canvas,o=0,s=i.length;for(this._showLine&&(t=n.dataset._model.clip,V.canvas.clipArea(e.ctx,{left:!1===t.left?0:a.left-t.left,right:!1===t.right?r.width:a.right+t.right,top:!1===t.top?0:a.top-t.top,bottom:!1===t.bottom?r.height:a.bottom+t.bottom}),n.dataset.draw(),V.canvas.unclipArea(e.ctx));o<s;++o)i[o].draw(a)},setHoverStyle:function(t){var e=t._model,n=t._options,i=V.getHoverColor;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth,radius:e.radius},e.backgroundColor=Et(n.hoverBackgroundColor,i(n.backgroundColor)),e.borderColor=Et(n.hoverBorderColor,i(n.borderColor)),e.borderWidth=Et(n.hoverBorderWidth,n.borderWidth),e.radius=Et(n.hoverRadius,n.radius)}}),Yt=V.options.resolve;z._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,n,i,a=document.createElement("ul"),r=t.data,o=r.datasets,s=r.labels;if(a.setAttribute("class",t.id+"-legend"),o.length)for(e=0,n=o[0].data.length;e<n;++e)(i=a.appendChild(document.createElement("li"))).appendChild(document.createElement("span")).style.backgroundColor=o[0].backgroundColor[e],s[e]&&i.appendChild(document.createTextNode(s[e]));return a.outerHTML},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),r=a.controller.getStyle(i);return{text:n,fillStyle:r.backgroundColor,strokeStyle:r.borderColor,lineWidth:r.borderWidth,hidden:isNaN(e.datasets[0].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}}}});var Gt=nt.extend({dataElementType:_t.Arc,linkScales:V.noop,_dataElementOptions:["backgroundColor","borderColor","borderWidth","borderAlign","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth"],_getIndexScaleId:function(){return this.chart.scale.id},_getValueScaleId:function(){return this.chart.scale.id},update:function(t){var e,n,i,a=this,r=a.getDataset(),o=a.getMeta(),s=a.chart.options.startAngle||0,l=a._starts=[],u=a._angles=[],d=o.data;for(a._updateRadius(),o.count=a.countVisibleElements(),e=0,n=r.data.length;e<n;e++)l[e]=s,i=a._computeAngle(e),u[e]=i,s+=i;for(e=0,n=d.length;e<n;++e)d[e]._options=a._resolveDataElementOptions(d[e],e),a.updateElement(d[e],e,t)},_updateRadius:function(){var t=this,e=t.chart,n=e.chartArea,i=e.options,a=Math.min(n.right-n.left,n.bottom-n.top);e.outerRadius=Math.max(a/2,0),e.innerRadius=Math.max(i.cutoutPercentage?e.outerRadius/100*i.cutoutPercentage:1,0),e.radiusLength=(e.outerRadius-e.innerRadius)/e.getVisibleDatasetCount(),t.outerRadius=e.outerRadius-e.radiusLength*t.index,t.innerRadius=t.outerRadius-e.radiusLength},updateElement:function(t,e,n){var i=this,a=i.chart,r=i.getDataset(),o=a.options,s=o.animation,l=a.scale,u=a.data.labels,d=l.xCenter,h=l.yCenter,c=o.startAngle,f=t.hidden?0:l.getDistanceFromCenterForValue(r.data[e]),g=i._starts[e],p=g+(t.hidden?0:i._angles[e]),m=s.animateScale?0:l.getDistanceFromCenterForValue(r.data[e]),v=t._options||{};V.extend(t,{_datasetIndex:i.index,_index:e,_scale:l,_model:{backgroundColor:v.backgroundColor,borderColor:v.borderColor,borderWidth:v.borderWidth,borderAlign:v.borderAlign,x:d,y:h,innerRadius:0,outerRadius:n?m:f,startAngle:n&&s.animateRotate?c:g,endAngle:n&&s.animateRotate?c:p,label:V.valueAtIndexOrDefault(u,e,u[e])}}),t.pivot()},countVisibleElements:function(){var t=this.getDataset(),e=this.getMeta(),n=0;return V.each(e.data,(function(e,i){isNaN(t.data[i])||e.hidden||n++})),n},setHoverStyle:function(t){var e=t._model,n=t._options,i=V.getHoverColor,a=V.valueOrDefault;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth},e.backgroundColor=a(n.hoverBackgroundColor,i(n.backgroundColor)),e.borderColor=a(n.hoverBorderColor,i(n.borderColor)),e.borderWidth=a(n.hoverBorderWidth,n.borderWidth)},_computeAngle:function(t){var e=this,n=this.getMeta().count,i=e.getDataset(),a=e.getMeta();if(isNaN(i.data[t])||a.data[t].hidden)return 0;var r={chart:e.chart,dataIndex:t,dataset:i,datasetIndex:e.index};return Yt([e.chart.options.elements.arc.angle,2*Math.PI/n],r,t)}});z._set("pie",V.clone(z.doughnut)),z._set("pie",{cutoutPercentage:0});var Xt=Nt,Kt=V.valueOrDefault;z._set("radar",{spanGaps:!1,scale:{type:"radialLinear"},elements:{line:{fill:"start",tension:0}}});var Zt=nt.extend({datasetElementType:_t.Line,dataElementType:_t.Point,linkScales:V.noop,_datasetElementOptions:["backgroundColor","borderWidth","borderColor","borderCapStyle","borderDash","borderDashOffset","borderJoinStyle","fill"],_dataElementOptions:{backgroundColor:"pointBackgroundColor",borderColor:"pointBorderColor",borderWidth:"pointBorderWidth",hitRadius:"pointHitRadius",hoverBackgroundColor:"pointHoverBackgroundColor",hoverBorderColor:"pointHoverBorderColor",hoverBorderWidth:"pointHoverBorderWidth",hoverRadius:"pointHoverRadius",pointStyle:"pointStyle",radius:"pointRadius",rotation:"pointRotation"},_getIndexScaleId:function(){return this.chart.scale.id},_getValueScaleId:function(){return this.chart.scale.id},update:function(t){var e,n,i=this,a=i.getMeta(),r=a.dataset,o=a.data||[],s=i.chart.scale,l=i._config;for(void 0!==l.tension&&void 0===l.lineTension&&(l.lineTension=l.tension),r._scale=s,r._datasetIndex=i.index,r._children=o,r._loop=!0,r._model=i._resolveDatasetElementOptions(r),r.pivot(),e=0,n=o.length;e<n;++e)i.updateElement(o[e],e,t);for(i.updateBezierControlPoints(),e=0,n=o.length;e<n;++e)o[e].pivot()},updateElement:function(t,e,n){var i=this,a=t.custom||{},r=i.getDataset(),o=i.chart.scale,s=o.getPointPositionForValue(e,r.data[e]),l=i._resolveDataElementOptions(t,e),u=i.getMeta().dataset._model,d=n?o.xCenter:s.x,h=n?o.yCenter:s.y;t._scale=o,t._options=l,t._datasetIndex=i.index,t._index=e,t._model={x:d,y:h,skip:a.skip||isNaN(d)||isNaN(h),radius:l.radius,pointStyle:l.pointStyle,rotation:l.rotation,backgroundColor:l.backgroundColor,borderColor:l.borderColor,borderWidth:l.borderWidth,tension:Kt(a.tension,u?u.tension:0),hitRadius:l.hitRadius}},_resolveDatasetElementOptions:function(){var t=this,e=t._config,n=t.chart.options,i=nt.prototype._resolveDatasetElementOptions.apply(t,arguments);return i.spanGaps=Kt(e.spanGaps,n.spanGaps),i.tension=Kt(e.lineTension,n.elements.line.tension),i},updateBezierControlPoints:function(){var t,e,n,i,a=this.getMeta(),r=this.chart.chartArea,o=a.data||[];function s(t,e,n){return Math.max(Math.min(t,n),e)}for(a.dataset._model.spanGaps&&(o=o.filter((function(t){return!t._model.skip}))),t=0,e=o.length;t<e;++t)n=o[t]._model,i=V.splineCurve(V.previousItem(o,t,!0)._model,n,V.nextItem(o,t,!0)._model,n.tension),n.controlPointPreviousX=s(i.previous.x,r.left,r.right),n.controlPointPreviousY=s(i.previous.y,r.top,r.bottom),n.controlPointNextX=s(i.next.x,r.left,r.right),n.controlPointNextY=s(i.next.y,r.top,r.bottom)},setHoverStyle:function(t){var e=t._model,n=t._options,i=V.getHoverColor;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth,radius:e.radius},e.backgroundColor=Kt(n.hoverBackgroundColor,i(n.backgroundColor)),e.borderColor=Kt(n.hoverBorderColor,i(n.borderColor)),e.borderWidth=Kt(n.hoverBorderWidth,n.borderWidth),e.radius=Kt(n.hoverRadius,n.radius)}});z._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),z._set("global",{datasets:{scatter:{showLine:!1}}});var $t={bar:Dt,bubble:Ft,doughnut:Nt,horizontalBar:Bt,line:Ut,polarArea:Gt,pie:Xt,radar:Zt,scatter:Ut};function Jt(t,e){return t.native?{x:t.x,y:t.y}:V.getRelativePosition(t,e)}function Qt(t,e){var n,i,a,r,o,s,l=t._getSortedVisibleDatasetMetas();for(i=0,r=l.length;i<r;++i)for(a=0,o=(n=l[i].data).length;a<o;++a)(s=n[a])._view.skip||e(s)}function te(t,e){var n=[];return Qt(t,(function(t){t.inRange(e.x,e.y)&&n.push(t)})),n}function ee(t,e,n,i){var a=Number.POSITIVE_INFINITY,r=[];return Qt(t,(function(t){if(!n||t.inRange(e.x,e.y)){var o=t.getCenterPoint(),s=i(e,o);s<a?(r=[t],a=s):s===a&&r.push(t)}})),r}function ne(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 ie(t,e,n){var i=Jt(e,t);n.axis=n.axis||"x";var a=ne(n.axis),r=n.intersect?te(t,i):ee(t,i,!1,a),o=[];return r.length?(t._getSortedVisibleDatasetMetas().forEach((function(t){var e=t.data[r[0]._index];e&&!e._view.skip&&o.push(e)})),o):[]}var ae={modes:{single:function(t,e){var n=Jt(e,t),i=[];return Qt(t,(function(t){if(t.inRange(n.x,n.y))return i.push(t),i})),i.slice(0,1)},label:ie,index:ie,dataset:function(t,e,n){var i=Jt(e,t);n.axis=n.axis||"xy";var a=ne(n.axis),r=n.intersect?te(t,i):ee(t,i,!1,a);return r.length>0&&(r=t.getDatasetMeta(r[0]._datasetIndex).data),r},"x-axis":function(t,e){return ie(t,e,{intersect:!1})},point:function(t,e){return te(t,Jt(e,t))},nearest:function(t,e,n){var i=Jt(e,t);n.axis=n.axis||"xy";var a=ne(n.axis);return ee(t,i,n.intersect,a)},x:function(t,e,n){var i=Jt(e,t),a=[],r=!1;return Qt(t,(function(t){t.inXRange(i.x)&&a.push(t),t.inRange(i.x,i.y)&&(r=!0)})),n.intersect&&!r&&(a=[]),a},y:function(t,e,n){var i=Jt(e,t),a=[],r=!1;return Qt(t,(function(t){t.inYRange(i.y)&&a.push(t),t.inRange(i.x,i.y)&&(r=!0)})),n.intersect&&!r&&(a=[]),a}}},re=V.extend;function oe(t,e){return V.where(t,(function(t){return t.pos===e}))}function se(t,e){return t.sort((function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i.index-a.index:i.weight-a.weight}))}function le(t,e,n,i){return Math.max(t[n],e[n])+Math.max(t[i],e[i])}function ue(t,e,n){var i,a,r=n.box,o=t.maxPadding;if(n.size&&(t[n.pos]-=n.size),n.size=n.horizontal?r.height:r.width,t[n.pos]+=n.size,r.getPadding){var s=r.getPadding();o.top=Math.max(o.top,s.top),o.left=Math.max(o.left,s.left),o.bottom=Math.max(o.bottom,s.bottom),o.right=Math.max(o.right,s.right)}if(i=e.outerWidth-le(o,t,"left","right"),a=e.outerHeight-le(o,t,"top","bottom"),i!==t.w||a!==t.h)return t.w=i,t.h=a,n.horizontal?i!==t.w:a!==t.h}function de(t,e){var n=e.maxPadding;function i(t){var i={left:0,top:0,right:0,bottom:0};return t.forEach((function(t){i[t]=Math.max(e[t],n[t])})),i}return i(t?["left","right"]:["top","bottom"])}function he(t,e,n){var i,a,r,o,s,l,u=[];for(i=0,a=t.length;i<a;++i)(o=(r=t[i]).box).update(r.width||e.w,r.height||e.h,de(r.horizontal,e)),ue(e,n,r)&&(l=!0,u.length&&(s=!0)),o.fullWidth||u.push(r);return s&&he(u,e,n)||l}function ce(t,e,n){var i,a,r,o,s=n.padding,l=e.x,u=e.y;for(i=0,a=t.length;i<a;++i)o=(r=t[i]).box,r.horizontal?(o.left=o.fullWidth?s.left:e.left,o.right=o.fullWidth?n.outerWidth-s.right:e.left+e.w,o.top=u,o.bottom=u+o.height,o.width=o.right-o.left,u=o.bottom):(o.left=l,o.right=l+o.width,o.top=e.top,o.bottom=e.top+e.h,o.height=o.bottom-o.top,l=o.right);e.x=l,e.y=u}z._set("global",{layout:{padding:{top:0,right:0,bottom:0,left:0}}});var fe,ge={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,e._layers=e._layers||function(){return[{z:0,draw:function(){e.draw.apply(e,arguments)}}]},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,e,n){if(t){var i=t.options.layout||{},a=V.options.toPadding(i.padding),r=e-a.width,o=n-a.height,s=function(t){var e=function(t){var e,n,i,a=[];for(e=0,n=(t||[]).length;e<n;++e)i=t[e],a.push({index:e,box:i,pos:i.position,horizontal:i.isHorizontal(),weight:i.weight});return a}(t),n=se(oe(e,"left"),!0),i=se(oe(e,"right")),a=se(oe(e,"top"),!0),r=se(oe(e,"bottom"));return{leftAndTop:n.concat(a),rightAndBottom:i.concat(r),chartArea:oe(e,"chartArea"),vertical:n.concat(i),horizontal:a.concat(r)}}(t.boxes),l=s.vertical,u=s.horizontal,d=Object.freeze({outerWidth:e,outerHeight:n,padding:a,availableWidth:r,vBoxMaxWidth:r/2/l.length,hBoxMaxHeight:o/2}),h=re({maxPadding:re({},a),w:r,h:o,x:a.left,y:a.top},a);!function(t,e){var n,i,a;for(n=0,i=t.length;n<i;++n)(a=t[n]).width=a.horizontal?a.box.fullWidth&&e.availableWidth:e.vBoxMaxWidth,a.height=a.horizontal&&e.hBoxMaxHeight}(l.concat(u),d),he(l,h,d),he(u,h,d)&&he(l,h,d),function(t){var e=t.maxPadding;function n(n){var i=Math.max(e[n]-t[n],0);return t[n]+=i,i}t.y+=n("top"),t.x+=n("left"),n("right"),n("bottom")}(h),ce(s.leftAndTop,h,d),h.x+=h.w,h.y+=h.h,ce(s.rightAndBottom,h,d),t.chartArea={left:h.left,top:h.top,right:h.left+h.w,bottom:h.top+h.h},V.each(s.chartArea,(function(e){var n=e.box;re(n,t.chartArea),n.update(h.w,h.h)}))}}},pe=(fe=Object.freeze({__proto__:null,default:"@keyframes chartjs-render-animation{from{opacity:.99}to{opacity:1}}.chartjs-render-monitor{animation:chartjs-render-animation 1ms}.chartjs-size-monitor,.chartjs-size-monitor-expand,.chartjs-size-monitor-shrink{position:absolute;direction:ltr;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1}.chartjs-size-monitor-expand>div{position:absolute;width:1000000px;height:1000000px;left:0;top:0}.chartjs-size-monitor-shrink>div{position:absolute;width:200%;height:200%;left:0;top:0}"}))&&fe.default||fe,me="$chartjs",ve="chartjs-size-monitor",be="chartjs-render-monitor",xe="chartjs-render-animation",ye=["animationstart","webkitAnimationStart"],_e={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"};function ke(t,e){var n=V.getStyle(t,e),i=n&&n.match(/^(\d+)(\.\d+)?px$/);return i?Number(i[1]):void 0}var we=!!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};function Me(t,e,n){t.addEventListener(e,n,we)}function Se(t,e,n){t.removeEventListener(e,n,we)}function Ce(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 Pe(t){var e=document.createElement("div");return e.className=t||"",e}function Ae(t,e,n){var i,a,r,o,s=t[me]||(t[me]={}),l=s.resizer=function(t){var e=Pe(ve),n=Pe(ve+"-expand"),i=Pe(ve+"-shrink");n.appendChild(Pe()),i.appendChild(Pe()),e.appendChild(n),e.appendChild(i),e._reset=function(){n.scrollLeft=1e6,n.scrollTop=1e6,i.scrollLeft=1e6,i.scrollTop=1e6};var a=function(){e._reset(),t()};return Me(n,"scroll",a.bind(n,"expand")),Me(i,"scroll",a.bind(i,"shrink")),e}((i=function(){if(s.resizer){var i=n.options.maintainAspectRatio&&t.parentNode,a=i?i.clientWidth:0;e(Ce("resize",n)),i&&i.clientWidth<a&&n.canvas&&e(Ce("resize",n))}},r=!1,o=[],function(){o=Array.prototype.slice.call(arguments),a=a||this,r||(r=!0,V.requestAnimFrame.call(window,(function(){r=!1,i.apply(a,o)})))}));!function(t,e){var n=t[me]||(t[me]={}),i=n.renderProxy=function(t){t.animationName===xe&&e()};V.each(ye,(function(e){Me(t,e,i)})),n.reflow=!!t.offsetParent,t.classList.add(be)}(t,(function(){if(s.resizer){var e=t.parentNode;e&&e!==l.parentNode&&e.insertBefore(l,e.firstChild),l._reset()}}))}function De(t){var e=t[me]||{},n=e.resizer;delete e.resizer,function(t){var e=t[me]||{},n=e.renderProxy;n&&(V.each(ye,(function(e){Se(t,e,n)})),delete e.renderProxy),t.classList.remove(be)}(t),n&&n.parentNode&&n.parentNode.removeChild(n)}var Te={disableCSSInjection:!1,_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,_ensureLoaded:function(t){if(!this.disableCSSInjection){var e=t.getRootNode?t.getRootNode():document;!function(t,e){var n=t[me]||(t[me]={});if(!n.containsStyles){n.containsStyles=!0,e="/* Chart.js */\n"+e;var i=document.createElement("style");i.setAttribute("type","text/css"),i.appendChild(document.createTextNode(e)),t.appendChild(i)}}(e.host?e:document.head,pe)}},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?(this._ensureLoaded(t),function(t,e){var n=t.style,i=t.getAttribute("height"),a=t.getAttribute("width");if(t[me]={initial:{height:i,width:a,style:{display:n.display,height:n.height,width:n.width}}},n.display=n.display||"block",null===a||""===a){var r=ke(t,"width");void 0!==r&&(t.width=r)}if(null===i||""===i)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var o=ke(t,"height");void 0!==r&&(t.height=o)}}(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e[me]){var n=e[me].initial;["height","width"].forEach((function(t){var i=n[t];V.isNullOrUndef(i)?e.removeAttribute(t):e.setAttribute(t,i)})),V.each(n.style||{},(function(t,n){e.style[n]=t})),e.width=e.width,delete e[me]}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=n[me]||(n[me]={});Me(i,e,(a.proxies||(a.proxies={}))[t.id+"_"+e]=function(e){n(function(t,e){var n=_e[t.type]||t.type,i=V.getRelativePosition(t,e);return Ce(n,e,i.x,i.y,t)}(e,t))})}else Ae(i,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[me]||{}).proxies||{})[t.id+"_"+e];a&&Se(i,e,a)}else De(i)}};V.addEvent=Me,V.removeEvent=Se;var Ie=Te._enabled?Te:{acquireContext:function(t){return t&&t.canvas&&(t=t.canvas),t&&t.getContext("2d")||null}},Fe=V.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},Ie);z._set("global",{plugins:{}});var Le={_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("function"==typeof(s=(r=(a=l[i]).plugin)[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=[],i=[],a=t&&t.config||{},r=a.options&&a.options.plugins||{};return this._plugins.concat(a.plugins||[]).forEach((function(t){if(-1===n.indexOf(t)){var e=t.id,a=r[e];!1!==a&&(!0===a&&(a=V.clone(z.global.plugins[e])),n.push(t),i.push({plugin:t,options:a||{}}))}})),e.descriptors=i,e.id=this._cacheId,i},_invalidate:function(t){delete t.$plugins}},Oe={constructors:{},defaults:{},registerScaleType:function(t,e,n){this.constructors[t]=e,this.defaults[t]=V.clone(n)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(t){return this.defaults.hasOwnProperty(t)?V.merge({},[z.scale,this.defaults[t]]):{}},updateScaleDefaults:function(t,e){this.defaults.hasOwnProperty(t)&&(this.defaults[t]=V.extend(this.defaults[t],e))},addScalesToLayout:function(t){V.each(t.scales,(function(e){e.fullWidth=e.options.fullWidth,e.position=e.options.position,e.weight=e.options.weight,ge.addBox(t,e)}))}},Re=V.valueOrDefault,ze=V.rtl.getRtlAdapter;z._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:V.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var r=t[0];r.label?n=r.label:r.xLabel?n=r.xLabel:a>0&&r.index<a&&(n=i[r.index])}return n},afterTitle:V.noop,beforeBody:V.noop,beforeLabel:V.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n&&(n+=": "),V.isNullOrUndef(t.value)?n+=t.yLabel:n+=t.value,n},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:V.noop,afterBody:V.noop,beforeFooter:V.noop,footer:V.noop,afterFooter:V.noop}}});var Ne={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:i/r,y:a/r}},nearest:function(t,e){var n,i,a,r=e.x,o=e.y,s=Number.POSITIVE_INFINITY;for(n=0,i=t.length;n<i;++n){var l=t[n];if(l&&l.hasValue()){var u=l.getCenterPoint(),d=V.distanceBetweenPoints(e,u);d<s&&(s=d,a=l)}}if(a){var h=a.tooltipPosition();r=h.x,o=h.y}return{x:r,y:o}}};function Be(t,e){return e&&(V.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function Ee(t){return("string"==typeof t||t instanceof String)&&t.indexOf("\n")>-1?t.split("\n"):t}function We(t){var e=z.global;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,rtl:t.rtl,textDirection:t.textDirection,bodyFontColor:t.bodyFontColor,_bodyFontFamily:Re(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:Re(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:Re(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:Re(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:Re(t.titleFontStyle,e.defaultFontStyle),titleFontSize:Re(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:Re(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:Re(t.footerFontStyle,e.defaultFontStyle),footerFontSize:Re(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 Ve(t,e){return"center"===e?t.x+t.width/2:"right"===e?t.x+t.width-t.xPadding:t.x+t.xPadding}function He(t){return Be([],Ee(t))}var je=X.extend({initialize:function(){this._model=We(this._options),this._lastActive=[]},getTitle:function(){var t=this,e=t._options,n=e.callbacks,i=n.beforeTitle.apply(t,arguments),a=n.title.apply(t,arguments),r=n.afterTitle.apply(t,arguments),o=[];return o=Be(o,Ee(i)),o=Be(o,Ee(a)),o=Be(o,Ee(r))},getBeforeBody:function(){return He(this._options.callbacks.beforeBody.apply(this,arguments))},getBody:function(t,e){var n=this,i=n._options.callbacks,a=[];return V.each(t,(function(t){var r={before:[],lines:[],after:[]};Be(r.before,Ee(i.beforeLabel.call(n,t,e))),Be(r.lines,i.label.call(n,t,e)),Be(r.after,Ee(i.afterLabel.call(n,t,e))),a.push(r)})),a},getAfterBody:function(){return He(this._options.callbacks.afterBody.apply(this,arguments))},getFooter:function(){var t=this,e=t._options.callbacks,n=e.beforeFooter.apply(t,arguments),i=e.footer.apply(t,arguments),a=e.afterFooter.apply(t,arguments),r=[];return r=Be(r,Ee(n)),r=Be(r,Ee(i)),r=Be(r,Ee(a))},update:function(t){var e,n,i,a,r,o,s,l,u,d,h=this,c=h._options,f=h._model,g=h._model=We(c),p=h._active,m=h._data,v={xAlign:f.xAlign,yAlign:f.yAlign},b={x:f.x,y:f.y},x={width:f.width,height:f.height},y={x:f.caretX,y:f.caretY};if(p.length){g.opacity=1;var _=[],k=[];y=Ne[c.position].call(h,p,h._eventPosition);var w=[];for(e=0,n=p.length;e<n;++e)w.push((i=p[e],a=void 0,r=void 0,o=void 0,s=void 0,l=void 0,u=void 0,d=void 0,a=i._xScale,r=i._yScale||i._scale,o=i._index,s=i._datasetIndex,l=i._chart.getDatasetMeta(s).controller,u=l._getIndexScale(),d=l._getValueScale(),{xLabel:a?a.getLabelForIndex(o,s):"",yLabel:r?r.getLabelForIndex(o,s):"",label:u?""+u.getLabelForIndex(o,s):"",value:d?""+d.getLabelForIndex(o,s):"",index:o,datasetIndex:s,x:i._model.x,y:i._model.y}));c.filter&&(w=w.filter((function(t){return c.filter(t,m)}))),c.itemSort&&(w=w.sort((function(t,e){return c.itemSort(t,e,m)}))),V.each(w,(function(t){_.push(c.callbacks.labelColor.call(h,t,h._chart)),k.push(c.callbacks.labelTextColor.call(h,t,h._chart))})),g.title=h.getTitle(w,m),g.beforeBody=h.getBeforeBody(w,m),g.body=h.getBody(w,m),g.afterBody=h.getAfterBody(w,m),g.footer=h.getFooter(w,m),g.x=y.x,g.y=y.y,g.caretPadding=c.caretPadding,g.labelColors=_,g.labelTextColors=k,g.dataPoints=w,x=function(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,r=e.body,o=r.reduce((function(t,e){return t+e.before.length+e.lines.length+e.after.length}),0);o+=e.beforeBody.length+e.afterBody.length;var s=e.title.length,l=e.footer.length,u=e.titleFontSize,d=e.bodyFontSize,h=e.footerFontSize;i+=s*u,i+=s?(s-1)*e.titleSpacing:0,i+=s?e.titleMarginBottom:0,i+=o*d,i+=o?(o-1)*e.bodySpacing:0,i+=l?e.footerMarginTop:0,i+=l*h,i+=l?(l-1)*e.footerSpacing:0;var c=0,f=function(t){a=Math.max(a,n.measureText(t).width+c)};return n.font=V.fontString(u,e._titleFontStyle,e._titleFontFamily),V.each(e.title,f),n.font=V.fontString(d,e._bodyFontStyle,e._bodyFontFamily),V.each(e.beforeBody.concat(e.afterBody),f),c=e.displayColors?d+2:0,V.each(r,(function(t){V.each(t.before,f),V.each(t.lines,f),V.each(t.after,f)})),c=0,n.font=V.fontString(h,e._footerFontStyle,e._footerFontFamily),V.each(e.footer,f),{width:a+=2*e.xPadding,height:i}}(this,g),b=function(t,e,n,i){var a=t.x,r=t.y,o=t.caretSize,s=t.caretPadding,l=t.cornerRadius,u=n.xAlign,d=n.yAlign,h=o+s,c=l+s;return"right"===u?a-=e.width:"center"===u&&((a-=e.width/2)+e.width>i.width&&(a=i.width-e.width),a<0&&(a=0)),"top"===d?r+=h:r-="bottom"===d?e.height+h:e.height/2,"center"===d?"left"===u?a+=h:"right"===u&&(a-=h):"left"===u?a-=c:"right"===u&&(a+=c),{x:a,y:r}}(g,x,v=function(t,e){var n,i,a,r,o,s=t._model,l=t._chart,u=t._chart.chartArea,d="center",h="center";s.y<e.height?h="top":s.y>l.height-e.height&&(h="bottom");var c=(u.left+u.right)/2,f=(u.top+u.bottom)/2;"center"===h?(n=function(t){return t<=c},i=function(t){return t>c}):(n=function(t){return t<=e.width/2},i=function(t){return t>=l.width-e.width/2}),a=function(t){return t+e.width+s.caretSize+s.caretPadding>l.width},r=function(t){return t-e.width-s.caretSize-s.caretPadding<0},o=function(t){return t<=f?"top":"bottom"},n(s.x)?(d="left",a(s.x)&&(d="center",h=o(s.y))):i(s.x)&&(d="right",r(s.x)&&(d="center",h=o(s.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:d,yAlign:g.yAlign?g.yAlign:h}}(this,x),h._chart)}else g.opacity=0;return g.xAlign=v.xAlign,g.yAlign=v.yAlign,g.x=b.x,g.y=b.y,g.width=x.width,g.height=x.height,g.caretX=y.x,g.caretY=y.y,h._model=g,t&&c.custom&&c.custom.call(h,g),h},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,h=n.xAlign,c=n.yAlign,f=t.x,g=t.y,p=e.width,m=e.height;if("center"===c)s=g+m/2,"left"===h?(a=(i=f)-u,r=i,o=s+u,l=s-u):(a=(i=f+p)+u,r=i,o=s-u,l=s+u);else if("left"===h?(i=(a=f+d+u)-u,r=a+u):"right"===h?(i=(a=f+p-d-u)-u,r=a+u):(i=(a=n.caretX)-u,r=a+u),"top"===c)s=(o=g)-u,l=o;else{s=(o=g+m)+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,e,n){var i,a,r,o=e.title,s=o.length;if(s){var l=ze(e.rtl,e.x,e.width);for(t.x=Ve(e,e._titleAlign),n.textAlign=l.textAlign(e._titleAlign),n.textBaseline="middle",i=e.titleFontSize,a=e.titleSpacing,n.fillStyle=e.titleFontColor,n.font=V.fontString(i,e._titleFontStyle,e._titleFontFamily),r=0;r<s;++r)n.fillText(o[r],l.x(t.x),t.y+i/2),t.y+=i+a,r+1===s&&(t.y+=e.titleMarginBottom-a)}},drawBody:function(t,e,n){var i,a,r,o,s,l,u,d,h=e.bodyFontSize,c=e.bodySpacing,f=e._bodyAlign,g=e.body,p=e.displayColors,m=0,v=p?Ve(e,"left"):0,b=ze(e.rtl,e.x,e.width),x=function(e){n.fillText(e,b.x(t.x+m),t.y+h/2),t.y+=h+c},y=b.textAlign(f);for(n.textAlign=f,n.textBaseline="middle",n.font=V.fontString(h,e._bodyFontStyle,e._bodyFontFamily),t.x=Ve(e,y),n.fillStyle=e.bodyFontColor,V.each(e.beforeBody,x),m=p&&"right"!==y?"center"===f?h/2+1:h+2:0,s=0,u=g.length;s<u;++s){for(i=g[s],a=e.labelTextColors[s],r=e.labelColors[s],n.fillStyle=a,V.each(i.before,x),l=0,d=(o=i.lines).length;l<d;++l){if(p){var _=b.x(v);n.fillStyle=e.legendColorBackground,n.fillRect(b.leftForLtr(_,h),t.y,h,h),n.lineWidth=1,n.strokeStyle=r.borderColor,n.strokeRect(b.leftForLtr(_,h),t.y,h,h),n.fillStyle=r.backgroundColor,n.fillRect(b.leftForLtr(b.xPlus(_,1),h-2),t.y+1,h-2,h-2),n.fillStyle=a}x(o[l])}V.each(i.after,x)}m=0,V.each(e.afterBody,x),t.y-=c},drawFooter:function(t,e,n){var i,a,r=e.footer,o=r.length;if(o){var s=ze(e.rtl,e.x,e.width);for(t.x=Ve(e,e._footerAlign),t.y+=e.footerMarginTop,n.textAlign=s.textAlign(e._footerAlign),n.textBaseline="middle",i=e.footerFontSize,n.fillStyle=e.footerFontColor,n.font=V.fontString(i,e._footerFontStyle,e._footerFontFamily),a=0;a<o;++a)n.fillText(r[a],s.x(t.x),t.y+i/2),t.y+=i+e.footerSpacing}},drawBackground:function(t,e,n,i){n.fillStyle=e.backgroundColor,n.strokeStyle=e.borderColor,n.lineWidth=e.borderWidth;var a=e.xAlign,r=e.yAlign,o=t.x,s=t.y,l=i.width,u=i.height,d=e.cornerRadius;n.beginPath(),n.moveTo(o+d,s),"top"===r&&this.drawCaret(t,i),n.lineTo(o+l-d,s),n.quadraticCurveTo(o+l,s,o+l,s+d),"center"===r&&"right"===a&&this.drawCaret(t,i),n.lineTo(o+l,s+u-d),n.quadraticCurveTo(o+l,s+u,o+l-d,s+u),"bottom"===r&&this.drawCaret(t,i),n.lineTo(o+d,s+u),n.quadraticCurveTo(o,s+u,o,s+u-d),"center"===r&&"left"===a&&this.drawCaret(t,i),n.lineTo(o,s+d),n.quadraticCurveTo(o,s,o+d,s),n.closePath(),n.fill(),e.borderWidth>0&&n.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&&(t.save(),t.globalAlpha=a,this.drawBackground(i,e,t,n),i.y+=e.yPadding,V.rtl.overrideTextDirection(t,e.textDirection),this.drawTitle(i,e,t),this.drawBody(i,e,t),this.drawFooter(i,e,t),V.rtl.restoreTextDirection(t,e.textDirection),t.restore())}},handleEvent:function(t){var e,n=this,i=n._options;return n._lastActive=n._lastActive||[],"mouseout"===t.type?n._active=[]:(n._active=n._chart.getElementsAtEventForMode(t,i.mode,i),i.reverse&&n._active.reverse()),(e=!V.arrayEquals(n._active,n._lastActive))&&(n._lastActive=n._active,(i.enabled||i.custom)&&(n._eventPosition={x:t.x,y:t.y},n.update(!0),n.pivot())),e}}),qe=Ne,Ue=je;Ue.positioners=qe;var Ye=V.valueOrDefault;function Ge(){return V.merge({},[].slice.call(arguments),{merger:function(t,e,n,i){if("xAxes"===t||"yAxes"===t){var a,r,o,s=n[t].length;for(e[t]||(e[t]=[]),a=0;a<s;++a)o=n[t][a],r=Ye(o.type,"xAxes"===t?"category":"linear"),a>=e[t].length&&e[t].push({}),!e[t][a].type||o.type&&o.type!==e[t][a].type?V.merge(e[t][a],[Oe.getScaleDefaults(r),o]):V.merge(e[t][a],o)}else V._merger(t,e,n,i)}})}function Xe(){return V.merge({},[].slice.call(arguments),{merger:function(t,e,n,i){var a=e[t]||{},r=n[t];"scales"===t?e[t]=Ge(a,r):"scale"===t?e[t]=V.merge(a,[Oe.getScaleDefaults(r.type),r]):V._merger(t,e,n,i)}})}function Ke(t){var e=t.options;V.each(t.scales,(function(e){ge.removeBox(t,e)})),e=Xe(z.global,z[t.config.type],e),t.options=t.config.options=e,t.ensureScalesHaveIDs(),t.buildOrUpdateScales(),t.tooltip._options=e.tooltips,t.tooltip.initialize()}function Ze(t,e,n){var i,a=function(t){return t.id===i};do{i=e+n++}while(V.findIndex(t,a)>=0);return i}function $e(t){return"top"===t||"bottom"===t}function Je(t,e){return function(n,i){return n[t]===i[t]?n[e]-i[e]:n[t]-i[t]}}z._set("global",{elements:{},events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,maintainAspectRatio:!0,responsive:!0,responsiveAnimationDuration:0});var Qe=function(t,e){return this.construct(t,e),this};V.extend(Qe.prototype,{construct:function(t,e){var n=this;e=function(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=Xe(z.global,z[t.type],t.options||{}),t}(e);var i=Fe.acquireContext(t,e),a=i&&i.canvas,r=a&&a.height,o=a&&a.width;n.id=V.uid(),n.ctx=i,n.canvas=a,n.config=e,n.width=o,n.height=r,n.aspectRatio=r?o/r:null,n.options=e.options,n._bufferedRender=!1,n._layers=[],n.chart=n,n.controller=n,Qe.instances[n.id]=n,Object.defineProperty(n,"data",{get:function(){return n.config.data},set:function(t){n.config.data=t}}),i&&a?(n.initialize(),n.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return Le.notify(t,"beforeInit"),V.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.initToolTip(),Le.notify(t,"afterInit"),t},clear:function(){return V.canvas.clear(this),this},stop:function(){return $.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,a=n.maintainAspectRatio&&e.aspectRatio||null,r=Math.max(0,Math.floor(V.getMaximumWidth(i))),o=Math.max(0,Math.floor(a?r/a:V.getMaximumHeight(i)));if((e.width!==r||e.height!==o)&&(i.width=e.width=r,i.height=e.height=o,i.style.width=r+"px",i.style.height=o+"px",V.retinaScale(e,n.devicePixelRatio),!t)){var s={width:r,height:o};Le.notify(e,"resize",[s]),n.onResize&&n.onResize(e,s),e.stop(),e.update({duration:n.responsiveAnimationDuration})}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;V.each(e.xAxes,(function(t,n){t.id||(t.id=Ze(e.xAxes,"x-axis-",n))})),V.each(e.yAxes,(function(t,n){t.id||(t.id=Ze(e.yAxes,"y-axis-",n))})),n&&(n.id=n.id||"scale")},buildOrUpdateScales:function(){var t=this,e=t.options,n=t.scales||{},i=[],a=Object.keys(n).reduce((function(t,e){return t[e]=!1,t}),{});e.scales&&(i=i.concat((e.scales.xAxes||[]).map((function(t){return{options:t,dtype:"category",dposition:"bottom"}})),(e.scales.yAxes||[]).map((function(t){return{options:t,dtype:"linear",dposition:"left"}})))),e.scale&&i.push({options:e.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),V.each(i,(function(e){var i=e.options,r=i.id,o=Ye(i.type,e.dtype);$e(i.position)!==$e(e.dposition)&&(i.position=e.dposition),a[r]=!0;var s=null;if(r in n&&n[r].type===o)(s=n[r]).options=i,s.ctx=t.ctx,s.chart=t;else{var l=Oe.getScaleConstructor(o);if(!l)return;s=new l({id:r,type:o,options:i,ctx:t.ctx,chart:t}),n[s.id]=s}s.mergeTicksOptions(),e.isDefault&&(t.scale=s)})),V.each(a,(function(t,e){t||delete n[e]})),t.scales=n,Oe.addScalesToLayout(this)},buildOrUpdateControllers:function(){var t,e,n=this,i=[],a=n.data.datasets;for(t=0,e=a.length;t<e;t++){var r=a[t],o=n.getDatasetMeta(t),s=r.type||n.config.type;if(o.type&&o.type!==s&&(n.destroyDatasetMeta(t),o=n.getDatasetMeta(t)),o.type=s,o.order=r.order||0,o.index=t,o.controller)o.controller.updateIndex(t),o.controller.linkScales();else{var l=$t[o.type];if(void 0===l)throw new Error('"'+o.type+'" is not a chart type.');o.controller=new l(n,t),i.push(o.controller)}}return i},resetElements:function(){var t=this;V.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,n,i=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),Ke(i),Le._invalidate(i),!1!==Le.notify(i,"beforeUpdate")){i.tooltip._data=i.data;var a=i.buildOrUpdateControllers();for(e=0,n=i.data.datasets.length;e<n;e++)i.getDatasetMeta(e).controller.buildOrUpdateElements();i.updateLayout(),i.options.animation&&i.options.animation.duration&&V.each(a,(function(t){t.reset()})),i.updateDatasets(),i.tooltip.initialize(),i.lastActive=[],Le.notify(i,"afterUpdate"),i._layers.sort(Je("z","_idx")),i._bufferedRender?i._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:i.render(t)}},updateLayout:function(){var t=this;!1!==Le.notify(t,"beforeLayout")&&(ge.update(this,this.width,this.height),t._layers=[],V.each(t.boxes,(function(e){e._configure&&e._configure(),t._layers.push.apply(t._layers,e._layers())}),t),t._layers.forEach((function(t,e){t._idx=e})),Le.notify(t,"afterScaleUpdate"),Le.notify(t,"afterLayout"))},updateDatasets:function(){if(!1!==Le.notify(this,"beforeDatasetsUpdate")){for(var t=0,e=this.data.datasets.length;t<e;++t)this.updateDataset(t);Le.notify(this,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this.getDatasetMeta(t),n={meta:e,index:t};!1!==Le.notify(this,"beforeDatasetUpdate",[n])&&(e.controller._update(),Le.notify(this,"afterDatasetUpdate",[n]))},render:function(t){var e=this;t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]});var n=e.options.animation,i=Ye(t.duration,n&&n.duration),a=t.lazy;if(!1!==Le.notify(e,"beforeRender")){var r=function(t){Le.notify(e,"afterRender"),V.callback(n&&n.onComplete,[t],e)};if(n&&i){var o=new Z({numSteps:i/16.66,easing:t.easing||n.easing,render:function(t,e){var n=V.easing.effects[e.easing],i=e.currentStep,a=i/e.numSteps;t.draw(n(a),a,i)},onAnimationProgress:n.onProgress,onAnimationComplete:r});$.addAnimation(e,o,i,a)}else e.draw(),r(new Z({numSteps:0,chart:e}));return e}},draw:function(t){var e,n,i=this;if(i.clear(),V.isNullOrUndef(t)&&(t=1),i.transition(t),!(i.width<=0||i.height<=0)&&!1!==Le.notify(i,"beforeDraw",[t])){for(n=i._layers,e=0;e<n.length&&n[e].z<=0;++e)n[e].draw(i.chartArea);for(i.drawDatasets(t);e<n.length;++e)n[e].draw(i.chartArea);i._drawTooltip(t),Le.notify(i,"afterDraw",[t])}},transition:function(t){for(var e=0,n=(this.data.datasets||[]).length;e<n;++e)this.isDatasetVisible(e)&&this.getDatasetMeta(e).controller.transition(t);this.tooltip.transition(t)},_getSortedDatasetMetas:function(t){var e,n,i=[];for(e=0,n=(this.data.datasets||[]).length;e<n;++e)t&&!this.isDatasetVisible(e)||i.push(this.getDatasetMeta(e));return i.sort(Je("order","index")),i},_getSortedVisibleDatasetMetas:function(){return this._getSortedDatasetMetas(!0)},drawDatasets:function(t){var e,n;if(!1!==Le.notify(this,"beforeDatasetsDraw",[t])){for(n=(e=this._getSortedVisibleDatasetMetas()).length-1;n>=0;--n)this.drawDataset(e[n],t);Le.notify(this,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n={meta:t,index:t.index,easingValue:e};!1!==Le.notify(this,"beforeDatasetDraw",[n])&&(t.controller.draw(e),Le.notify(this,"afterDatasetDraw",[n]))},_drawTooltip:function(t){var e=this.tooltip,n={tooltip:e,easingValue:t};!1!==Le.notify(this,"beforeTooltipDraw",[n])&&(e.draw(),Le.notify(this,"afterTooltipDraw",[n]))},getElementAtEvent:function(t){return ae.modes.single(this,t)},getElementsAtEvent:function(t){return ae.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return ae.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=ae.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return ae.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this.data.datasets[t];e._meta||(e._meta={});var n=e._meta[this.id];return n||(n=e._meta[this.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:e.order||0,index:t}),n},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 t,e,n=this,i=n.canvas;for(n.stop(),t=0,e=n.data.datasets.length;t<e;++t)n.destroyDatasetMeta(t);i&&(n.unbindEvents(),V.canvas.clear(n),Fe.releaseContext(n.ctx),n.canvas=null,n.ctx=null),Le.notify(n,"destroy"),delete Qe.instances[n.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var t=this;t.tooltip=new Ue({_chart:t,_chartInstance:t,_data:t.data,_options:t.options.tooltips},t)},bindEvents:function(){var t=this,e=t._listeners={},n=function(){t.eventHandler.apply(t,arguments)};V.each(t.options.events,(function(i){Fe.addEventListener(t,i,n),e[i]=n})),t.options.responsive&&(n=function(){t.resize()},Fe.addEventListener(t,"resize",n),e.resize=n)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,V.each(e,(function(e,n){Fe.removeEventListener(t,n,e)})))},updateHoverStyle:function(t,e,n){var i,a,r,o=n?"set":"remove";for(a=0,r=t.length;a<r;++a)(i=t[a])&&this.getDatasetMeta(i._datasetIndex).controller[o+"HoverStyle"](i);"dataset"===e&&this.getDatasetMeta(t[0]._datasetIndex).controller["_"+o+"DatasetHoverStyle"]()},eventHandler:function(t){var e=this,n=e.tooltip;if(!1!==Le.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var i=e.handleEvent(t);n&&(i=n._start?n.handleEvent(t):i|n.handleEvent(t)),Le.notify(e,"afterEvent",[t]);var a=e._bufferedRequest;return a?e.render(a):i&&!e.animating&&(e.stop(),e.render({duration:e.options.hover.animationDuration,lazy:!0})),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e,n=this,i=n.options||{},a=i.hover;return n.lastActive=n.lastActive||[],"mouseout"===t.type?n.active=[]:n.active=n.getElementsAtEventForMode(t,a.mode,a),V.callback(i.onHover||i.hover.onHover,[t.native,n.active],n),"mouseup"!==t.type&&"click"!==t.type||i.onClick&&i.onClick.call(n,t.native,n.active),n.lastActive.length&&n.updateHoverStyle(n.lastActive,a.mode,!1),n.active.length&&a.mode&&n.updateHoverStyle(n.active,a.mode,!0),e=!V.arrayEquals(n.active,n.lastActive),n.lastActive=n.active,e}}),Qe.instances={};var tn=Qe;Qe.Controller=Qe,Qe.types={},V.configMerge=Xe,V.scaleMerge=Ge;function en(){throw new Error("This method is not implemented: either no adapter can be found or an incomplete integration was provided.")}function nn(t){this.options=t||{}}V.extend(nn.prototype,{formats:en,parse:en,format:en,add:en,diff:en,startOf:en,endOf:en,_create:function(t){return t}}),nn.override=function(t){V.extend(nn.prototype,t)};var an={_date:nn},rn={formatters:{values:function(t){return V.isArray(t)?t:""+t},linear:function(t,e,n){var i=n.length>3?n[2]-n[1]:n[1]-n[0];Math.abs(i)>1&&t!==Math.floor(t)&&(i=t-Math.floor(t));var a=V.log10(Math.abs(i)),r="";if(0!==t)if(Math.max(Math.abs(n[0]),Math.abs(n[n.length-1]))<1e-4){var o=V.log10(Math.abs(t)),s=Math.floor(o)-Math.floor(a);s=Math.max(Math.min(s,20),0),r=t.toExponential(s)}else{var l=-1*Math.floor(a);l=Math.max(Math.min(l,20),0),r=t.toFixed(l)}else r="0";return r},logarithmic:function(t,e,n){var i=t/Math.pow(10,Math.floor(V.log10(t)));return 0===t?"0":1===i||2===i||5===i||0===e||e===n.length-1?t.toExponential():""}}},on=V.isArray,sn=V.isNullOrUndef,ln=V.valueOrDefault,un=V.valueAtIndexOrDefault;function dn(t,e,n){var i,a=t.getTicks().length,r=Math.min(e,a-1),o=t.getPixelForTick(r),s=t._startPixel,l=t._endPixel;if(!(n&&(i=1===a?Math.max(o-s,l-o):0===e?(t.getPixelForTick(1)-o)/2:(o-t.getPixelForTick(r-1))/2,(o+=r<e?i:-i)<s-1e-6||o>l+1e-6)))return o}function hn(t,e,n,i){var a,r,o,s,l,u,d,h,c,f,g,p,m,v=n.length,b=[],x=[],y=[];for(a=0;a<v;++a){if(s=n[a].label,l=n[a].major?e.major:e.minor,t.font=u=l.string,d=i[u]=i[u]||{data:{},gc:[]},h=l.lineHeight,c=f=0,sn(s)||on(s)){if(on(s))for(r=0,o=s.length;r<o;++r)g=s[r],sn(g)||on(g)||(c=V.measureText(t,d.data,d.gc,c,g),f+=h)}else c=V.measureText(t,d.data,d.gc,c,s),f=h;b.push(c),x.push(f),y.push(h/2)}function _(t){return{width:b[t]||0,height:x[t]||0,offset:y[t]||0}}return function(t,e){V.each(t,(function(t){var n,i=t.gc,a=i.length/2;if(a>e){for(n=0;n<a;++n)delete t.data[i[n]];i.splice(0,a)}}))}(i,v),p=b.indexOf(Math.max.apply(null,b)),m=x.indexOf(Math.max.apply(null,x)),{first:_(0),last:_(v-1),widest:_(p),highest:_(m)}}function cn(t){return t.drawTicks?t.tickMarkLength:0}function fn(t){var e,n;return t.display?(e=V.options._parseFont(t),n=V.options.toPadding(t.padding),e.lineHeight+n.height):0}function gn(t,e){return V.extend(V.options._parseFont({fontFamily:ln(e.fontFamily,t.fontFamily),fontSize:ln(e.fontSize,t.fontSize),fontStyle:ln(e.fontStyle,t.fontStyle),lineHeight:ln(e.lineHeight,t.lineHeight)}),{color:V.options.resolve([e.fontColor,t.fontColor,z.global.defaultFontColor])})}function pn(t){var e=gn(t,t.minor);return{minor:e,major:t.major.enabled?gn(t,t.major):e}}function mn(t){var e,n,i,a=[];for(n=0,i=t.length;n<i;++n)void 0!==(e=t[n])._index&&a.push(e);return a}function vn(t,e,n,i){var a,r,o,s,l=ln(n,0),u=Math.min(ln(i,t.length),t.length),d=0;for(e=Math.ceil(e),i&&(e=(a=i-n)/Math.floor(a/e)),s=l;s<0;)d++,s=Math.round(l+d*e);for(r=Math.max(l,0);r<u;r++)o=t[r],r===s?(o._index=r,d++,s=Math.round(l+d*e)):delete o.label}z._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:"",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:rn.formatters.values,minor:{},major:{}}});var bn=X.extend({zeroLineIndex:0,getPadding:function(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}},getTicks:function(){return this._ticks},_getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels||[]},mergeTicksOptions:function(){},beforeUpdate:function(){V.callback(this.options.beforeUpdate,[this])},update:function(t,e,n){var i,a,r,o,s,l=this,u=l.options.ticks,d=u.sampleSize;if(l.beforeUpdate(),l.maxWidth=t,l.maxHeight=e,l.margins=V.extend({left:0,right:0,top:0,bottom:0},n),l._ticks=null,l.ticks=null,l._labelSizes=null,l._maxLabelLines=0,l.longestLabelWidth=0,l.longestTextCache=l.longestTextCache||{},l._gridLineItems=null,l._labelItems=null,l.beforeSetDimensions(),l.setDimensions(),l.afterSetDimensions(),l.beforeDataLimits(),l.determineDataLimits(),l.afterDataLimits(),l.beforeBuildTicks(),o=l.buildTicks()||[],(!(o=l.afterBuildTicks(o)||o)||!o.length)&&l.ticks)for(o=[],i=0,a=l.ticks.length;i<a;++i)o.push({value:l.ticks[i],major:!1});return l._ticks=o,s=d<o.length,r=l._convertTicksToLabels(s?function(t,e){for(var n=[],i=t.length/e,a=0,r=t.length;a<r;a+=i)n.push(t[Math.floor(a)]);return n}(o,d):o),l._configure(),l.beforeCalculateTickRotation(),l.calculateTickRotation(),l.afterCalculateTickRotation(),l.beforeFit(),l.fit(),l.afterFit(),l._ticksToDraw=u.display&&(u.autoSkip||"auto"===u.source)?l._autoSkip(o):o,s&&(r=l._convertTicksToLabels(l._ticksToDraw)),l.ticks=r,l.afterUpdate(),l.minSize},_configure:function(){var t,e,n=this,i=n.options.ticks.reverse;n.isHorizontal()?(t=n.left,e=n.right):(t=n.top,e=n.bottom,i=!i),n._startPixel=t,n._endPixel=e,n._reversePixels=i,n._length=e-t},afterUpdate:function(){V.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){V.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(){V.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){V.callback(this.options.beforeDataLimits,[this])},determineDataLimits:V.noop,afterDataLimits:function(){V.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){V.callback(this.options.beforeBuildTicks,[this])},buildTicks:V.noop,afterBuildTicks:function(t){var e=this;return on(t)&&t.length?V.callback(e.options.afterBuildTicks,[e,t]):(e.ticks=V.callback(e.options.afterBuildTicks,[e,e.ticks])||e.ticks,t)},beforeTickToLabelConversion:function(){V.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this.options.ticks;this.ticks=this.ticks.map(t.userCallback||t.callback,this)},afterTickToLabelConversion:function(){V.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){V.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t,e,n,i,a,r,o,s=this,l=s.options,u=l.ticks,d=s.getTicks().length,h=u.minRotation||0,c=u.maxRotation,f=h;!s._isVisible()||!u.display||h>=c||d<=1||!s.isHorizontal()?s.labelRotation=h:(e=(t=s._getLabelSizes()).widest.width,n=t.highest.height-t.highest.offset,i=Math.min(s.maxWidth,s.chart.width-e),e+6>(a=l.offset?s.maxWidth/d:i/(d-1))&&(a=i/(d-(l.offset?.5:1)),r=s.maxHeight-cn(l.gridLines)-u.padding-fn(l.scaleLabel),o=Math.sqrt(e*e+n*n),f=V.toDegrees(Math.min(Math.asin(Math.min((t.highest.height+6)/a,1)),Math.asin(Math.min(r/o,1))-Math.asin(n/o))),f=Math.max(h,Math.min(c,f))),s.labelRotation=f)},afterCalculateTickRotation:function(){V.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){V.callback(this.options.beforeFit,[this])},fit:function(){var t=this,e=t.minSize={width:0,height:0},n=t.chart,i=t.options,a=i.ticks,r=i.scaleLabel,o=i.gridLines,s=t._isVisible(),l="bottom"===i.position,u=t.isHorizontal();if(u?e.width=t.maxWidth:s&&(e.width=cn(o)+fn(r)),u?s&&(e.height=cn(o)+fn(r)):e.height=t.maxHeight,a.display&&s){var d=pn(a),h=t._getLabelSizes(),c=h.first,f=h.last,g=h.widest,p=h.highest,m=.4*d.minor.lineHeight,v=a.padding;if(u){var b=0!==t.labelRotation,x=V.toRadians(t.labelRotation),y=Math.cos(x),_=Math.sin(x),k=_*g.width+y*(p.height-(b?p.offset:0))+(b?0:m);e.height=Math.min(t.maxHeight,e.height+k+v);var w,M,S=t.getPixelForTick(0)-t.left,C=t.right-t.getPixelForTick(t.getTicks().length-1);b?(w=l?y*c.width+_*c.offset:_*(c.height-c.offset),M=l?_*(f.height-f.offset):y*f.width+_*f.offset):(w=c.width/2,M=f.width/2),t.paddingLeft=Math.max((w-S)*t.width/(t.width-S),0)+3,t.paddingRight=Math.max((M-C)*t.width/(t.width-C),0)+3}else{var P=a.mirror?0:g.width+v+m;e.width=Math.min(t.maxWidth,e.width+P),t.paddingTop=c.height/2,t.paddingBottom=f.height/2}}t.handleMargins(),u?(t.width=t._length=n.width-t.margins.left-t.margins.right,t.height=e.height):(t.width=e.width,t.height=t._length=n.height-t.margins.top-t.margins.bottom)},handleMargins:function(){var t=this;t.margins&&(t.margins.left=Math.max(t.paddingLeft,t.margins.left),t.margins.top=Math.max(t.paddingTop,t.margins.top),t.margins.right=Math.max(t.paddingRight,t.margins.right),t.margins.bottom=Math.max(t.paddingBottom,t.margins.bottom))},afterFit:function(){V.callback(this.options.afterFit,[this])},isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(sn(t))return NaN;if(("number"==typeof t||t instanceof Number)&&!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},_convertTicksToLabels:function(t){var e,n,i,a=this;for(a.ticks=t.map((function(t){return t.value})),a.beforeTickToLabelConversion(),e=a.convertTicksToLabels(t)||a.ticks,a.afterTickToLabelConversion(),n=0,i=t.length;n<i;++n)t[n].label=e[n];return e},_getLabelSizes:function(){var t=this,e=t._labelSizes;return e||(t._labelSizes=e=hn(t.ctx,pn(t.options.ticks),t.getTicks(),t.longestTextCache),t.longestLabelWidth=e.widest.width),e},_parseValue:function(t){var e,n,i,a;return on(t)?(e=+this.getRightValue(t[0]),n=+this.getRightValue(t[1]),i=Math.min(e,n),a=Math.max(e,n)):(e=void 0,n=t=+this.getRightValue(t),i=t,a=t),{min:i,max:a,start:e,end:n}},_getScaleLabel:function(t){var e=this._parseValue(t);return void 0!==e.start?"["+e.start+", "+e.end+"]":+this.getRightValue(t)},getLabelForIndex:V.noop,getPixelForValue:V.noop,getValueForPixel:V.noop,getPixelForTick:function(t){var e=this.options.offset,n=this._ticks.length,i=1/Math.max(n-(e?0:1),1);return t<0||t>n-1?null:this.getPixelForDecimal(t*i+(e?i/2:0))},getPixelForDecimal:function(t){return this._reversePixels&&(t=1-t),this._startPixel+t*this._length},getDecimalForPixel:function(t){var e=(t-this._startPixel)/this._length;return this._reversePixels?1-e:e},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this.min,e=this.max;return this.beginAtZero?0:t<0&&e<0?e:t>0&&e>0?t:0},_autoSkip:function(t){var e,n,i,a,r=this.options.ticks,o=this._length,s=r.maxTicksLimit||o/this._tickSize()+1,l=r.major.enabled?function(t){var e,n,i=[];for(e=0,n=t.length;e<n;e++)t[e].major&&i.push(e);return i}(t):[],u=l.length,d=l[0],h=l[u-1];if(u>s)return function(t,e,n){var i,a,r=0,o=e[0];for(n=Math.ceil(n),i=0;i<t.length;i++)a=t[i],i===o?(a._index=i,o=e[++r*n]):delete a.label}(t,l,u/s),mn(t);if(i=function(t,e,n,i){var a,r,o,s,l=function(t){var e,n,i=t.length;if(i<2)return!1;for(n=t[0],e=1;e<i;++e)if(t[e]-t[e-1]!==n)return!1;return n}(t),u=(e.length-1)/i;if(!l)return Math.max(u,1);for(o=0,s=(a=V.math._factorize(l)).length-1;o<s;o++)if((r=a[o])>u)return r;return Math.max(u,1)}(l,t,0,s),u>0){for(e=0,n=u-1;e<n;e++)vn(t,i,l[e],l[e+1]);return a=u>1?(h-d)/(u-1):null,vn(t,i,V.isNullOrUndef(a)?0:d-a,d),vn(t,i,h,V.isNullOrUndef(a)?t.length:h+a),mn(t)}return vn(t,i),mn(t)},_tickSize:function(){var t=this.options.ticks,e=V.toRadians(this.labelRotation),n=Math.abs(Math.cos(e)),i=Math.abs(Math.sin(e)),a=this._getLabelSizes(),r=t.autoSkipPadding||0,o=a?a.widest.width+r:0,s=a?a.highest.height+r:0;return this.isHorizontal()?s*n>o*i?o/n:s/i:s*i<o*n?s/n:o/i},_isVisible:function(){var t,e,n,i=this.chart,a=this.options.display;if("auto"!==a)return!!a;for(t=0,e=i.data.datasets.length;t<e;++t)if(i.isDatasetVisible(t)&&((n=i.getDatasetMeta(t)).xAxisID===this.id||n.yAxisID===this.id))return!0;return!1},_computeGridLineItems:function(t){var e,n,i,a,r,o,s,l,u,d,h,c,f,g,p,m,v,b=this,x=b.chart,y=b.options,_=y.gridLines,k=y.position,w=_.offsetGridLines,M=b.isHorizontal(),S=b._ticksToDraw,C=S.length+(w?1:0),P=cn(_),A=[],D=_.drawBorder?un(_.lineWidth,0,0):0,T=D/2,I=V._alignPixel,F=function(t){return I(x,t,D)};for("top"===k?(e=F(b.bottom),s=b.bottom-P,u=e-T,h=F(t.top)+T,f=t.bottom):"bottom"===k?(e=F(b.top),h=t.top,f=F(t.bottom)-T,s=e+T,u=b.top+P):"left"===k?(e=F(b.right),o=b.right-P,l=e-T,d=F(t.left)+T,c=t.right):(e=F(b.left),d=t.left,c=F(t.right)-T,o=e+T,l=b.left+P),n=0;n<C;++n)i=S[n]||{},sn(i.label)&&n<S.length||(n===b.zeroLineIndex&&y.offset===w?(g=_.zeroLineWidth,p=_.zeroLineColor,m=_.zeroLineBorderDash||[],v=_.zeroLineBorderDashOffset||0):(g=un(_.lineWidth,n,1),p=un(_.color,n,"rgba(0,0,0,0.1)"),m=_.borderDash||[],v=_.borderDashOffset||0),void 0!==(a=dn(b,i._index||n,w))&&(r=I(x,a,g),M?o=l=d=c=r:s=u=h=f=r,A.push({tx1:o,ty1:s,tx2:l,ty2:u,x1:d,y1:h,x2:c,y2:f,width:g,color:p,borderDash:m,borderDashOffset:v})));return A.ticksLength=C,A.borderValue=e,A},_computeLabelItems:function(){var t,e,n,i,a,r,o,s,l,u,d,h,c=this,f=c.options,g=f.ticks,p=f.position,m=g.mirror,v=c.isHorizontal(),b=c._ticksToDraw,x=pn(g),y=g.padding,_=cn(f.gridLines),k=-V.toRadians(c.labelRotation),w=[];for("top"===p?(r=c.bottom-_-y,o=k?"left":"center"):"bottom"===p?(r=c.top+_+y,o=k?"right":"center"):"left"===p?(a=c.right-(m?0:_)-y,o=m?"left":"right"):(a=c.left+(m?0:_)+y,o=m?"right":"left"),t=0,e=b.length;t<e;++t)i=(n=b[t]).label,sn(i)||(s=c.getPixelForTick(n._index||t)+g.labelOffset,u=(l=n.major?x.major:x.minor).lineHeight,d=on(i)?i.length:1,v?(a=s,h="top"===p?((k?1:.5)-d)*u:(k?0:.5)*u):(r=s,h=(1-d)*u/2),w.push({x:a,y:r,rotation:k,label:i,font:l,textOffset:h,textAlign:o}));return w},_drawGrid:function(t){var e=this,n=e.options.gridLines;if(n.display){var i,a,r,o,s,l=e.ctx,u=e.chart,d=V._alignPixel,h=n.drawBorder?un(n.lineWidth,0,0):0,c=e._gridLineItems||(e._gridLineItems=e._computeGridLineItems(t));for(r=0,o=c.length;r<o;++r)i=(s=c[r]).width,a=s.color,i&&a&&(l.save(),l.lineWidth=i,l.strokeStyle=a,l.setLineDash&&(l.setLineDash(s.borderDash),l.lineDashOffset=s.borderDashOffset),l.beginPath(),n.drawTicks&&(l.moveTo(s.tx1,s.ty1),l.lineTo(s.tx2,s.ty2)),n.drawOnChartArea&&(l.moveTo(s.x1,s.y1),l.lineTo(s.x2,s.y2)),l.stroke(),l.restore());if(h){var f,g,p,m,v=h,b=un(n.lineWidth,c.ticksLength-1,1),x=c.borderValue;e.isHorizontal()?(f=d(u,e.left,v)-v/2,g=d(u,e.right,b)+b/2,p=m=x):(p=d(u,e.top,v)-v/2,m=d(u,e.bottom,b)+b/2,f=g=x),l.lineWidth=h,l.strokeStyle=un(n.color,0),l.beginPath(),l.moveTo(f,p),l.lineTo(g,m),l.stroke()}}},_drawLabels:function(){var t=this;if(t.options.ticks.display){var e,n,i,a,r,o,s,l,u=t.ctx,d=t._labelItems||(t._labelItems=t._computeLabelItems());for(e=0,i=d.length;e<i;++e){if(o=(r=d[e]).font,u.save(),u.translate(r.x,r.y),u.rotate(r.rotation),u.font=o.string,u.fillStyle=o.color,u.textBaseline="middle",u.textAlign=r.textAlign,s=r.label,l=r.textOffset,on(s))for(n=0,a=s.length;n<a;++n)u.fillText(""+s[n],0,l),l+=o.lineHeight;else u.fillText(s,0,l);u.restore()}}},_drawTitle:function(){var t=this,e=t.ctx,n=t.options,i=n.scaleLabel;if(i.display){var a,r,o=ln(i.fontColor,z.global.defaultFontColor),s=V.options._parseFont(i),l=V.options.toPadding(i.padding),u=s.lineHeight/2,d=n.position,h=0;if(t.isHorizontal())a=t.left+t.width/2,r="bottom"===d?t.bottom-u-l.bottom:t.top+u+l.top;else{var c="left"===d;a=c?t.left+u+l.top:t.right-u-l.top,r=t.top+t.height/2,h=c?-.5*Math.PI:.5*Math.PI}e.save(),e.translate(a,r),e.rotate(h),e.textAlign="center",e.textBaseline="middle",e.fillStyle=o,e.font=s.string,e.fillText(i.labelString,0,0),e.restore()}},draw:function(t){this._isVisible()&&(this._drawGrid(t),this._drawTitle(),this._drawLabels())},_layers:function(){var t=this,e=t.options,n=e.ticks&&e.ticks.z||0,i=e.gridLines&&e.gridLines.z||0;return t._isVisible()&&n!==i&&t.draw===t._draw?[{z:i,draw:function(){t._drawGrid.apply(t,arguments),t._drawTitle.apply(t,arguments)}},{z:n,draw:function(){t._drawLabels.apply(t,arguments)}}]:[{z:n,draw:function(){t.draw.apply(t,arguments)}}]},_getMatchingVisibleMetas:function(t){var e=this,n=e.isHorizontal();return e.chart._getSortedVisibleDatasetMetas().filter((function(i){return(!t||i.type===t)&&(n?i.xAxisID===e.id:i.yAxisID===e.id)}))}});bn.prototype._draw=bn.prototype.draw;var xn=bn,yn=V.isNullOrUndef,_n=xn.extend({determineDataLimits:function(){var t,e=this,n=e._getLabels(),i=e.options.ticks,a=i.min,r=i.max,o=0,s=n.length-1;void 0!==a&&(t=n.indexOf(a))>=0&&(o=t),void 0!==r&&(t=n.indexOf(r))>=0&&(s=t),e.minIndex=o,e.maxIndex=s,e.min=n[o],e.max=n[s]},buildTicks:function(){var t=this._getLabels(),e=this.minIndex,n=this.maxIndex;this.ticks=0===e&&n===t.length-1?t:t.slice(e,n+1)},getLabelForIndex:function(t,e){var n=this.chart;return n.getDatasetMeta(e).controller._getValueScaleId()===this.id?this.getRightValue(n.data.datasets[e].data[t]):this._getLabels()[t]},_configure:function(){var t=this,e=t.options.offset,n=t.ticks;xn.prototype._configure.call(t),t.isHorizontal()||(t._reversePixels=!t._reversePixels),n&&(t._startValue=t.minIndex-(e?.5:0),t._valueRange=Math.max(n.length-(e?0:1),1))},getPixelForValue:function(t,e,n){var i,a,r,o=this;return yn(e)||yn(n)||(t=o.chart.data.datasets[n].data[e]),yn(t)||(i=o.isHorizontal()?t.x:t.y),(void 0!==i||void 0!==t&&isNaN(e))&&(a=o._getLabels(),t=V.valueOrDefault(i,t),e=-1!==(r=a.indexOf(t))?r:e,isNaN(e)&&(e=t)),o.getPixelForDecimal((e-o._startValue)/o._valueRange)},getPixelForTick:function(t){var e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t],t+this.minIndex)},getValueForPixel:function(t){var e=Math.round(this._startValue+this.getDecimalForPixel(t)*this._valueRange);return Math.min(Math.max(e,0),this.ticks.length-1)},getBasePixel:function(){return this.bottom}}),kn={position:"bottom"};_n._defaults=kn;var wn=V.noop,Mn=V.isNullOrUndef;var Sn=xn.extend({getRightValue:function(t){return"string"==typeof t?+t:xn.prototype.getRightValue.call(this,t)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=V.sign(t.min),i=V.sign(t.max);n<0&&i<0?t.max=0:n>0&&i>0&&(t.min=0)}var a=void 0!==e.min||void 0!==e.suggestedMin,r=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)),a!==r&&t.min>=t.max&&(a?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:function(){var t,e=this.options.ticks,n=e.stepSize,i=e.maxTicksLimit;return n?t=Math.ceil(this.max/n)-Math.floor(this.min/n)+1:(t=this._computeTickLimit(),i=i||11),i&&(t=Math.min(i,t)),t},_computeTickLimit:function(){return Number.POSITIVE_INFINITY},handleDirectionalChanges:wn,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),i={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,precision:e.precision,stepSize:V.valueOrDefault(e.fixedStepSize,e.stepSize)},a=t.ticks=function(t,e){var n,i,a,r,o=[],s=t.stepSize,l=s||1,u=t.maxTicks-1,d=t.min,h=t.max,c=t.precision,f=e.min,g=e.max,p=V.niceNum((g-f)/u/l)*l;if(p<1e-14&&Mn(d)&&Mn(h))return[f,g];(r=Math.ceil(g/p)-Math.floor(f/p))>u&&(p=V.niceNum(r*p/u/l)*l),s||Mn(c)?n=Math.pow(10,V._decimalPlaces(p)):(n=Math.pow(10,c),p=Math.ceil(p*n)/n),i=Math.floor(f/p)*p,a=Math.ceil(g/p)*p,s&&(!Mn(d)&&V.almostWhole(d/p,p/1e3)&&(i=d),!Mn(h)&&V.almostWhole(h/p,p/1e3)&&(a=h)),r=(a-i)/p,r=V.almostEquals(r,Math.round(r),p/1e3)?Math.round(r):Math.ceil(r),i=Math.round(i*n)/n,a=Math.round(a*n)/n,o.push(Mn(d)?i:d);for(var m=1;m<r;++m)o.push(Math.round((i+m*p)*n)/n);return o.push(Mn(h)?a:h),o}(i,t);t.handleDirectionalChanges(),t.max=V.max(a),t.min=V.min(a),e.reverse?(a.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var t=this;t.ticksAsNumbers=t.ticks.slice(),t.zeroLineIndex=t.ticks.indexOf(0),xn.prototype.convertTicksToLabels.call(t)},_configure:function(){var t,e=this,n=e.getTicks(),i=e.min,a=e.max;xn.prototype._configure.call(e),e.options.offset&&n.length&&(i-=t=(a-i)/Math.max(n.length-1,1)/2,a+=t),e._startValue=i,e._endValue=a,e._valueRange=a-i}}),Cn={position:"left",ticks:{callback:rn.formatters.linear}};function Pn(t,e,n,i){var a,r,o=t.options,s=function(t,e,n){var i=[n.type,void 0===e&&void 0===n.stack?n.index:"",n.stack].join(".");return void 0===t[i]&&(t[i]={pos:[],neg:[]}),t[i]}(e,o.stacked,n),l=s.pos,u=s.neg,d=i.length;for(a=0;a<d;++a)r=t._parseValue(i[a]),isNaN(r.min)||isNaN(r.max)||n.data[a].hidden||(l[a]=l[a]||0,u[a]=u[a]||0,o.relativePoints?l[a]=100:r.min<0||r.max<0?u[a]+=r.min:l[a]+=r.max)}function An(t,e,n){var i,a,r=n.length;for(i=0;i<r;++i)a=t._parseValue(n[i]),isNaN(a.min)||isNaN(a.max)||e.data[i].hidden||(t.min=Math.min(t.min,a.min),t.max=Math.max(t.max,a.max))}var Dn=Sn.extend({determineDataLimits:function(){var t,e,n,i,a=this,r=a.options,o=a.chart.data.datasets,s=a._getMatchingVisibleMetas(),l=r.stacked,u={},d=s.length;if(a.min=Number.POSITIVE_INFINITY,a.max=Number.NEGATIVE_INFINITY,void 0===l)for(t=0;!l&&t<d;++t)l=void 0!==(e=s[t]).stack;for(t=0;t<d;++t)n=o[(e=s[t]).index].data,l?Pn(a,u,e,n):An(a,e,n);V.each(u,(function(t){i=t.pos.concat(t.neg),a.min=Math.min(a.min,V.min(i)),a.max=Math.max(a.max,V.max(i))})),a.min=V.isFinite(a.min)&&!isNaN(a.min)?a.min:0,a.max=V.isFinite(a.max)&&!isNaN(a.max)?a.max:1,a.handleTickRangeOptions()},_computeTickLimit:function(){var t;return this.isHorizontal()?Math.ceil(this.width/40):(t=V.options._parseFont(this.options.ticks),Math.ceil(this.height/t.lineHeight))},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return this._getScaleLabel(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){return this.getPixelForDecimal((+this.getRightValue(t)-this._startValue)/this._valueRange)},getValueForPixel:function(t){return this._startValue+this.getDecimalForPixel(t)*this._valueRange},getPixelForTick:function(t){var e=this.ticksAsNumbers;return t<0||t>e.length-1?null:this.getPixelForValue(e[t])}}),Tn=Cn;Dn._defaults=Tn;var In=V.valueOrDefault,Fn=V.math.log10;var Ln={position:"left",ticks:{callback:rn.formatters.logarithmic}};function On(t,e){return V.isFinite(t)&&t>=0?t:e}var Rn=xn.extend({determineDataLimits:function(){var t,e,n,i,a,r,o=this,s=o.options,l=o.chart,u=l.data.datasets,d=o.isHorizontal();function h(t){return d?t.xAxisID===o.id:t.yAxisID===o.id}o.min=Number.POSITIVE_INFINITY,o.max=Number.NEGATIVE_INFINITY,o.minNotZero=Number.POSITIVE_INFINITY;var c=s.stacked;if(void 0===c)for(t=0;t<u.length;t++)if(e=l.getDatasetMeta(t),l.isDatasetVisible(t)&&h(e)&&void 0!==e.stack){c=!0;break}if(s.stacked||c){var f={};for(t=0;t<u.length;t++){var g=[(e=l.getDatasetMeta(t)).type,void 0===s.stacked&&void 0===e.stack?t:"",e.stack].join(".");if(l.isDatasetVisible(t)&&h(e))for(void 0===f[g]&&(f[g]=[]),a=0,r=(i=u[t].data).length;a<r;a++){var p=f[g];n=o._parseValue(i[a]),isNaN(n.min)||isNaN(n.max)||e.data[a].hidden||n.min<0||n.max<0||(p[a]=p[a]||0,p[a]+=n.max)}}V.each(f,(function(t){if(t.length>0){var e=V.min(t),n=V.max(t);o.min=Math.min(o.min,e),o.max=Math.max(o.max,n)}}))}else for(t=0;t<u.length;t++)if(e=l.getDatasetMeta(t),l.isDatasetVisible(t)&&h(e))for(a=0,r=(i=u[t].data).length;a<r;a++)n=o._parseValue(i[a]),isNaN(n.min)||isNaN(n.max)||e.data[a].hidden||n.min<0||n.max<0||(o.min=Math.min(n.min,o.min),o.max=Math.max(n.max,o.max),0!==n.min&&(o.minNotZero=Math.min(n.min,o.minNotZero)));o.min=V.isFinite(o.min)?o.min:null,o.max=V.isFinite(o.max)?o.max:null,o.minNotZero=V.isFinite(o.minNotZero)?o.minNotZero:null,this.handleTickRangeOptions()},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;t.min=On(e.min,t.min),t.max=On(e.max,t.max),t.min===t.max&&(0!==t.min&&null!==t.min?(t.min=Math.pow(10,Math.floor(Fn(t.min))-1),t.max=Math.pow(10,Math.floor(Fn(t.max))+1)):(t.min=1,t.max=10)),null===t.min&&(t.min=Math.pow(10,Math.floor(Fn(t.max))-1)),null===t.max&&(t.max=0!==t.min?Math.pow(10,Math.floor(Fn(t.min))+1):10),null===t.minNotZero&&(t.min>0?t.minNotZero=t.min:t.max<1?t.minNotZero=Math.pow(10,Math.floor(Fn(t.max))):t.minNotZero=1)},buildTicks:function(){var t=this,e=t.options.ticks,n=!t.isHorizontal(),i={min:On(e.min),max:On(e.max)},a=t.ticks=function(t,e){var n,i,a=[],r=In(t.min,Math.pow(10,Math.floor(Fn(e.min)))),o=Math.floor(Fn(e.max)),s=Math.ceil(e.max/Math.pow(10,o));0===r?(n=Math.floor(Fn(e.minNotZero)),i=Math.floor(e.minNotZero/Math.pow(10,n)),a.push(r),r=i*Math.pow(10,n)):(n=Math.floor(Fn(r)),i=Math.floor(r/Math.pow(10,n)));var l=n<0?Math.pow(10,Math.abs(n)):1;do{a.push(r),10===++i&&(i=1,l=++n>=0?1:l),r=Math.round(i*Math.pow(10,n)*l)/l}while(n<o||n===o&&i<s);var u=In(t.max,r);return a.push(u),a}(i,t);t.max=V.max(a),t.min=V.min(a),e.reverse?(n=!n,t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max),n&&a.reverse()},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),xn.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return this._getScaleLabel(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){var e=this.tickValues;return t<0||t>e.length-1?null:this.getPixelForValue(e[t])},_getFirstTickValue:function(t){var e=Math.floor(Fn(t));return Math.floor(t/Math.pow(10,e))*Math.pow(10,e)},_configure:function(){var t=this,e=t.min,n=0;xn.prototype._configure.call(t),0===e&&(e=t._getFirstTickValue(t.minNotZero),n=In(t.options.ticks.fontSize,z.global.defaultFontSize)/t._length),t._startValue=Fn(e),t._valueOffset=n,t._valueRange=(Fn(t.max)-Fn(e))/(1-n)},getPixelForValue:function(t){var e=this,n=0;return(t=+e.getRightValue(t))>e.min&&t>0&&(n=(Fn(t)-e._startValue)/e._valueRange+e._valueOffset),e.getPixelForDecimal(n)},getValueForPixel:function(t){var e=this,n=e.getDecimalForPixel(t);return 0===n&&0===e.min?0:Math.pow(10,e._startValue+(n-e._valueOffset)*e._valueRange)}}),zn=Ln;Rn._defaults=zn;var Nn=V.valueOrDefault,Bn=V.valueAtIndexOrDefault,En=V.options.resolve,Wn={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0,0,0,0.1)",lineWidth:1,borderDash:[],borderDashOffset:0},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:rn.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}};function Vn(t){var e=t.ticks;return e.display&&t.display?Nn(e.fontSize,z.global.defaultFontSize)+2*e.backdropPaddingY:0}function Hn(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,end:e}:{start:e,end:e+n}}function jn(t){return 0===t||180===t?"center":t<180?"left":"right"}function qn(t,e,n,i){var a,r,o=n.y+i/2;if(V.isArray(e))for(a=0,r=e.length;a<r;++a)t.fillText(e[a],n.x,o),o+=i;else t.fillText(e,n.x,o)}function Un(t,e,n){90===t||270===t?n.y-=e.h/2:(t>270||t<90)&&(n.y-=e.h)}function Yn(t){return V.isNumber(t)?t:0}var Gn=Sn.extend({setDimensions:function(){var t=this;t.width=t.maxWidth,t.height=t.maxHeight,t.paddingTop=Vn(t.options)/2,t.xCenter=Math.floor(t.width/2),t.yCenter=Math.floor((t.height-t.paddingTop)/2),t.drawingArea=Math.min(t.height-t.paddingTop,t.width)/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;V.each(e.data.datasets,(function(a,r){if(e.isDatasetVisible(r)){var o=e.getDatasetMeta(r);V.each(a.data,(function(e,a){var r=+t.getRightValue(e);isNaN(r)||o.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()},_computeTickLimit:function(){return Math.ceil(this.drawingArea/Vn(this.options))},convertTicksToLabels:function(){var t=this;Sn.prototype.convertTicksToLabels.call(t),t.pointLabels=t.chart.data.labels.map((function(){var e=V.callback(t.options.pointLabels.callback,arguments,t);return e||0===e?e:""}))},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){var t=this.options;t.display&&t.pointLabels.display?function(t){var e,n,i,a=V.options._parseFont(t.options.pointLabels),r={l:0,r:t.width,t:0,b:t.height-t.paddingTop},o={};t.ctx.font=a.string,t._pointLabelSizes=[];var s,l,u,d=t.chart.data.labels.length;for(e=0;e<d;e++){i=t.getPointPosition(e,t.drawingArea+5),s=t.ctx,l=a.lineHeight,u=t.pointLabels[e],n=V.isArray(u)?{w:V.longestText(s,s.font,u),h:u.length*l}:{w:s.measureText(u).width,h:l},t._pointLabelSizes[e]=n;var h=t.getIndexAngle(e),c=V.toDegrees(h)%360,f=Hn(c,i.x,n.w,0,180),g=Hn(c,i.y,n.h,90,270);f.start<r.l&&(r.l=f.start,o.l=h),f.end>r.r&&(r.r=f.end,o.r=h),g.start<r.t&&(r.t=g.start,o.t=h),g.end>r.b&&(r.b=g.end,o.b=h)}t.setReductions(t.drawingArea,r,o)}(this):this.setCenterPoint(0,0,0,0)},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-i.paddingTop),0)/Math.cos(n.b);a=Yn(a),r=Yn(r),o=Yn(o),s=Yn(s),i.drawingArea=Math.min(Math.floor(t-(a+r)/2),Math.floor(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-a.paddingTop-i-a.drawingArea;a.xCenter=Math.floor((o+r)/2+a.left),a.yCenter=Math.floor((s+l)/2+a.top+a.paddingTop)},getIndexAngle:function(t){var e=this.chart,n=(t*(360/e.data.labels.length)+((e.options||{}).startAngle||0))%360;return(n<0?n+360:n)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(V.isNullOrUndef(t))return NaN;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.getIndexAngle(t)-Math.PI/2;return{x:Math.cos(n)*e+this.xCenter,y:Math.sin(n)*e+this.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(t){var e=this.min,n=this.max;return this.getPointPositionForValue(t||0,this.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0)},_drawGrid:function(){var t,e,n,i=this,a=i.ctx,r=i.options,o=r.gridLines,s=r.angleLines,l=Nn(s.lineWidth,o.lineWidth),u=Nn(s.color,o.color);if(r.pointLabels.display&&function(t){var e=t.ctx,n=t.options,i=n.pointLabels,a=Vn(n),r=t.getDistanceFromCenterForValue(n.ticks.reverse?t.min:t.max),o=V.options._parseFont(i);e.save(),e.font=o.string,e.textBaseline="middle";for(var s=t.chart.data.labels.length-1;s>=0;s--){var l=0===s?a/2:0,u=t.getPointPosition(s,r+l+5),d=Bn(i.fontColor,s,z.global.defaultFontColor);e.fillStyle=d;var h=t.getIndexAngle(s),c=V.toDegrees(h);e.textAlign=jn(c),Un(c,t._pointLabelSizes[s],u),qn(e,t.pointLabels[s],u,o.lineHeight)}e.restore()}(i),o.display&&V.each(i.ticks,(function(t,n){0!==n&&(e=i.getDistanceFromCenterForValue(i.ticksAsNumbers[n]),function(t,e,n,i){var a,r=t.ctx,o=e.circular,s=t.chart.data.labels.length,l=Bn(e.color,i-1),u=Bn(e.lineWidth,i-1);if((o||s)&&l&&u){if(r.save(),r.strokeStyle=l,r.lineWidth=u,r.setLineDash&&(r.setLineDash(e.borderDash||[]),r.lineDashOffset=e.borderDashOffset||0),r.beginPath(),o)r.arc(t.xCenter,t.yCenter,n,0,2*Math.PI);else{a=t.getPointPosition(0,n),r.moveTo(a.x,a.y);for(var d=1;d<s;d++)a=t.getPointPosition(d,n),r.lineTo(a.x,a.y)}r.closePath(),r.stroke(),r.restore()}}(i,o,e,n))})),s.display&&l&&u){for(a.save(),a.lineWidth=l,a.strokeStyle=u,a.setLineDash&&(a.setLineDash(En([s.borderDash,o.borderDash,[]])),a.lineDashOffset=En([s.borderDashOffset,o.borderDashOffset,0])),t=i.chart.data.labels.length-1;t>=0;t--)e=i.getDistanceFromCenterForValue(r.ticks.reverse?i.min:i.max),n=i.getPointPosition(t,e),a.beginPath(),a.moveTo(i.xCenter,i.yCenter),a.lineTo(n.x,n.y),a.stroke();a.restore()}},_drawLabels:function(){var t=this,e=t.ctx,n=t.options.ticks;if(n.display){var i,a,r=t.getIndexAngle(0),o=V.options._parseFont(n),s=Nn(n.fontColor,z.global.defaultFontColor);e.save(),e.font=o.string,e.translate(t.xCenter,t.yCenter),e.rotate(r),e.textAlign="center",e.textBaseline="middle",V.each(t.ticks,(function(r,l){(0!==l||n.reverse)&&(i=t.getDistanceFromCenterForValue(t.ticksAsNumbers[l]),n.showLabelBackdrop&&(a=e.measureText(r).width,e.fillStyle=n.backdropColor,e.fillRect(-a/2-n.backdropPaddingX,-i-o.size/2-n.backdropPaddingY,a+2*n.backdropPaddingX,o.size+2*n.backdropPaddingY)),e.fillStyle=s,e.fillText(r,0,-i))})),e.restore()}},_drawTitle:V.noop}),Xn=Wn;Gn._defaults=Xn;var Kn=V._deprecated,Zn=V.options.resolve,$n=V.valueOrDefault,Jn=Number.MIN_SAFE_INTEGER||-9007199254740991,Qn=Number.MAX_SAFE_INTEGER||9007199254740991,ti={millisecond:{common:!0,size:1,steps:1e3},second:{common:!0,size:1e3,steps:60},minute:{common:!0,size:6e4,steps:60},hour:{common:!0,size:36e5,steps:24},day:{common:!0,size:864e5,steps:30},week:{common:!1,size:6048e5,steps:4},month:{common:!0,size:2628e6,steps:12},quarter:{common:!1,size:7884e6,steps:4},year:{common:!0,size:3154e7}},ei=Object.keys(ti);function ni(t,e){return t-e}function ii(t){return V.valueOrDefault(t.time.min,t.ticks.min)}function ai(t){return V.valueOrDefault(t.time.max,t.ticks.max)}function ri(t,e,n,i){var a=function(t,e,n){for(var i,a,r,o=0,s=t.length-1;o>=0&&o<=s;){if(a=t[(i=o+s>>1)-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}}(t,e,n),r=a.lo?a.hi?a.lo:t[t.length-2]:t[0],o=a.lo?a.hi?a.hi:t[t.length-1]:t[1],s=o[e]-r[e],l=s?(n-r[e])/s:0,u=(o[i]-r[i])*l;return r[i]+u}function oi(t,e){var n=t._adapter,i=t.options.time,a=i.parser,r=a||i.format,o=e;return"function"==typeof a&&(o=a(o)),V.isFinite(o)||(o="string"==typeof r?n.parse(o,r):n.parse(o)),null!==o?+o:(a||"function"!=typeof r||(o=r(e),V.isFinite(o)||(o=n.parse(o))),o)}function si(t,e){if(V.isNullOrUndef(e))return null;var n=t.options.time,i=oi(t,t.getRightValue(e));return null===i?i:(n.round&&(i=+t._adapter.startOf(i,n.round)),i)}function li(t,e,n,i){var a,r,o,s=ei.length;for(a=ei.indexOf(t);a<s-1;++a)if(o=(r=ti[ei[a]]).steps?r.steps:Qn,r.common&&Math.ceil((n-e)/(o*r.size))<=i)return ei[a];return ei[s-1]}function ui(t,e,n){var i,a,r=[],o={},s=e.length;for(i=0;i<s;++i)o[a=e[i]]=i,r.push({value:a,major:!1});return 0!==s&&n?function(t,e,n,i){var a,r,o=t._adapter,s=+o.startOf(e[0].value,i),l=e[e.length-1].value;for(a=s;a<=l;a=+o.add(a,1,i))(r=n[a])>=0&&(e[r].major=!0);return e}(t,r,o,n):r}var di=xn.extend({initialize:function(){this.mergeTicksOptions(),xn.prototype.initialize.call(this)},update:function(){var t=this,e=t.options,n=e.time||(e.time={}),i=t._adapter=new an._date(e.adapters.date);return Kn("time scale",n.format,"time.format","time.parser"),Kn("time scale",n.min,"time.min","ticks.min"),Kn("time scale",n.max,"time.max","ticks.max"),V.mergeIf(n.displayFormats,i.formats()),xn.prototype.update.apply(t,arguments)},getRightValue:function(t){return t&&void 0!==t.t&&(t=t.t),xn.prototype.getRightValue.call(this,t)},determineDataLimits:function(){var t,e,n,i,a,r,o,s=this,l=s.chart,u=s._adapter,d=s.options,h=d.time.unit||"day",c=Qn,f=Jn,g=[],p=[],m=[],v=s._getLabels();for(t=0,n=v.length;t<n;++t)m.push(si(s,v[t]));for(t=0,n=(l.data.datasets||[]).length;t<n;++t)if(l.isDatasetVisible(t))if(a=l.data.datasets[t].data,V.isObject(a[0]))for(p[t]=[],e=0,i=a.length;e<i;++e)r=si(s,a[e]),g.push(r),p[t][e]=r;else p[t]=m.slice(0),o||(g=g.concat(m),o=!0);else p[t]=[];m.length&&(c=Math.min(c,m[0]),f=Math.max(f,m[m.length-1])),g.length&&(g=n>1?function(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}(g).sort(ni):g.sort(ni),c=Math.min(c,g[0]),f=Math.max(f,g[g.length-1])),c=si(s,ii(d))||c,f=si(s,ai(d))||f,c=c===Qn?+u.startOf(Date.now(),h):c,f=f===Jn?+u.endOf(Date.now(),h)+1:f,s.min=Math.min(c,f),s.max=Math.max(c+1,f),s._table=[],s._timestamps={data:g,datasets:p,labels:m}},buildTicks:function(){var t,e,n,i=this,a=i.min,r=i.max,o=i.options,s=o.ticks,l=o.time,u=i._timestamps,d=[],h=i.getLabelCapacity(a),c=s.source,f=o.distribution;for(u="data"===c||"auto"===c&&"series"===f?u.data:"labels"===c?u.labels:function(t,e,n,i){var a,r=t._adapter,o=t.options,s=o.time,l=s.unit||li(s.minUnit,e,n,i),u=Zn([s.stepSize,s.unitStepSize,1]),d="week"===l&&s.isoWeekday,h=e,c=[];if(d&&(h=+r.startOf(h,"isoWeek",d)),h=+r.startOf(h,d?"day":l),r.diff(n,e,l)>1e5*u)throw e+" and "+n+" are too far apart with stepSize of "+u+" "+l;for(a=h;a<n;a=+r.add(a,u,l))c.push(a);return a!==n&&"ticks"!==o.bounds||c.push(a),c}(i,a,r,h),"ticks"===o.bounds&&u.length&&(a=u[0],r=u[u.length-1]),a=si(i,ii(o))||a,r=si(i,ai(o))||r,t=0,e=u.length;t<e;++t)(n=u[t])>=a&&n<=r&&d.push(n);return i.min=a,i.max=r,i._unit=l.unit||(s.autoSkip?li(l.minUnit,i.min,i.max,h):function(t,e,n,i,a){var r,o;for(r=ei.length-1;r>=ei.indexOf(n);r--)if(o=ei[r],ti[o].common&&t._adapter.diff(a,i,o)>=e-1)return o;return ei[n?ei.indexOf(n):0]}(i,d.length,l.minUnit,i.min,i.max)),i._majorUnit=s.major.enabled&&"year"!==i._unit?function(t){for(var e=ei.indexOf(t)+1,n=ei.length;e<n;++e)if(ti[ei[e]].common)return ei[e]}(i._unit):void 0,i._table=function(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}(i._timestamps.data,a,r,f),i._offsets=function(t,e,n,i,a){var r,o,s=0,l=0;return a.offset&&e.length&&(r=ri(t,"time",e[0],"pos"),s=1===e.length?1-r:(ri(t,"time",e[1],"pos")-r)/2,o=ri(t,"time",e[e.length-1],"pos"),l=1===e.length?o:(o-ri(t,"time",e[e.length-2],"pos"))/2),{start:s,end:l,factor:1/(s+1+l)}}(i._table,d,0,0,o),s.reverse&&d.reverse(),ui(i,d,i._majorUnit)},getLabelForIndex:function(t,e){var n=this,i=n._adapter,a=n.chart.data,r=n.options.time,o=a.labels&&t<a.labels.length?a.labels[t]:"",s=a.datasets[e].data[t];return V.isObject(s)&&(o=n.getRightValue(s)),r.tooltipFormat?i.format(oi(n,o),r.tooltipFormat):"string"==typeof o?o:i.format(oi(n,o),r.displayFormats.datetime)},tickFormatFunction:function(t,e,n,i){var a=this._adapter,r=this.options,o=r.time.displayFormats,s=o[this._unit],l=this._majorUnit,u=o[l],d=n[e],h=r.ticks,c=l&&u&&d&&d.major,f=a.format(t,i||(c?u:s)),g=c?h.major:h.minor,p=Zn([g.callback,g.userCallback,h.callback,h.userCallback]);return p?p(f,e,n):f},convertTicksToLabels:function(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(this.tickFormatFunction(t[e].value,e,t));return i},getPixelForOffset:function(t){var e=this._offsets,n=ri(this._table,"time",t,"pos");return this.getPixelForDecimal((e.start+n)*e.factor)},getPixelForValue:function(t,e,n){var i=null;if(void 0!==e&&void 0!==n&&(i=this._timestamps.datasets[n][e]),null===i&&(i=si(this,t)),null!==i)return this.getPixelForOffset(i)},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._offsets,n=this.getDecimalForPixel(t)/e.factor-e.end,i=ri(this._table,"pos",n,"time");return this._adapter._create(i)},_getLabelSize:function(t){var e=this.options.ticks,n=this.ctx.measureText(t).width,i=V.toRadians(this.isHorizontal()?e.maxRotation:e.minRotation),a=Math.cos(i),r=Math.sin(i),o=$n(e.fontSize,z.global.defaultFontSize);return{w:n*a+o*r,h:n*r+o*a}},getLabelWidth:function(t){return this._getLabelSize(t).w},getLabelCapacity:function(t){var e=this,n=e.options.time,i=n.displayFormats,a=i[n.unit]||i.millisecond,r=e.tickFormatFunction(t,0,ui(e,[t],e._majorUnit),a),o=e._getLabelSize(r),s=Math.floor(e.isHorizontal()?e.width/o.w:e.height/o.h);return e.options.offset&&s--,s>0?s:1}}),hi={position:"bottom",distribution:"linear",bounds:"data",adapters:{},time:{parser:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}};di._defaults=hi;var ci={category:_n,linear:Dn,logarithmic:Rn,radialLinear:Gn,time:di},fi={datetime:"MMM D, YYYY, h:mm:ss a",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"};an._date.override("function"==typeof t?{_id:"moment",formats:function(){return fi},parse:function(e,n){return"string"==typeof e&&"string"==typeof n?e=t(e,n):e instanceof t||(e=t(e)),e.isValid()?e.valueOf():null},format:function(e,n){return t(e).format(n)},add:function(e,n,i){return t(e).add(n,i).valueOf()},diff:function(e,n,i){return t(e).diff(t(n),i)},startOf:function(e,n,i){return e=t(e),"isoWeek"===n?e.isoWeekday(i).valueOf():e.startOf(n).valueOf()},endOf:function(e,n){return t(e).endOf(n).valueOf()},_create:function(e){return t(e)}}:{}),z._set("global",{plugins:{filler:{propagate:!0}}});var gi={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 V.isArray(e)?function(t,n){return e[n]}:function(t){return{x:null===n?t.x:n,y:null===i?t.y:i}}}};function pi(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 mi(t){return(t.el._scale||{}).getPointPositionForValue?function(t){var e,n,i,a,r,o=t.el._scale,s=o.options,l=o.chart.data.labels.length,u=t.fill,d=[];if(!l)return null;for(e=s.ticks.reverse?o.max:o.min,n=s.ticks.reverse?o.min:o.max,i=o.getPointPositionForValue(0,e),a=0;a<l;++a)r="start"===u||"end"===u?o.getPointPositionForValue(a,"start"===u?e:n):o.getBasePosition(a),s.gridLines.circular&&(r.cx=i.x,r.cy=i.y,r.angle=o.getIndexAngle(a)-Math.PI/2),d.push(r);return d}(t):function(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.getBasePixel&&(r=i.getBasePixel()),null!=r){if(void 0!==r.x&&void 0!==r.y)return r;if(V.isFinite(r))return{x:(e=i.isHorizontal())?r:null,y:e?null:r}}return null}(t)}function vi(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 bi(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),gi[n](t))}function xi(t){return t&&!t.skip}function yi(t,e,n,i,a){var r,o,s,l;if(i&&a){for(t.moveTo(e[0].x,e[0].y),r=1;r<i;++r)V.canvas.lineTo(t,e[r-1],e[r]);if(void 0===n[0].angle)for(t.lineTo(n[a-1].x,n[a-1].y),r=a-1;r>0;--r)V.canvas.lineTo(t,n[r],n[r-1],!0);else for(o=n[0].cx,s=n[0].cy,l=Math.sqrt(Math.pow(n[0].x-o,2)+Math.pow(n[0].y-s,2)),r=a-1;r>0;--r)t.arc(o,s,l,n[r].angle,n[r-1].angle,!0)}}function _i(t,e,n,i,a,r){var o,s,l,u,d,h,c,f,g=e.length,p=i.spanGaps,m=[],v=[],b=0,x=0;for(t.beginPath(),o=0,s=g;o<s;++o)d=n(u=e[l=o%g]._view,l,i),h=xi(u),c=xi(d),r&&void 0===f&&h&&(s=g+(f=o+1)),h&&c?(b=m.push(u),x=v.push(d)):b&&x&&(p?(h&&m.push(u),c&&v.push(d)):(yi(t,m,v,b,x),b=x=0,m=[],v=[]));yi(t,m,v,b,x),t.closePath(),t.fillStyle=a,t.fill()}var ki={id:"filler",afterDatasetsUpdate:function(t,e){var n,i,a,r,o=(t.data.datasets||[]).length,s=e.propagate,l=[];for(i=0;i<o;++i)r=null,(a=(n=t.getDatasetMeta(i)).dataset)&&a._model&&a instanceof _t.Line&&(r={visible:t.isDatasetVisible(i),fill:pi(a,i,o),chart:t,el:a}),n.$filler=r,l.push(r);for(i=0;i<o;++i)(r=l[i])&&(r.fill=vi(l,i,s),r.boundary=mi(r),r.mapper=bi(r))},beforeDatasetsDraw:function(t){var e,n,i,a,r,o,s,l=t._getSortedVisibleDatasetMetas(),u=t.ctx;for(n=l.length-1;n>=0;--n)(e=l[n].$filler)&&e.visible&&(a=(i=e.el)._view,r=i._children||[],o=e.mapper,s=a.backgroundColor||z.global.defaultColor,o&&s&&r.length&&(V.canvas.clipArea(u,t.chartArea),_i(u,r,o,a,s,i._loop),V.canvas.unclipArea(u)))}},wi=V.rtl.getRtlAdapter,Mi=V.noop,Si=V.valueOrDefault;function Ci(t,e){return t.usePointStyle&&t.boxWidth>e?e:t.boxWidth}z._set("global",{legend:{display:!0,position:"top",align:"center",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,onLeave:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data.datasets,n=t.options.legend||{},i=n.labels&&n.labels.usePointStyle;return t._getSortedDatasetMetas().map((function(n){var a=n.controller.getStyle(i?0:void 0);return{text:e[n.index].label,fillStyle:a.backgroundColor,hidden:!t.isDatasetVisible(n.index),lineCap:a.borderCapStyle,lineDash:a.borderDash,lineDashOffset:a.borderDashOffset,lineJoin:a.borderJoinStyle,lineWidth:a.borderWidth,strokeStyle:a.borderColor,pointStyle:a.pointStyle,rotation:a.rotation,datasetIndex:n.index}}),this)}}},legendCallback:function(t){var e,n,i,a=document.createElement("ul"),r=t.data.datasets;for(a.setAttribute("class",t.id+"-legend"),e=0,n=r.length;e<n;e++)(i=a.appendChild(document.createElement("li"))).appendChild(document.createElement("span")).style.backgroundColor=r[e].backgroundColor,r[e].label&&i.appendChild(document.createTextNode(r[e].label));return a.outerHTML}});var Pi=X.extend({initialize:function(t){V.extend(this,t),this.legendHitBoxes=[],this._hoveredItem=null,this.doughnutMode=!1},beforeUpdate:Mi,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:Mi,beforeSetDimensions:Mi,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:Mi,beforeBuildLabels:Mi,buildLabels:function(){var t=this,e=t.options.labels||{},n=V.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:Mi,beforeFit:Mi,fit:function(){var t=this,e=t.options,n=e.labels,i=e.display,a=t.ctx,r=V.options._parseFont(n),o=r.size,s=t.legendHitBoxes=[],l=t.minSize,u=t.isHorizontal();if(u?(l.width=t.maxWidth,l.height=i?10:0):(l.width=i?10:0,l.height=t.maxHeight),i){if(a.font=r.string,u){var d=t.lineWidths=[0],h=0;a.textAlign="left",a.textBaseline="middle",V.each(t.legendItems,(function(t,e){var i=Ci(n,o)+o/2+a.measureText(t.text).width;(0===e||d[d.length-1]+i+2*n.padding>l.width)&&(h+=o+n.padding,d[d.length-(e>0?0:1)]=0),s[e]={left:0,top:0,width:i,height:o},d[d.length-1]+=i+n.padding})),l.height+=h}else{var c=n.padding,f=t.columnWidths=[],g=t.columnHeights=[],p=n.padding,m=0,v=0;V.each(t.legendItems,(function(t,e){var i=Ci(n,o)+o/2+a.measureText(t.text).width;e>0&&v+o+2*c>l.height&&(p+=m+n.padding,f.push(m),g.push(v),m=0,v=0),m=Math.max(m,i),v+=o+c,s[e]={left:0,top:0,width:i,height:o}})),p+=m,f.push(m),g.push(v),l.width+=p}t.width=l.width,t.height=l.height}else t.width=l.width=t.height=l.height=0},afterFit:Mi,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,e=t.options,n=e.labels,i=z.global,a=i.defaultColor,r=i.elements.line,o=t.height,s=t.columnHeights,l=t.width,u=t.lineWidths;if(e.display){var d,h=wi(e.rtl,t.left,t.minSize.width),c=t.ctx,f=Si(n.fontColor,i.defaultFontColor),g=V.options._parseFont(n),p=g.size;c.textAlign=h.textAlign("left"),c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=g.string;var m=Ci(n,p),v=t.legendHitBoxes,b=function(t,i){switch(e.align){case"start":return n.padding;case"end":return t-i;default:return(t-i+n.padding)/2}},x=t.isHorizontal();d=x?{x:t.left+b(l,u[0]),y:t.top+n.padding,line:0}:{x:t.left+n.padding,y:t.top+b(o,s[0]),line:0},V.rtl.overrideTextDirection(t.ctx,e.textDirection);var y=p+n.padding;V.each(t.legendItems,(function(e,i){var f=c.measureText(e.text).width,g=m+p/2+f,_=d.x,k=d.y;h.setWidth(t.minSize.width),x?i>0&&_+g+n.padding>t.left+t.minSize.width&&(k=d.y+=y,d.line++,_=d.x=t.left+b(l,u[d.line])):i>0&&k+y>t.top+t.minSize.height&&(_=d.x=_+t.columnWidths[d.line]+n.padding,d.line++,k=d.y=t.top+b(o,s[d.line]));var w=h.x(_);!function(t,e,i){if(!(isNaN(m)||m<=0)){c.save();var o=Si(i.lineWidth,r.borderWidth);if(c.fillStyle=Si(i.fillStyle,a),c.lineCap=Si(i.lineCap,r.borderCapStyle),c.lineDashOffset=Si(i.lineDashOffset,r.borderDashOffset),c.lineJoin=Si(i.lineJoin,r.borderJoinStyle),c.lineWidth=o,c.strokeStyle=Si(i.strokeStyle,a),c.setLineDash&&c.setLineDash(Si(i.lineDash,r.borderDash)),n&&n.usePointStyle){var s=m*Math.SQRT2/2,l=h.xPlus(t,m/2),u=e+p/2;V.canvas.drawPoint(c,i.pointStyle,s,l,u,i.rotation)}else c.fillRect(h.leftForLtr(t,m),e,m,p),0!==o&&c.strokeRect(h.leftForLtr(t,m),e,m,p);c.restore()}}(w,k,e),v[i].left=h.leftForLtr(w,v[i].width),v[i].top=k,function(t,e,n,i){var a=p/2,r=h.xPlus(t,m+a),o=e+a;c.fillText(n.text,r,o),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(r,o),c.lineTo(h.xPlus(r,i),o),c.stroke())}(w,k,e,f),x?d.x+=g+n.padding:d.y+=y})),V.rtl.restoreTextDirection(t.ctx,e.textDirection)}},_getLegendItemAt:function(t,e){var n,i,a,r=this;if(t>=r.left&&t<=r.right&&e>=r.top&&e<=r.bottom)for(a=r.legendHitBoxes,n=0;n<a.length;++n)if(t>=(i=a[n]).left&&t<=i.left+i.width&&e>=i.top&&e<=i.top+i.height)return r.legendItems[n];return null},handleEvent:function(t){var e,n=this,i=n.options,a="mouseup"===t.type?"click":t.type;if("mousemove"===a){if(!i.onHover&&!i.onLeave)return}else{if("click"!==a)return;if(!i.onClick)return}e=n._getLegendItemAt(t.x,t.y),"click"===a?e&&i.onClick&&i.onClick.call(n,t.native,e):(i.onLeave&&e!==n._hoveredItem&&(n._hoveredItem&&i.onLeave.call(n,t.native,n._hoveredItem),n._hoveredItem=e),i.onHover&&e&&i.onHover.call(n,t.native,e))}});function Ai(t,e){var n=new Pi({ctx:t.ctx,options:e,chart:t});ge.configure(t,n,e),ge.addBox(t,n),t.legend=n}var Di={id:"legend",_element:Pi,beforeInit:function(t){var e=t.options.legend;e&&Ai(t,e)},beforeUpdate:function(t){var e=t.options.legend,n=t.legend;e?(V.mergeIf(e,z.global.legend),n?(ge.configure(t,n,e),n.options=e):Ai(t,e)):n&&(ge.removeBox(t,n),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}},Ti=V.noop;z._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,padding:10,position:"top",text:"",weight:2e3}});var Ii=X.extend({initialize:function(t){V.extend(this,t),this.legendHitBoxes=[]},beforeUpdate:Ti,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:Ti,beforeSetDimensions:Ti,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:Ti,beforeBuildLabels:Ti,buildLabels:Ti,afterBuildLabels:Ti,beforeFit:Ti,fit:function(){var t,e=this,n=e.options,i=e.minSize={},a=e.isHorizontal();n.display?(t=(V.isArray(n.text)?n.text.length:1)*V.options._parseFont(n).lineHeight+2*n.padding,e.width=i.width=a?e.maxWidth:t,e.height=i.height=a?t:e.maxHeight):e.width=i.width=e.height=i.height=0},afterFit:Ti,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=t.options;if(n.display){var i,a,r,o=V.options._parseFont(n),s=o.lineHeight,l=s/2+n.padding,u=0,d=t.top,h=t.left,c=t.bottom,f=t.right;e.fillStyle=V.valueOrDefault(n.fontColor,z.global.defaultFontColor),e.font=o.string,t.isHorizontal()?(a=h+(f-h)/2,r=d+l,i=f-h):(a="left"===n.position?h+l:f-l,r=d+(c-d)/2,i=c-d,u=Math.PI*("left"===n.position?-.5:.5)),e.save(),e.translate(a,r),e.rotate(u),e.textAlign="center",e.textBaseline="middle";var g=n.text;if(V.isArray(g))for(var p=0,m=0;m<g.length;++m)e.fillText(g[m],0,p,i),p+=s;else e.fillText(g,0,0,i);e.restore()}}});function Fi(t,e){var n=new Ii({ctx:t.ctx,options:e,chart:t});ge.configure(t,n,e),ge.addBox(t,n),t.titleBlock=n}var Li={},Oi=ki,Ri=Di,zi={id:"title",_element:Ii,beforeInit:function(t){var e=t.options.title;e&&Fi(t,e)},beforeUpdate:function(t){var e=t.options.title,n=t.titleBlock;e?(V.mergeIf(e,z.global.title),n?(ge.configure(t,n,e),n.options=e):Fi(t,e)):n&&(ge.removeBox(t,n),delete t.titleBlock)}};for(var Ni in Li.filler=Oi,Li.legend=Ri,Li.title=zi,tn.helpers=V,function(){function t(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 e(t){return null!=t&&"none"!==t}function n(n,i,a){var r=document.defaultView,o=V._getParentNode(n),s=r.getComputedStyle(n)[i],l=r.getComputedStyle(o)[i],u=e(s),d=e(l),h=Number.POSITIVE_INFINITY;return u||d?Math.min(u?t(s,n,a):h,d?t(l,o,a):h):"none"}V.where=function(t,e){if(V.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return V.each(t,(function(t){e(t)&&n.push(t)})),n},V.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},V.findNextWhere=function(t,e,n){V.isNullOrUndef(n)&&(n=-1);for(var i=n+1;i<t.length;i++){var a=t[i];if(e(a))return a}},V.findPreviousWhere=function(t,e,n){V.isNullOrUndef(n)&&(n=t.length);for(var i=n-1;i>=0;i--){var a=t[i];if(e(a))return a}},V.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},V.almostEquals=function(t,e,n){return Math.abs(t-e)<n},V.almostWhole=function(t,e){var n=Math.round(t);return n-e<=t&&n+e>=t},V.max=function(t){return t.reduce((function(t,e){return isNaN(e)?t:Math.max(t,e)}),Number.NEGATIVE_INFINITY)},V.min=function(t){return t.reduce((function(t,e){return isNaN(e)?t:Math.min(t,e)}),Number.POSITIVE_INFINITY)},V.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0===(t=+t)||isNaN(t)?t:t>0?1:-1},V.toRadians=function(t){return t*(Math.PI/180)},V.toDegrees=function(t){return t*(180/Math.PI)},V._decimalPlaces=function(t){if(V.isFinite(t)){for(var e=1,n=0;Math.round(t*e)/e!==t;)e*=10,n++;return n}},V.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}},V.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},V.aliasPixel=function(t){return t%2==0?0:.5},V._alignPixel=function(t,e,n){var i=t.currentDevicePixelRatio,a=n/2;return Math.round((e-a)*i)/i+a},V.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),h=i*(u=isNaN(u)?0:u),c=i*(d=isNaN(d)?0:d);return{previous:{x:r.x-h*(o.x-a.x),y:r.y-h*(o.y-a.y)},next:{x:r.x+c*(o.x-a.x),y:r.y+c*(o.y-a.y)}}},V.EPSILON=Number.EPSILON||1e-14,V.splineCurveMonotone=function(t){var e,n,i,a,r,o,s,l,u,d=(t||[]).map((function(t){return{model:t._model,deltaK:0,mK:0}})),h=d.length;for(e=0;e<h;++e)if(!(i=d[e]).model.skip){if(n=e>0?d[e-1]:null,(a=e<h-1?d[e+1]:null)&&!a.model.skip){var c=a.model.x-i.model.x;i.deltaK=0!==c?(a.model.y-i.model.y)/c: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}for(e=0;e<h-1;++e)i=d[e],a=d[e+1],i.model.skip||a.model.skip||(V.almostEquals(i.deltaK,0,this.EPSILON)?i.mK=a.mK=0:(r=i.mK/i.deltaK,o=a.mK/i.deltaK,(l=Math.pow(r,2)+Math.pow(o,2))<=9||(s=3/Math.sqrt(l),i.mK=r*s*i.deltaK,a.mK=o*s*i.deltaK)));for(e=0;e<h;++e)(i=d[e]).model.skip||(n=e>0?d[e-1]:null,a=e<h-1?d[e+1]:null,n&&!n.model.skip&&(u=(i.model.x-n.model.x)/3,i.model.controlPointPreviousX=i.model.x-u,i.model.controlPointPreviousY=i.model.y-u*i.mK),a&&!a.model.skip&&(u=(a.model.x-i.model.x)/3,i.model.controlPointNextX=i.model.x+u,i.model.controlPointNextY=i.model.y+u*i.mK))},V.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]},V.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},V.niceNum=function(t,e){var n=Math.floor(V.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)},V.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)},V.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,r=t.target||t.srcElement,o=r.getBoundingClientRect(),s=a.touches;s&&s.length>0?(n=s[0].clientX,i=s[0].clientY):(n=a.clientX,i=a.clientY);var l=parseFloat(V.getStyle(r,"padding-left")),u=parseFloat(V.getStyle(r,"padding-top")),d=parseFloat(V.getStyle(r,"padding-right")),h=parseFloat(V.getStyle(r,"padding-bottom")),c=o.right-o.left-l-d,f=o.bottom-o.top-u-h;return{x:n=Math.round((n-o.left-l)/c*r.width/e.currentDevicePixelRatio),y:i=Math.round((i-o.top-u)/f*r.height/e.currentDevicePixelRatio)}},V.getConstraintWidth=function(t){return n(t,"max-width","clientWidth")},V.getConstraintHeight=function(t){return n(t,"max-height","clientHeight")},V._calculatePadding=function(t,e,n){return(e=V.getStyle(t,e)).indexOf("%")>-1?n*parseInt(e,10)/100:parseInt(e,10)},V._getParentNode=function(t){var e=t.parentNode;return e&&"[object ShadowRoot]"===e.toString()&&(e=e.host),e},V.getMaximumWidth=function(t){var e=V._getParentNode(t);if(!e)return t.clientWidth;var n=e.clientWidth,i=n-V._calculatePadding(e,"padding-left",n)-V._calculatePadding(e,"padding-right",n),a=V.getConstraintWidth(t);return isNaN(a)?i:Math.min(i,a)},V.getMaximumHeight=function(t){var e=V._getParentNode(t);if(!e)return t.clientHeight;var n=e.clientHeight,i=n-V._calculatePadding(e,"padding-top",n)-V._calculatePadding(e,"padding-bottom",n),a=V.getConstraintHeight(t);return isNaN(a)?i:Math.min(i,a)},V.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},V.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||"undefined"!=typeof window&&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||i.style.width||(i.style.height=a+"px",i.style.width=r+"px")}},V.fontString=function(t,e,n){return e+" "+t+"px "+n},V.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},r=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},r=i.garbageCollect=[],i.font=e),t.font=e;var o,s,l,u,d,h=0,c=n.length;for(o=0;o<c;o++)if(null!=(u=n[o])&&!0!==V.isArray(u))h=V.measureText(t,a,r,h,u);else if(V.isArray(u))for(s=0,l=u.length;s<l;s++)null==(d=u[s])||V.isArray(d)||(h=V.measureText(t,a,r,h,d));var f=r.length/2;if(f>n.length){for(o=0;o<f;o++)delete a[r[o]];r.splice(0,f)}return h},V.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},V.numberOfLabelLines=function(t){var e=1;return V.each(t,(function(t){V.isArray(t)&&t.length>e&&(e=t.length)})),e},V.color=k?function(t){return t instanceof CanvasGradient&&(t=z.global.defaultColor),k(t)}:function(t){return console.error("Color.js not found!"),t},V.getHoverColor=function(t){return t instanceof CanvasPattern||t instanceof CanvasGradient?t:V.color(t).saturate(.5).darken(.1).rgbString()}}(),tn._adapters=an,tn.Animation=Z,tn.animationService=$,tn.controllers=$t,tn.DatasetController=nt,tn.defaults=z,tn.Element=X,tn.elements=_t,tn.Interaction=ae,tn.layouts=ge,tn.platform=Fe,tn.plugins=Le,tn.Scale=xn,tn.scaleService=Oe,tn.Ticks=rn,tn.Tooltip=Ue,tn.helpers.each(ci,(function(t,e){tn.scaleService.registerScaleType(e,t,t._defaults)})),Li)Li.hasOwnProperty(Ni)&&tn.plugins.register(Li[Ni]);tn.platform.initialize();var Bi=tn;return"undefined"!=typeof window&&(window.Chart=tn),tn.Chart=tn,tn.Legend=Li.legend._element,tn.Title=Li.title._element,tn.pluginService=tn.plugins,tn.PluginBase=tn.Element.extend({}),tn.canvasHelpers=tn.helpers.canvas,tn.layoutService=tn.layouts,tn.LinearScaleBase=Sn,tn.helpers.each(["Bar","Bubble","Doughnut","Line","PolarArea","Radar","Scatter"],(function(t){tn[t]=function(e,n){return new tn(e,tn.helpers.merge(n||{},{type:t.charAt(0).toLowerCase()+t.slice(1)}))}})),Bi}));
 
lib/Chart_js/bower.json DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "name": "Chart.js",
3
- "version": "1.0.1-beta.4",
4
- "description": "Simple HTML5 Charts using the canvas element",
5
- "homepage": "https://github.com/nnnick/Chart.js",
6
- "author": "nnnick",
7
- "main": [
8
- "Chart.min.js"
9
- ],
10
- "dependencies": {}
11
- }
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/docs/00-Getting-Started.md DELETED
@@ -1,200 +0,0 @@
1
- ---
2
- title: Getting started
3
- anchor: getting-started
4
- ---
5
-
6
- ###Include Chart.js
7
-
8
- First we need to include the Chart.js library on the page. The library occupies a global variable of `Chart`.
9
-
10
- ```html
11
- <script src="Chart.js"></script>
12
- ```
13
-
14
- Alternatively, if you're using an AMD loader for JavaScript modules, that is also supported in the Chart.js core. Please note: the library will still occupy a global variable of `Chart`, even if it detects `define` and `define.amd`. If this is a problem, you can call `noConflict` to restore the global Chart variable to it's previous owner.
15
-
16
- ```javascript
17
- // Using requirejs
18
- require(['path/to/Chartjs'], function(Chart){
19
- // Use Chart.js as normal here.
20
-
21
- // Chart.noConflict restores the Chart global variable to it's previous owner
22
- // The function returns what was previously Chart, allowing you to reassign.
23
- var Chartjs = Chart.noConflict();
24
-
25
- });
26
- ```
27
-
28
- You can also grab Chart.js using bower:
29
-
30
- ```bash
31
- bower install chartjs --save
32
- ```
33
-
34
- ###Creating a chart
35
-
36
- To create a chart, we need to instantiate the `Chart` class. To do this, we need to pass in the 2d context of where we want to draw the chart. Here's an example.
37
-
38
- ```html
39
- <canvas id="myChart" width="400" height="400"></canvas>
40
- ```
41
-
42
- ```javascript
43
- // Get the context of the canvas element we want to select
44
- var ctx = document.getElementById("myChart").getContext("2d");
45
- var myNewChart = new Chart(ctx).PolarArea(data);
46
- ```
47
-
48
- We can also get the context of our canvas with jQuery. To do this, we need to get the DOM node out of the jQuery collection, and call the `getContext("2d")` method on that.
49
-
50
- ```javascript
51
- // Get context with jQuery - using jQuery's .get() method.
52
- var ctx = $("#myChart").get(0).getContext("2d");
53
- // This will get the first returned node in the jQuery collection.
54
- var myNewChart = new Chart(ctx);
55
- ```
56
-
57
- After we've instantiated the Chart class on the canvas we want to draw on, Chart.js will handle the scaling for retina displays.
58
-
59
- With the Chart class set up, we can go on to create one of the charts Chart.js has available. In the example below, we would be drawing a Polar area chart.
60
-
61
- ```javascript
62
- new Chart(ctx).PolarArea(data, options);
63
- ```
64
-
65
- We call a method of the name of the chart we want to create. We pass in the data for that chart type, and the options for that chart as parameters. Chart.js will merge the global defaults with chart type specific defaults, then merge any options passed in as a second argument after data.
66
-
67
- ###Global chart configuration
68
-
69
- This concept was introduced in Chart.js 1.0 to keep configuration DRY, and allow for changing options globally across chart types, avoiding the need to specify options for each instance, or the default for a particular chart type.
70
-
71
- ```javascript
72
- Chart.defaults.global = {
73
- // Boolean - Whether to animate the chart
74
- animation: true,
75
-
76
- // Number - Number of animation steps
77
- animationSteps: 60,
78
-
79
- // String - Animation easing effect
80
- animationEasing: "easeOutQuart",
81
-
82
- // Boolean - If we should show the scale at all
83
- showScale: true,
84
-
85
- // Boolean - If we want to override with a hard coded scale
86
- scaleOverride: false,
87
-
88
- // ** Required if scaleOverride is true **
89
- // Number - The number of steps in a hard coded scale
90
- scaleSteps: null,
91
- // Number - The value jump in the hard coded scale
92
- scaleStepWidth: null,
93
- // Number - The scale starting value
94
- scaleStartValue: null,
95
-
96
- // String - Colour of the scale line
97
- scaleLineColor: "rgba(0,0,0,.1)",
98
-
99
- // Number - Pixel width of the scale line
100
- scaleLineWidth: 1,
101
-
102
- // Boolean - Whether to show labels on the scale
103
- scaleShowLabels: true,
104
-
105
- // Interpolated JS string - can access value
106
- scaleLabel: "<%=value%>",
107
-
108
- // Boolean - Whether the scale should stick to integers, not floats even if drawing space is there
109
- scaleIntegersOnly: true,
110
-
111
- // Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
112
- scaleBeginAtZero: false,
113
-
114
- // String - Scale label font declaration for the scale label
115
- scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
116
-
117
- // Number - Scale label font size in pixels
118
- scaleFontSize: 12,
119
-
120
- // String - Scale label font weight style
121
- scaleFontStyle: "normal",
122
-
123
- // String - Scale label font colour
124
- scaleFontColor: "#666",
125
-
126
- // Boolean - whether or not the chart should be responsive and resize when the browser does.
127
- responsive: false,
128
-
129
- // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
130
- maintainAspectRatio: true,
131
-
132
- // Boolean - Determines whether to draw tooltips on the canvas or not
133
- showTooltips: true,
134
-
135
- // Array - Array of string names to attach tooltip events
136
- tooltipEvents: ["mousemove", "touchstart", "touchmove"],
137
-
138
- // String - Tooltip background colour
139
- tooltipFillColor: "rgba(0,0,0,0.8)",
140
-
141
- // String - Tooltip label font declaration for the scale label
142
- tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
143
-
144
- // Number - Tooltip label font size in pixels
145
- tooltipFontSize: 14,
146
-
147
- // String - Tooltip font weight style
148
- tooltipFontStyle: "normal",
149
-
150
- // String - Tooltip label font colour
151
- tooltipFontColor: "#fff",
152
-
153
- // String - Tooltip title font declaration for the scale label
154
- tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
155
-
156
- // Number - Tooltip title font size in pixels
157
- tooltipTitleFontSize: 14,
158
-
159
- // String - Tooltip title font weight style
160
- tooltipTitleFontStyle: "bold",
161
-
162
- // String - Tooltip title font colour
163
- tooltipTitleFontColor: "#fff",
164
-
165
- // Number - pixel width of padding around tooltip text
166
- tooltipYPadding: 6,
167
-
168
- // Number - pixel width of padding around tooltip text
169
- tooltipXPadding: 6,
170
-
171
- // Number - Size of the caret on the tooltip
172
- tooltipCaretSize: 8,
173
-
174
- // Number - Pixel radius of the tooltip border
175
- tooltipCornerRadius: 6,
176
-
177
- // Number - Pixel offset from point x to tooltip edge
178
- tooltipXOffset: 10,
179
- {% raw %}
180
- // String - Template string for single tooltips
181
- tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>",
182
- {% endraw %}
183
- // String - Template string for single tooltips
184
- multiTooltipTemplate: "<%= value %>",
185
-
186
- // Function - Will fire on animation progression.
187
- onAnimationProgress: function(){},
188
-
189
- // Function - Will fire on animation completion.
190
- onAnimationComplete: function(){}
191
- }
192
- ```
193
-
194
- If for example, you wanted all charts created to be responsive, and resize when the browser window does, the following setting can be changed:
195
-
196
- ```javascript
197
- Chart.defaults.global.responsive = true;
198
- ```
199
-
200
- Now, every time we create a chart, `options.responsive` will be `true`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/docs/01-Line-Chart.md DELETED
@@ -1,160 +0,0 @@
1
- ---
2
- title: Line Chart
3
- anchor: line-chart
4
- ---
5
- ###Introduction
6
- A line chart is a way of plotting data points on a line.
7
-
8
- Often, it is used to show trend data, and the comparison of two data sets.
9
-
10
- <div class="canvas-holder">
11
- <canvas width="250" height="125"></canvas>
12
- </div>
13
-
14
- ###Example usage
15
- ```javascript
16
- var myLineChart = new Chart(ctx).Line(data, options);
17
- ```
18
- ###Data structure
19
-
20
- ```javascript
21
- var data = {
22
- labels: ["January", "February", "March", "April", "May", "June", "July"],
23
- datasets: [
24
- {
25
- label: "My First dataset",
26
- fillColor: "rgba(220,220,220,0.2)",
27
- strokeColor: "rgba(220,220,220,1)",
28
- pointColor: "rgba(220,220,220,1)",
29
- pointStrokeColor: "#fff",
30
- pointHighlightFill: "#fff",
31
- pointHighlightStroke: "rgba(220,220,220,1)",
32
- data: [65, 59, 80, 81, 56, 55, 40]
33
- },
34
- {
35
- label: "My Second dataset",
36
- fillColor: "rgba(151,187,205,0.2)",
37
- strokeColor: "rgba(151,187,205,1)",
38
- pointColor: "rgba(151,187,205,1)",
39
- pointStrokeColor: "#fff",
40
- pointHighlightFill: "#fff",
41
- pointHighlightStroke: "rgba(151,187,205,1)",
42
- data: [28, 48, 40, 19, 86, 27, 90]
43
- }
44
- ]
45
- };
46
- ```
47
-
48
- The line chart requires an array of labels for each of the data points. This is shown on the X axis.
49
- The data for line charts is broken up into an array of datasets. Each dataset has a colour for the fill, a colour for the line and colours for the points and strokes of the points. These colours are strings just like CSS. You can use RGBA, RGB, HEX or HSL notation.
50
-
51
- The label key on each dataset is optional, and can be used when generating a scale for the chart.
52
-
53
- ### Chart options
54
-
55
- These are the customisation options specific to Line charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
56
-
57
- ```javascript
58
- {
59
-
60
- ///Boolean - Whether grid lines are shown across the chart
61
- scaleShowGridLines : true,
62
-
63
- //String - Colour of the grid lines
64
- scaleGridLineColor : "rgba(0,0,0,.05)",
65
-
66
- //Number - Width of the grid lines
67
- scaleGridLineWidth : 1,
68
-
69
- //Boolean - Whether the line is curved between points
70
- bezierCurve : true,
71
-
72
- //Number - Tension of the bezier curve between points
73
- bezierCurveTension : 0.4,
74
-
75
- //Boolean - Whether to show a dot for each point
76
- pointDot : true,
77
-
78
- //Number - Radius of each point dot in pixels
79
- pointDotRadius : 4,
80
-
81
- //Number - Pixel width of point dot stroke
82
- pointDotStrokeWidth : 1,
83
-
84
- //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
85
- pointHitDetectionRadius : 20,
86
-
87
- //Boolean - Whether to show a stroke for datasets
88
- datasetStroke : true,
89
-
90
- //Number - Pixel width of dataset stroke
91
- datasetStrokeWidth : 2,
92
-
93
- //Boolean - Whether to fill the dataset with a colour
94
- datasetFill : true,
95
- {% raw %}
96
- //String - A legend template
97
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
98
- {% endraw %}
99
- };
100
- ```
101
-
102
- You can override these for your `Chart` instance by passing a second argument into the `Line` method as an object with the keys you want to override.
103
-
104
- For example, we could have a line chart without bezier curves between points by doing the following:
105
-
106
- ```javascript
107
- new Chart(ctx).Line(data, {
108
- bezierCurve: false
109
- });
110
- // This will create a chart with all of the default options, merged from the global config,
111
- // and the Line chart defaults, but this particular instance will have `bezierCurve` set to false.
112
- ```
113
-
114
- We can also change these defaults values for each Line type that is created, this object is available at `Chart.defaults.Line`.
115
-
116
-
117
- ### Prototype methods
118
-
119
- #### .getPointsAtEvent( event )
120
-
121
- Calling `getPointsAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the point elements that are at that the same position of that event.
122
-
123
- ```javascript
124
- canvas.onclick = function(evt){
125
- var activePoints = myLineChart.getPointsAtEvent(evt);
126
- // => activePoints is an array of points on the canvas that are at the same position as the click event.
127
- };
128
- ```
129
-
130
- This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.
131
-
132
- #### .update( )
133
-
134
- Calling `update()` on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.
135
-
136
- ```javascript
137
- myLineChart.datasets[0].points[2].value = 50;
138
- // Would update the first dataset's value of 'March' to be 50
139
- myLineChart.update();
140
- // Calling update now animates the position of March from 90 to 50.
141
- ```
142
-
143
- #### .addData( valuesArray, label )
144
-
145
- Calling `addData(valuesArray, label)` on your Chart instance passing an array of values for each dataset, along with a label for those points.
146
-
147
- ```javascript
148
- // The values array passed into addData should be one for each dataset in the chart
149
- myLineChart.addData([40, 60], "August");
150
- // This new data will now animate at the end of the chart.
151
- ```
152
-
153
- #### .removeData( )
154
-
155
- Calling `removeData()` on your Chart instance will remove the first value for all datasets on the chart.
156
-
157
- ```javascript
158
- myLineChart.removeData();
159
- // The chart will remove the first point and animate other points into place
160
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/docs/02-Bar-Chart.md DELETED
@@ -1,143 +0,0 @@
1
- ---
2
- title: Bar Chart
3
- anchor: bar-chart
4
- ---
5
-
6
- ### Introduction
7
- A bar chart is a way of showing data as bars.
8
-
9
- It is sometimes used to show trend data, and the comparison of multiple data sets side by side.
10
-
11
- <div class="canvas-holder">
12
- <canvas width="250" height="125"></canvas>
13
- </div>
14
-
15
- ### Example usage
16
- ```javascript
17
- var myBarChart = new Chart(ctx).Bar(data, options);
18
- ```
19
-
20
- ### Data structure
21
-
22
- ```javascript
23
- var data = {
24
- labels: ["January", "February", "March", "April", "May", "June", "July"],
25
- datasets: [
26
- {
27
- label: "My First dataset",
28
- fillColor: "rgba(220,220,220,0.5)",
29
- strokeColor: "rgba(220,220,220,0.8)",
30
- highlightFill: "rgba(220,220,220,0.75)",
31
- highlightStroke: "rgba(220,220,220,1)",
32
- data: [65, 59, 80, 81, 56, 55, 40]
33
- },
34
- {
35
- label: "My Second dataset",
36
- fillColor: "rgba(151,187,205,0.5)",
37
- strokeColor: "rgba(151,187,205,0.8)",
38
- highlightFill: "rgba(151,187,205,0.75)",
39
- highlightStroke: "rgba(151,187,205,1)",
40
- data: [28, 48, 40, 19, 86, 27, 90]
41
- }
42
- ]
43
- };
44
- ```
45
- The bar chart has the a very similar data structure to the line chart, and has an array of datasets, each with colours and an array of data. Again, colours are in CSS format.
46
- We have an array of labels too for display. In the example, we are showing the same data as the previous line chart example.
47
-
48
- The label key on each dataset is optional, and can be used when generating a scale for the chart.
49
-
50
- ### Chart Options
51
-
52
- These are the customisation options specific to Bar charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
53
-
54
- ```javascript
55
- {
56
- //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
57
- scaleBeginAtZero : true,
58
-
59
- //Boolean - Whether grid lines are shown across the chart
60
- scaleShowGridLines : true,
61
-
62
- //String - Colour of the grid lines
63
- scaleGridLineColor : "rgba(0,0,0,.05)",
64
-
65
- //Number - Width of the grid lines
66
- scaleGridLineWidth : 1,
67
-
68
- //Boolean - If there is a stroke on each bar
69
- barShowStroke : true,
70
-
71
- //Number - Pixel width of the bar stroke
72
- barStrokeWidth : 2,
73
-
74
- //Number - Spacing between each of the X value sets
75
- barValueSpacing : 5,
76
-
77
- //Number - Spacing between data sets within X values
78
- barDatasetSpacing : 1,
79
- {% raw %}
80
- //String - A legend template
81
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
82
- {% endraw %}
83
- }
84
- ```
85
-
86
- You can override these for your `Chart` instance by passing a second argument into the `Bar` method as an object with the keys you want to override.
87
-
88
- For example, we could have a bar chart without a stroke on each bar by doing the following:
89
-
90
- ```javascript
91
- new Chart(ctx).Bar(data, {
92
- barShowStroke: false
93
- });
94
- // This will create a chart with all of the default options, merged from the global config,
95
- // and the Bar chart defaults but this particular instance will have `barShowStroke` set to false.
96
- ```
97
-
98
- We can also change these defaults values for each Bar type that is created, this object is available at `Chart.defaults.Bar`.
99
-
100
- ### Prototype methods
101
-
102
- #### .getBarsAtEvent( event )
103
-
104
- Calling `getBarsAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the bar elements that are at that the same position of that event.
105
-
106
- ```javascript
107
- canvas.onclick = function(evt){
108
- var activeBars = myBarChart.getBarsAtEvent(evt);
109
- // => activeBars is an array of bars on the canvas that are at the same position as the click event.
110
- };
111
- ```
112
-
113
- This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.
114
-
115
- #### .update( )
116
-
117
- Calling `update()` on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.
118
-
119
- ```javascript
120
- myBarChart.datasets[0].bars[2].value = 50;
121
- // Would update the first dataset's value of 'March' to be 50
122
- myBarChart.update();
123
- // Calling update now animates the position of March from 90 to 50.
124
- ```
125
-
126
- #### .addData( valuesArray, label )
127
-
128
- Calling `addData(valuesArray, label)` on your Chart instance passing an array of values for each dataset, along with a label for those bars.
129
-
130
- ```javascript
131
- // The values array passed into addData should be one for each dataset in the chart
132
- myBarChart.addData([40, 60], "August");
133
- // The new data will now animate at the end of the chart.
134
- ```
135
-
136
- #### .removeData( )
137
-
138
- Calling `removeData()` on your Chart instance will remove the first value for all datasets on the chart.
139
-
140
- ```javascript
141
- myBarChart.removeData();
142
- // The chart will now animate and remove the first bar
143
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/docs/03-Radar-Chart.md DELETED
@@ -1,177 +0,0 @@
1
- ---
2
- title: Radar Chart
3
- anchor: radar-chart
4
- ---
5
-
6
- ###Introduction
7
- A radar chart is a way of showing multiple data points and the variation between them.
8
-
9
- They are often useful for comparing the points of two or more different data sets.
10
-
11
- <div class="canvas-holder">
12
- <canvas width="250" height="125"></canvas>
13
- </div>
14
-
15
- ###Example usage
16
-
17
- ```javascript
18
- var myRadarChart = new Chart(ctx).Radar(data, options);
19
- ```
20
-
21
- ###Data structure
22
- ```javascript
23
- var data = {
24
- labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
25
- datasets: [
26
- {
27
- label: "My First dataset",
28
- fillColor: "rgba(220,220,220,0.2)",
29
- strokeColor: "rgba(220,220,220,1)",
30
- pointColor: "rgba(220,220,220,1)",
31
- pointStrokeColor: "#fff",
32
- pointHighlightFill: "#fff",
33
- pointHighlightStroke: "rgba(220,220,220,1)",
34
- data: [65, 59, 90, 81, 56, 55, 40]
35
- },
36
- {
37
- label: "My Second dataset",
38
- fillColor: "rgba(151,187,205,0.2)",
39
- strokeColor: "rgba(151,187,205,1)",
40
- pointColor: "rgba(151,187,205,1)",
41
- pointStrokeColor: "#fff",
42
- pointHighlightFill: "#fff",
43
- pointHighlightStroke: "rgba(151,187,205,1)",
44
- data: [28, 48, 40, 19, 96, 27, 100]
45
- }
46
- ]
47
- };
48
- ```
49
- For a radar chart, to provide context of what each point means, we include an array of strings that show around each point in the chart.
50
- For the radar chart data, we have an array of datasets. Each of these is an object, with a fill colour, a stroke colour, a colour for the fill of each point, and a colour for the stroke of each point. We also have an array of data values.
51
-
52
- The label key on each dataset is optional, and can be used when generating a scale for the chart.
53
-
54
- ### Chart options
55
-
56
- These are the customisation options specific to Radar charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
57
-
58
-
59
- ```javascript
60
- {
61
- //Boolean - Whether to show lines for each scale point
62
- scaleShowLine : true,
63
-
64
- //Boolean - Whether we show the angle lines out of the radar
65
- angleShowLineOut : true,
66
-
67
- //Boolean - Whether to show labels on the scale
68
- scaleShowLabels : false,
69
-
70
- // Boolean - Whether the scale should begin at zero
71
- scaleBeginAtZero : true,
72
-
73
- //String - Colour of the angle line
74
- angleLineColor : "rgba(0,0,0,.1)",
75
-
76
- //Number - Pixel width of the angle line
77
- angleLineWidth : 1,
78
-
79
- //String - Point label font declaration
80
- pointLabelFontFamily : "'Arial'",
81
-
82
- //String - Point label font weight
83
- pointLabelFontStyle : "normal",
84
-
85
- //Number - Point label font size in pixels
86
- pointLabelFontSize : 10,
87
-
88
- //String - Point label font colour
89
- pointLabelFontColor : "#666",
90
-
91
- //Boolean - Whether to show a dot for each point
92
- pointDot : true,
93
-
94
- //Number - Radius of each point dot in pixels
95
- pointDotRadius : 3,
96
-
97
- //Number - Pixel width of point dot stroke
98
- pointDotStrokeWidth : 1,
99
-
100
- //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
101
- pointHitDetectionRadius : 20,
102
-
103
- //Boolean - Whether to show a stroke for datasets
104
- datasetStroke : true,
105
-
106
- //Number - Pixel width of dataset stroke
107
- datasetStrokeWidth : 2,
108
-
109
- //Boolean - Whether to fill the dataset with a colour
110
- datasetFill : true,
111
- {% raw %}
112
- //String - A legend template
113
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
114
- {% endraw %}
115
- }
116
- ```
117
-
118
-
119
- You can override these for your `Chart` instance by passing a second argument into the `Radar` method as an object with the keys you want to override.
120
-
121
- For example, we could have a radar chart without a point for each on piece of data by doing the following:
122
-
123
- ```javascript
124
- new Chart(ctx).Radar(data, {
125
- pointDot: false
126
- });
127
- // This will create a chart with all of the default options, merged from the global config,
128
- // and the Bar chart defaults but this particular instance will have `pointDot` set to false.
129
- ```
130
-
131
- We can also change these defaults values for each Radar type that is created, this object is available at `Chart.defaults.Radar`.
132
-
133
-
134
- ### Prototype methods
135
-
136
- #### .getPointsAtEvent( event )
137
-
138
- Calling `getPointsAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the point elements that are at that the same position of that event.
139
-
140
- ```javascript
141
- canvas.onclick = function(evt){
142
- var activePoints = myRadarChart.getPointsAtEvent(evt);
143
- // => activePoints is an array of points on the canvas that are at the same position as the click event.
144
- };
145
- ```
146
-
147
- This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.
148
-
149
- #### .update( )
150
-
151
- Calling `update()` on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.
152
-
153
- ```javascript
154
- myRadarChart.datasets[0].points[2].value = 50;
155
- // Would update the first dataset's value of 'Sleeping' to be 50
156
- myRadarChart.update();
157
- // Calling update now animates the position of Sleeping from 90 to 50.
158
- ```
159
-
160
- #### .addData( valuesArray, label )
161
-
162
- Calling `addData(valuesArray, label)` on your Chart instance passing an array of values for each dataset, along with a label for those points.
163
-
164
- ```javascript
165
- // The values array passed into addData should be one for each dataset in the chart
166
- myRadarChart.addData([40, 60], "Dancing");
167
- // The new data will now animate at the end of the chart.
168
- ```
169
-
170
- #### .removeData( )
171
-
172
- Calling `removeData()` on your Chart instance will remove the first value for all datasets on the chart.
173
-
174
- ```javascript
175
- myRadarChart.removeData();
176
- // Other points will now animate to their correct positions.
177
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/docs/04-Polar-Area-Chart.md DELETED
@@ -1,172 +0,0 @@
1
- ---
2
- title: Polar Area Chart
3
- anchor: polar-area-chart
4
- ---
5
- ### Introduction
6
- Polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value.
7
-
8
- This type of chart is often useful when we want to show a comparison data similar to a pie chart, but also show a scale of values for context.
9
-
10
- <div class="canvas-holder">
11
- <canvas width="250" height="125"></canvas>
12
- </div>
13
-
14
- ### Example usage
15
-
16
- ```javascript
17
- new Chart(ctx).PolarArea(data, options);
18
- ```
19
-
20
- ### Data structure
21
-
22
- ```javascript
23
- var data = [
24
- {
25
- value: 300,
26
- color:"#F7464A",
27
- highlight: "#FF5A5E",
28
- label: "Red"
29
- },
30
- {
31
- value: 50,
32
- color: "#46BFBD",
33
- highlight: "#5AD3D1",
34
- label: "Green"
35
- },
36
- {
37
- value: 100,
38
- color: "#FDB45C",
39
- highlight: "#FFC870",
40
- label: "Yellow"
41
- },
42
- {
43
- value: 40,
44
- color: "#949FB1",
45
- highlight: "#A8B3C5",
46
- label: "Grey"
47
- },
48
- {
49
- value: 120,
50
- color: "#4D5360",
51
- highlight: "#616774",
52
- label: "Dark Grey"
53
- }
54
-
55
- ];
56
- ```
57
- As you can see, for the chart data you pass in an array of objects, with a value and a colour. The value attribute should be a number, while the color attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.
58
-
59
- ### Chart options
60
-
61
- These are the customisation options specific to Polar Area charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
62
-
63
- ```javascript
64
- {
65
- //Boolean - Show a backdrop to the scale label
66
- scaleShowLabelBackdrop : true,
67
-
68
- //String - The colour of the label backdrop
69
- scaleBackdropColor : "rgba(255,255,255,0.75)",
70
-
71
- // Boolean - Whether the scale should begin at zero
72
- scaleBeginAtZero : true,
73
-
74
- //Number - The backdrop padding above & below the label in pixels
75
- scaleBackdropPaddingY : 2,
76
-
77
- //Number - The backdrop padding to the side of the label in pixels
78
- scaleBackdropPaddingX : 2,
79
-
80
- //Boolean - Show line for each value in the scale
81
- scaleShowLine : true,
82
-
83
- //Boolean - Stroke a line around each segment in the chart
84
- segmentShowStroke : true,
85
-
86
- //String - The colour of the stroke on each segement.
87
- segmentStrokeColor : "#fff",
88
-
89
- //Number - The width of the stroke value in pixels
90
- segmentStrokeWidth : 2,
91
-
92
- //Number - Amount of animation steps
93
- animationSteps : 100,
94
-
95
- //String - Animation easing effect.
96
- animationEasing : "easeOutBounce",
97
-
98
- //Boolean - Whether to animate the rotation of the chart
99
- animateRotate : true,
100
-
101
- //Boolean - Whether to animate scaling the chart from the centre
102
- animateScale : false,
103
- {% raw %}
104
- //String - A legend template
105
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
106
- {% endraw %}
107
- }
108
- ```
109
-
110
- You can override these for your `Chart` instance by passing a second argument into the `PolarArea` method as an object with the keys you want to override.
111
-
112
- For example, we could have a polar area chart with a black stroke on each segment like so:
113
-
114
- ```javascript
115
- new Chart(ctx).PolarArea(data, {
116
- segmentStrokeColor: "#000000"
117
- });
118
- // This will create a chart with all of the default options, merged from the global config,
119
- // and the PolarArea chart defaults but this particular instance will have `segmentStrokeColor` set to `"#000000"`.
120
- ```
121
-
122
- We can also change these defaults values for each PolarArea type that is created, this object is available at `Chart.defaults.PolarArea`.
123
-
124
- ### Prototype methods
125
-
126
- #### .getSegmentsAtEvent( event )
127
-
128
- Calling `getSegmentsAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the segment elements that are at that the same position of that event.
129
-
130
- ```javascript
131
- canvas.onclick = function(evt){
132
- var activePoints = myPolarAreaChart.getSegmentsAtEvent(evt);
133
- // => activePoints is an array of segments on the canvas that are at the same position as the click event.
134
- };
135
- ```
136
-
137
- This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.
138
-
139
- #### .update( )
140
-
141
- Calling `update()` on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.
142
-
143
- ```javascript
144
- myPolarAreaChart.segments[1].value = 10;
145
- // Would update the first dataset's value of 'Green' to be 10
146
- myPolarAreaChart.update();
147
- // Calling update now animates the position of Green from 50 to 10.
148
- ```
149
-
150
- #### .addData( segmentData, index )
151
-
152
- Calling `addData(segmentData, index)` on your Chart instance passing an object in the same format as in the constructor. There is an option second argument of 'index', this determines at what index the new segment should be inserted into the chart.
153
-
154
- ```javascript
155
- // An object in the same format as the original data source
156
- myPolarAreaChart.addData({
157
- value: 130,
158
- color: "#B48EAD",
159
- highlight: "#C69CBE",
160
- label: "Purple"
161
- });
162
- // The new segment will now animate in.
163
- ```
164
-
165
- #### .removeData( index )
166
-
167
- Calling `removeData(index)` on your Chart instance will remove segment at that particular index. If none is provided, it will default to the last segment.
168
-
169
- ```javascript
170
- myPolarAreaChart.removeData();
171
- // Other segments will update to fill the empty space left.
172
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/docs/05-Pie-Doughnut-Chart.md DELETED
@@ -1,158 +0,0 @@
1
- ---
2
- title: Pie & Doughnut Charts
3
- anchor: doughnut-pie-chart
4
- ---
5
- ###Introduction
6
- Pie and doughnut charts are probably the most commonly used chart there are. They are divided into segments, the arc of each segment shows the proportional value of each piece of data.
7
-
8
- They are excellent at showing the relational proportions between data.
9
-
10
- Pie and doughnut charts are effectively the same class in Chart.js, but have one different default value - their `percentageInnerCutout`. This equates what percentage of the inner should be cut out. This defaults to `0` for pie charts, and `50` for doughnuts.
11
-
12
- They are also registered under two aliases in the `Chart` core. Other than their different default value, and different alias, they are exactly the same.
13
-
14
- <div class="canvas-holder half">
15
- <canvas width="250" height="125"></canvas>
16
- </div>
17
-
18
- <div class="canvas-holder half">
19
- <canvas width="250" height="125"></canvas>
20
- </div>
21
-
22
-
23
- ### Example usage
24
-
25
- ```javascript
26
- // For a pie chart
27
- var myPieChart = new Chart(ctx[0]).Pie(data,options);
28
-
29
- // And for a doughnut chart
30
- var myDoughnutChart = new Chart(ctx[1]).Doughnut(data,options);
31
- ```
32
-
33
- ### Data structure
34
-
35
- ```javascript
36
- var data = [
37
- {
38
- value: 300,
39
- color:"#F7464A",
40
- highlight: "#FF5A5E",
41
- label: "Red"
42
- },
43
- {
44
- value: 50,
45
- color: "#46BFBD",
46
- highlight: "#5AD3D1",
47
- label: "Green"
48
- },
49
- {
50
- value: 100,
51
- color: "#FDB45C",
52
- highlight: "#FFC870",
53
- label: "Yellow"
54
- }
55
- ]
56
- ```
57
-
58
- For a pie chart, you must pass in an array of objects with a value and a color property. The value attribute should be a number, Chart.js will total all of the numbers and calculate the relative proportion of each. The color attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.
59
-
60
- ### Chart options
61
-
62
- These are the customisation options specific to Pie & Doughnut charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
63
-
64
- ```javascript
65
- {
66
- //Boolean - Whether we should show a stroke on each segment
67
- segmentShowStroke : true,
68
-
69
- //String - The colour of each segment stroke
70
- segmentStrokeColor : "#fff",
71
-
72
- //Number - The width of each segment stroke
73
- segmentStrokeWidth : 2,
74
-
75
- //Number - The percentage of the chart that we cut out of the middle
76
- percentageInnerCutout : 50, // This is 0 for Pie charts
77
-
78
- //Number - Amount of animation steps
79
- animationSteps : 100,
80
-
81
- //String - Animation easing effect
82
- animationEasing : "easeOutBounce",
83
-
84
- //Boolean - Whether we animate the rotation of the Doughnut
85
- animateRotate : true,
86
-
87
- //Boolean - Whether we animate scaling the Doughnut from the centre
88
- animateScale : false,
89
- {% raw %}
90
- //String - A legend template
91
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
92
- {% endraw %}
93
- }
94
- ```
95
- You can override these for your `Chart` instance by passing a second argument into the `Doughnut` method as an object with the keys you want to override.
96
-
97
- For example, we could have a doughnut chart that animates by scaling out from the centre like so:
98
-
99
- ```javascript
100
- new Chart(ctx).Doughnut(data, {
101
- animateScale: true
102
- });
103
- // This will create a chart with all of the default options, merged from the global config,
104
- // and the Doughnut chart defaults but this particular instance will have `animateScale` set to `true`.
105
- ```
106
-
107
- We can also change these default values for each Doughnut type that is created, this object is available at `Chart.defaults.Doughnut`. Pie charts also have a clone of these defaults available to change at `Chart.defaults.Pie`, with the only difference being `percentageInnerCutout` being set to 0.
108
-
109
- ### Prototype methods
110
-
111
- #### .getSegmentsAtEvent( event )
112
-
113
- Calling `getSegmentsAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the segment elements that are at the same position of that event.
114
-
115
- ```javascript
116
- canvas.onclick = function(evt){
117
- var activePoints = myDoughnutChart.getSegmentsAtEvent(evt);
118
- // => activePoints is an array of segments on the canvas that are at the same position as the click event.
119
- };
120
- ```
121
-
122
- This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.
123
-
124
- #### .update( )
125
-
126
- Calling `update()` on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.
127
-
128
- ```javascript
129
- myDoughnutChart.segments[1].value = 10;
130
- // Would update the first dataset's value of 'Green' to be 10
131
- myDoughnutChart.update();
132
- // Calling update now animates the circumference of the segment 'Green' from 50 to 10.
133
- // and transitions other segment widths
134
- ```
135
-
136
- #### .addData( segmentData, index )
137
-
138
- Calling `addData(segmentData, index)` on your Chart instance passing an object in the same format as in the constructor. There is an optional second argument of 'index', this determines at what index the new segment should be inserted into the chart.
139
-
140
- ```javascript
141
- // An object in the same format as the original data source
142
- myDoughnutChart.addData({
143
- value: 130,
144
- color: "#B48EAD",
145
- highlight: "#C69CBE",
146
- label: "Purple"
147
- });
148
- // The new segment will now animate in.
149
- ```
150
-
151
- #### .removeData( index )
152
-
153
- Calling `removeData(index)` on your Chart instance will remove segment at that particular index. If none is provided, it will default to the last segment.
154
-
155
- ```javascript
156
- myDoughnutChart.removeData();
157
- // Other segments will update to fill the empty space left.
158
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/docs/06-Advanced.md DELETED
@@ -1,152 +0,0 @@
1
- ---
2
- title: Advanced usage
3
- anchor: advanced-usage
4
- ---
5
-
6
-
7
- ### Prototype methods
8
-
9
- For each chart, there are a set of global prototype methods on the shared `ChartType` which you may find useful. These are available on all charts created with Chart.js, but for the examples, let's use a line chart we've made.
10
-
11
- ```javascript
12
- // For example:
13
- var myLineChart = new Chart(ctx).Line(data);
14
- ```
15
-
16
- #### .clear()
17
-
18
- Will clear the chart canvas. Used extensively internally between animation frames, but you might find it useful.
19
-
20
- ```javascript
21
- // Will clear the canvas that myLineChart is drawn on
22
- myLineChart.clear();
23
- // => returns 'this' for chainability
24
- ```
25
-
26
- #### .stop()
27
-
28
- Use this to stop any current animation loop. This will pause the chart during any current animation frame. Call `.render()` to re-animate.
29
-
30
- ```javascript
31
- // Stops the charts animation loop at its current frame
32
- myLineChart.stop();
33
- // => returns 'this' for chainability
34
- ```
35
-
36
- #### .resize()
37
-
38
- Use this to manually resize the canvas element. This is run each time the browser is resized, but you can call this method manually if you change the size of the canvas nodes container element.
39
-
40
- ```javascript
41
- // Resizes & redraws to fill its container element
42
- myLineChart.resize();
43
- // => returns 'this' for chainability
44
- ```
45
-
46
- #### .destroy()
47
-
48
- Use this to destroy any chart instances that are created. This will clean up any references stored to the chart object within Chart.js, along with any associated event listeners attached by Chart.js.
49
-
50
- ```javascript
51
- // Destroys a specific chart instance
52
- myLineChart.destroy();
53
- ```
54
-
55
- #### .toBase64Image()
56
-
57
- This returns a base 64 encoded string of the chart in it's current state.
58
-
59
- ```javascript
60
- myLineChart.toBase64Image();
61
- // => returns png data url of the image on the canvas
62
- ```
63
-
64
- #### .generateLegend()
65
-
66
- Returns an HTML string of a legend for that chart. The template for this legend is at `legendTemplate` in the chart options.
67
-
68
- ```javascript
69
- myLineChart.generateLegend();
70
- // => returns HTML string of a legend for this chart
71
- ```
72
-
73
- ### Writing new chart types
74
-
75
- Chart.js 1.0 has been rewritten to provide a platform for developers to create their own custom chart types, and be able to share and utilise them through the Chart.js API.
76
-
77
- The format is relatively simple, there are a set of utility helper methods under `Chart.helpers`, including things such as looping over collections, requesting animation frames, and easing equations.
78
-
79
- On top of this, there are also some simple base classes of Chart elements, these all extend from `Chart.Element`, and include things such as points, bars and scales.
80
-
81
- ```javascript
82
- Chart.Type.extend({
83
- // Passing in a name registers this chart in the Chart namespace
84
- name: "Scatter",
85
- // Providing a defaults will also register the deafults in the chart namespace
86
- defaults : {
87
- options: "Here",
88
- available: "at this.options"
89
- },
90
- // Initialize is fired when the chart is initialized - Data is passed in as a parameter
91
- // Config is automatically merged by the core of Chart.js, and is available at this.options
92
- initialize: function(data){
93
- this.chart.ctx // The drawing context for this chart
94
- this.chart.canvas // the canvas node for this chart
95
- },
96
- // Used to draw something on the canvas
97
- draw: function() {
98
- }
99
- });
100
-
101
- // Now we can create a new instance of our chart, using the Chart.js API
102
- new Chart(ctx).Scatter(data);
103
- // initialize is now run
104
- ```
105
-
106
- ### Extending existing chart types
107
-
108
- We can also extend existing chart types, and expose them to the API in the same way. Let's say for example, we might want to run some more code when we initialize every Line chart.
109
-
110
- ```javascript
111
- // Notice now we're extending the particular Line chart type, rather than the base class.
112
- Chart.types.Line.extend({
113
- // Passing in a name registers this chart in the Chart namespace in the same way
114
- name: "LineAlt",
115
- initialize: function(data){
116
- console.log('My Line chart extension');
117
- Chart.types.Line.prototype.initialize.apply(this, arguments);
118
- }
119
- });
120
-
121
- // Creates a line chart in the same way
122
- new Chart(ctx).LineAlt(data);
123
- // but this logs 'My Line chart extension' in the console.
124
- ```
125
-
126
- ### Community extensions
127
-
128
- - <a href="https://github.com/Regaddi/Chart.StackedBar.js" target"_blank">Stacked Bar Chart</a> by <a href="https://twitter.com/Regaddi" target="_blank">@Regaddi</a>
129
- - <a href="https://github.com/CAYdenberg/Chart.js" target"_blank">Error bars (bar and line charts)</a> by <a href="https://twitter.com/CAYdenberg" target="_blank">@CAYdenberg</a>
130
-
131
- ### Creating custom builds
132
-
133
- Chart.js uses <a href="http://gulpjs.com/" target="_blank">gulp</a> to build the library into a single JavaScript file. We can use this same build script with custom parameters in order to build a custom version.
134
-
135
- Firstly, we need to ensure development dependencies are installed. With node and npm installed, after cloning the Chart.js repo to a local directory, and navigating to that directory in the command line, we can run the following:
136
-
137
- ```bash
138
- npm install
139
- npm install -g gulp
140
- ```
141
-
142
- This will install the local development dependencies for Chart.js, along with a CLI for the JavaScript task runner <a href="http://gulpjs.com/" target="_blank">gulp</a>.
143
-
144
- Now, we can run the `gulp build` task, and pass in a comma seperated list of types as an argument to build a custom version of Chart.js with only specified chart types.
145
-
146
- Here we will create a version of Chart.js with only Line, Radar and Bar charts included:
147
-
148
- ```bash
149
- gulp build --types=Line,Radar,Bar
150
- ```
151
-
152
- This will output to the `/custom` directory, and write two files, Chart.js, and Chart.min.js with only those chart types included.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/docs/07-Notes.md DELETED
@@ -1,42 +0,0 @@
1
- ---
2
- title: Notes
3
- anchor: notes
4
- ---
5
-
6
- ### Browser support
7
- Browser support for the canvas element is available in all modern & major mobile browsers <a href="http://caniuse.com/canvas" target="_blank">(caniuse.com/canvas)</a>.
8
-
9
- For IE8 & below, I would recommend using the polyfill ExplorerCanvas - available at <a href="https://code.google.com/p/explorercanvas/" target="_blank">https://code.google.com/p/explorercanvas/</a>. It falls back to Internet explorer's format VML when canvas support is not available. Example use:
10
-
11
- ```html
12
- <head>
13
- <!--[if lte IE 8]>
14
- <script src="excanvas.js"></script>
15
- <![endif]-->
16
- </head>
17
- ```
18
-
19
- Usually I would recommend feature detection to choose whether or not to load a polyfill, rather than IE conditional comments, however in this case, VML is a Microsoft proprietary format, so it will only work in IE.
20
-
21
- Some important points to note in my experience using ExplorerCanvas as a fallback.
22
-
23
- - Initialise charts on load rather than DOMContentReady when using the library, as sometimes a race condition will occur, and it will result in an error when trying to get the 2d context of a canvas.
24
- - New VML DOM elements are being created for each animation frame and there is no hardware acceleration. As a result animation is usually slow and jerky, with flashing text. It is a good idea to dynamically turn off animation based on canvas support. I recommend using the excellent <a href="http://modernizr.com/" target="_blank">Modernizr</a> to do this.
25
- - When declaring fonts, the library explorercanvas requires the font name to be in single quotes inside the string. For example, instead of your scaleFontFamily property being simply "Arial", explorercanvas support, use "'Arial'" instead. Chart.js does this for default values.
26
-
27
- ### Bugs & issues
28
-
29
- Please report these on the GitHub page - at <a href="https://github.com/nnnick/Chart.js" target="_blank">github.com/nnnick/Chart.js</a>. If you could include a link to a simple <a href="http://jsbin.com/" target="_blank">jsbin</a> or similar to demonstrate the issue, that'd be really helpful.
30
-
31
-
32
- ### Contributing
33
- New contributions to the library are welcome, just a couple of guidelines:
34
-
35
- - Tabs for indentation, not spaces please.
36
- - Please ensure you're changing the individual files in `/src`, not the concatenated output in the `Chart.js` file in the root of the repo.
37
- - Please check that your code will pass `jshint` code standards, `gulp jshint` will run this for you.
38
- - Please keep pull requests concise, and document new functionality in the relevant `.md` file.
39
- - Consider whether your changes are useful for all users, or if creating a Chart.js extension would be more appropriate.
40
-
41
- ### License
42
- Chart.js is open source and available under the <a href="http://opensource.org/licenses/MIT" target="_blank">MIT license</a>.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/gulpfile.js DELETED
@@ -1,131 +0,0 @@
1
- var gulp = require('gulp'),
2
- concat = require('gulp-concat'),
3
- uglify = require('gulp-uglify'),
4
- util = require('gulp-util'),
5
- jshint = require('gulp-jshint'),
6
- size = require('gulp-size'),
7
- connect = require('gulp-connect'),
8
- replace = require('gulp-replace'),
9
- inquirer = require('inquirer'),
10
- semver = require('semver'),
11
- exec = require('child_process').exec,
12
- fs = require('fs'),
13
- package = require('./package.json'),
14
- bower = require('./bower.json');
15
-
16
- var srcDir = './src/';
17
- /*
18
- * Usage : gulp build --types=Bar,Line,Doughnut
19
- * Output: - A built Chart.js file with Core and types Bar, Line and Doughnut concatenated together
20
- * - A minified version of this code, in Chart.min.js
21
- */
22
-
23
- gulp.task('build', function(){
24
-
25
- // Default to all of the chart types, with Chart.Core first
26
- var srcFiles = [FileName('Core')],
27
- isCustom = !!(util.env.types),
28
- outputDir = (isCustom) ? 'custom' : '.';
29
- if (isCustom){
30
- util.env.types.split(',').forEach(function(type){ return srcFiles.push(FileName(type))});
31
- }
32
- else{
33
- // Seems gulp-concat remove duplicates - nice!
34
- // So we can use this to sort out dependency order - aka include Core first!
35
- srcFiles.push(srcDir+'*');
36
- }
37
-
38
- return gulp.src(srcFiles)
39
- .pipe(concat('Chart.js'))
40
- .pipe(replace('{{ version }}', package.version))
41
- .pipe(gulp.dest(outputDir))
42
- .pipe(uglify({preserveComments:'some'}))
43
- .pipe(concat('Chart.min.js'))
44
- .pipe(gulp.dest(outputDir));
45
-
46
- function FileName(moduleName){
47
- return srcDir+'Chart.'+moduleName+'.js';
48
- };
49
- });
50
-
51
- /*
52
- * Usage : gulp bump
53
- * Prompts: Version increment to bump
54
- * Output: - New version number written into package.json & bower.json
55
- */
56
-
57
- gulp.task('bump', function(complete){
58
- util.log('Current version:', util.colors.cyan(package.version));
59
- var choices = ['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'].map(function(versionType){
60
- return versionType + ' (v' + semver.inc(package.version, versionType) + ')';
61
- });
62
- inquirer.prompt({
63
- type: 'list',
64
- name: 'version',
65
- message: 'What version update would you like?',
66
- choices: choices
67
- }, function(res){
68
- var increment = res.version.split(' ')[0],
69
- newVersion = semver.inc(package.version, increment);
70
-
71
- // Set the new versions into the bower/package object
72
- package.version = newVersion;
73
- bower.version = newVersion;
74
-
75
- // Write these to their own files, then build the output
76
- fs.writeFileSync('package.json', JSON.stringify(package, null, 2));
77
- fs.writeFileSync('bower.json', JSON.stringify(bower, null, 2));
78
-
79
- complete();
80
- });
81
- });
82
-
83
- gulp.task('release', ['build'], function(){
84
- exec('git tag -a v' + package.version);
85
- });
86
-
87
- gulp.task('jshint', function(){
88
- return gulp.src(srcDir + '*.js')
89
- .pipe(jshint())
90
- .pipe(jshint.reporter('default'));
91
- });
92
-
93
- gulp.task('library-size', function(){
94
- return gulp.src('Chart.min.js')
95
- .pipe(size({
96
- gzip: true
97
- }));
98
- });
99
-
100
- gulp.task('module-sizes', function(){
101
- return gulp.src(srcDir + '*.js')
102
- .pipe(uglify({preserveComments:'some'}))
103
- .pipe(size({
104
- showFiles: true,
105
- gzip: true
106
- }))
107
- });
108
-
109
- gulp.task('watch', function(){
110
- gulp.watch('./src/*', ['build']);
111
- });
112
-
113
- gulp.task('test', ['jshint']);
114
-
115
- gulp.task('size', ['library-size', 'module-sizes']);
116
-
117
- gulp.task('default', ['build', 'watch']);
118
-
119
- gulp.task('server', function(){
120
- connect.server({
121
- port: 8000,
122
- });
123
- });
124
-
125
- // Convenience task for opening the project straight from the command line
126
- gulp.task('_open', function(){
127
- exec('open http://localhost:8000');
128
- exec('subl .');
129
- });
130
-
131
- gulp.task('dev', ['server', 'default']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/package.json DELETED
@@ -1,24 +0,0 @@
1
- {
2
- "name": "chart.js",
3
- "homepage": "http://www.chartjs.org",
4
- "description": "Simple HTML5 charts using the canvas element.",
5
- "version": "1.0.1-beta.4",
6
- "main": "Chart.js",
7
- "repository": {
8
- "type": "git",
9
- "url": "https://github.com/nnnick/Chart.js.git"
10
- },
11
- "dependences": {},
12
- "devDependencies": {
13
- "gulp": "3.5.x",
14
- "gulp-concat": "~2.1.x",
15
- "gulp-connect": "~2.0.5",
16
- "gulp-jshint": "~1.5.1",
17
- "gulp-replace": "^0.4.0",
18
- "gulp-size": "~0.4.0",
19
- "gulp-uglify": "~0.2.x",
20
- "gulp-util": "~2.2.x",
21
- "inquirer": "^0.5.1",
22
- "semver": "^3.0.1"
23
- }
24
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/samples/bar.html DELETED
@@ -1,48 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <title>Bar Chart</title>
5
- <script src="../Chart.js"></script>
6
- </head>
7
- <body>
8
- <div style="width: 50%">
9
- <canvas id="canvas" height="450" width="600"></canvas>
10
- </div>
11
-
12
-
13
- <script>
14
- var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
15
-
16
- var barChartData = {
17
- labels : ["January","February","March","April","May","June","July"],
18
- datasets : [
19
- {
20
- showTooltips:true,
21
- label: "My Second dataset",
22
- fillColor : "rgba(220,220,220,0.5)",
23
- strokeColor : "rgba(220,220,220,0.8)",
24
- highlightFill: "rgba(220,220,220,0.75)",
25
- highlightStroke: "rgba(220,220,220,1)",
26
- data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
27
- },
28
- {
29
- label: "My Second dataset",
30
- fillColor : "rgba(151,187,205,0.5)",
31
- strokeColor : "rgba(151,187,205,0.8)",
32
- highlightFill : "rgba(151,187,205,0.75)",
33
- highlightStroke : "rgba(151,187,205,1)",
34
- data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
35
- }
36
- ]
37
-
38
- }
39
- window.onload = function(){
40
- var ctx = document.getElementById("canvas").getContext("2d");
41
- window.myBar = new Chart(ctx).Bar(barChartData, {
42
- responsive : true
43
- });
44
- }
45
-
46
- </script>
47
- </body>
48
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/samples/doughnut.html DELETED
@@ -1,67 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <title>Doughnut Chart</title>
5
- <script src="../Chart.js"></script>
6
- <style>
7
- body{
8
- padding: 0;
9
- margin: 0;
10
- }
11
- #canvas-holder{
12
- width:30%;
13
- }
14
- </style>
15
- </head>
16
- <body>
17
- <div id="canvas-holder">
18
- <canvas id="chart-area" width="500" height="500"/>
19
- </div>
20
-
21
-
22
- <script>
23
-
24
- var doughnutData = [
25
- {
26
- value: 300,
27
- color:"#F7464A",
28
- highlight: "#FF5A5E",
29
- label: "Red"
30
- },
31
- {
32
- value: 50,
33
- color: "#46BFBD",
34
- highlight: "#5AD3D1",
35
- label: "Green"
36
- },
37
- {
38
- value: 100,
39
- color: "#FDB45C",
40
- highlight: "#FFC870",
41
- label: "Yellow"
42
- },
43
- {
44
- value: 40,
45
- color: "#949FB1",
46
- highlight: "#A8B3C5",
47
- label: "Grey"
48
- },
49
- {
50
- value: 120,
51
- color: "#4D5360",
52
- highlight: "#616774",
53
- label: "Dark Grey"
54
- }
55
-
56
- ];
57
-
58
- window.onload = function(){
59
- var ctx = document.getElementById("chart-area").getContext("2d");
60
- window.myDoughnut = new Chart(ctx).Doughnut(doughnutData, {responsive : true});
61
- };
62
-
63
-
64
-
65
- </script>
66
- </body>
67
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/samples/line.html DELETED
@@ -1,54 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <title>Line Chart</title>
5
- <script src="../Chart.js"></script>
6
- </head>
7
- <body>
8
- <div style="width:30%">
9
- <div>
10
- <canvas id="canvas" height="450" width="600"></canvas>
11
- </div>
12
- </div>
13
-
14
-
15
- <script>
16
- var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
17
- var lineChartData = {
18
- labels : ["January","February","March","April","May","June","July"],
19
- datasets : [
20
- {
21
- label: "My First dataset",
22
- fillColor : "rgba(220,220,220,0.2)",
23
- strokeColor : "rgba(220,220,220,1)",
24
- pointColor : "rgba(220,220,220,1)",
25
- pointStrokeColor : "#fff",
26
- pointHighlightFill : "#fff",
27
- pointHighlightStroke : "rgba(220,220,220,1)",
28
- data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
29
- },
30
- {
31
- label: "My Second dataset",
32
- fillColor : "rgba(151,187,205,0.2)",
33
- strokeColor : "rgba(151,187,205,1)",
34
- pointColor : "rgba(151,187,205,1)",
35
- pointStrokeColor : "#fff",
36
- pointHighlightFill : "#fff",
37
- pointHighlightStroke : "rgba(151,187,205,1)",
38
- data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
39
- }
40
- ]
41
-
42
- }
43
-
44
- window.onload = function(){
45
- var ctx = document.getElementById("canvas").getContext("2d");
46
- window.myLine = new Chart(ctx).Line(lineChartData, {
47
- responsive: true
48
- });
49
- }
50
-
51
-
52
- </script>
53
- </body>
54
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/samples/pie.html DELETED
@@ -1,58 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <title>Pie Chart</title>
5
- <script src="../Chart.js"></script>
6
- </head>
7
- <body>
8
- <div id="canvas-holder">
9
- <canvas id="chart-area" width="300" height="300"/>
10
- </div>
11
-
12
-
13
- <script>
14
-
15
- var pieData = [
16
- {
17
- value: 300,
18
- color:"#F7464A",
19
- highlight: "#FF5A5E",
20
- label: "Red"
21
- },
22
- {
23
- value: 50,
24
- color: "#46BFBD",
25
- highlight: "#5AD3D1",
26
- label: "Green"
27
- },
28
- {
29
- value: 100,
30
- color: "#FDB45C",
31
- highlight: "#FFC870",
32
- label: "Yellow"
33
- },
34
- {
35
- value: 40,
36
- color: "#949FB1",
37
- highlight: "#A8B3C5",
38
- label: "Grey"
39
- },
40
- {
41
- value: 120,
42
- color: "#4D5360",
43
- highlight: "#616774",
44
- label: "Dark Grey"
45
- }
46
-
47
- ];
48
-
49
- window.onload = function(){
50
- var ctx = document.getElementById("chart-area").getContext("2d");
51
- window.myPie = new Chart(ctx).Pie(pieData);
52
- };
53
-
54
-
55
-
56
- </script>
57
- </body>
58
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/samples/polar-area.html DELETED
@@ -1,60 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <title>Polar Area Chart</title>
5
- <script src="../Chart.js"></script>
6
- </head>
7
- <body>
8
- <div id="canvas-holder" style="width:30%">
9
- <canvas id="chart-area" width="300" height="300"/>
10
- </div>
11
-
12
-
13
- <script>
14
-
15
- var polarData = [
16
- {
17
- value: 300,
18
- color:"#F7464A",
19
- highlight: "#FF5A5E",
20
- label: "Red"
21
- },
22
- {
23
- value: 50,
24
- color: "#46BFBD",
25
- highlight: "#5AD3D1",
26
- label: "Green"
27
- },
28
- {
29
- value: 100,
30
- color: "#FDB45C",
31
- highlight: "#FFC870",
32
- label: "Yellow"
33
- },
34
- {
35
- value: 40,
36
- color: "#949FB1",
37
- highlight: "#A8B3C5",
38
- label: "Grey"
39
- },
40
- {
41
- value: 120,
42
- color: "#4D5360",
43
- highlight: "#616774",
44
- label: "Dark Grey"
45
- }
46
-
47
- ];
48
-
49
- window.onload = function(){
50
- var ctx = document.getElementById("chart-area").getContext("2d");
51
- window.myPolarArea = new Chart(ctx).PolarArea(polarData, {
52
- responsive:true
53
- });
54
- };
55
-
56
-
57
-
58
- </script>
59
- </body>
60
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/samples/radar.html DELETED
@@ -1,53 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <title>Radar Chart</title>
5
- <script src="../Chart.js"></script>
6
- <meta name = "viewport" content = "initial-scale = 1, user-scalable = no">
7
- <style>
8
- canvas{
9
- }
10
- </style>
11
- </head>
12
- <body>
13
- <div style="width:30%">
14
- <canvas id="canvas" height="450" width="450"></canvas>
15
- </div>
16
-
17
-
18
- <script>
19
- var radarChartData = {
20
- labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
21
- datasets: [
22
- {
23
- label: "My First dataset",
24
- fillColor: "rgba(220,220,220,0.2)",
25
- strokeColor: "rgba(220,220,220,1)",
26
- pointColor: "rgba(220,220,220,1)",
27
- pointStrokeColor: "#fff",
28
- pointHighlightFill: "#fff",
29
- pointHighlightStroke: "rgba(220,220,220,1)",
30
- data: [65,59,90,81,56,55,40]
31
- },
32
- {
33
- label: "My Second dataset",
34
- fillColor: "rgba(151,187,205,0.2)",
35
- strokeColor: "rgba(151,187,205,1)",
36
- pointColor: "rgba(151,187,205,1)",
37
- pointStrokeColor: "#fff",
38
- pointHighlightFill: "#fff",
39
- pointHighlightStroke: "rgba(151,187,205,1)",
40
- data: [28,48,40,19,96,27,100]
41
- }
42
- ]
43
- };
44
-
45
- window.onload = function(){
46
- window.myRadar = new Chart(document.getElementById("canvas").getContext("2d")).Radar(radarChartData, {
47
- responsive: true
48
- });
49
- }
50
-
51
- </script>
52
- </body>
53
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/src/Chart.Bar.js DELETED
@@ -1,294 +0,0 @@
1
- (function(){
2
- "use strict";
3
-
4
- var root = this,
5
- Chart = root.Chart,
6
- helpers = Chart.helpers;
7
-
8
-
9
- var defaultConfig = {
10
- //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
11
- scaleBeginAtZero : true,
12
-
13
- //Boolean - Whether grid lines are shown across the chart
14
- scaleShowGridLines : true,
15
-
16
- //String - Colour of the grid lines
17
- scaleGridLineColor : "rgba(0,0,0,.05)",
18
-
19
- //Number - Width of the grid lines
20
- scaleGridLineWidth : 1,
21
-
22
- //Boolean - If there is a stroke on each bar
23
- barShowStroke : true,
24
-
25
- //Number - Pixel width of the bar stroke
26
- barStrokeWidth : 2,
27
-
28
- //Number - Spacing between each of the X value sets
29
- barValueSpacing : 5,
30
-
31
- //Number - Spacing between data sets within X values
32
- barDatasetSpacing : 1,
33
-
34
- //String - A legend template
35
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
36
-
37
- };
38
-
39
-
40
- Chart.Type.extend({
41
- name: "Bar",
42
- defaults : defaultConfig,
43
- initialize: function(data){
44
-
45
- //Expose options as a scope variable here so we can access it in the ScaleClass
46
- var options = this.options;
47
-
48
- this.ScaleClass = Chart.Scale.extend({
49
- offsetGridLines : true,
50
- calculateBarX : function(datasetCount, datasetIndex, barIndex){
51
- //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
52
- var xWidth = this.calculateBaseWidth(),
53
- xAbsolute = this.calculateX(barIndex) - (xWidth/2),
54
- barWidth = this.calculateBarWidth(datasetCount);
55
-
56
- return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;
57
- },
58
- calculateBaseWidth : function(){
59
- return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing);
60
- },
61
- calculateBarWidth : function(datasetCount){
62
- //The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
63
- var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);
64
-
65
- return (baseWidth / datasetCount);
66
- }
67
- });
68
-
69
- this.datasets = [];
70
-
71
- //Set up tooltip events on the chart
72
- if (this.options.showTooltips){
73
- helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
74
- var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];
75
-
76
- this.eachBars(function(bar){
77
- bar.restore(['fillColor', 'strokeColor']);
78
- });
79
- helpers.each(activeBars, function(activeBar){
80
- activeBar.fillColor = activeBar.highlightFill;
81
- activeBar.strokeColor = activeBar.highlightStroke;
82
- });
83
- this.showTooltip(activeBars);
84
- });
85
- }
86
-
87
- //Declare the extension of the default point, to cater for the options passed in to the constructor
88
- this.BarClass = Chart.Rectangle.extend({
89
- strokeWidth : this.options.barStrokeWidth,
90
- showStroke : this.options.barShowStroke,
91
- ctx : this.chart.ctx
92
- });
93
-
94
- //Iterate through each of the datasets, and build this into a property of the chart
95
- helpers.each(data.datasets,function(dataset,datasetIndex){
96
-
97
- var datasetObject = {
98
- label : dataset.label || null,
99
- fillColor : dataset.fillColor,
100
- strokeColor : dataset.strokeColor,
101
- bars : []
102
- };
103
-
104
- this.datasets.push(datasetObject);
105
-
106
- helpers.each(dataset.data,function(dataPoint,index){
107
- //Add a new point for each piece of data, passing any required data to draw.
108
- datasetObject.bars.push(new this.BarClass({
109
- value : dataPoint,
110
- label : data.labels[index],
111
- datasetLabel: dataset.label,
112
- strokeColor : dataset.strokeColor,
113
- fillColor : dataset.fillColor,
114
- highlightFill : dataset.highlightFill || dataset.fillColor,
115
- highlightStroke : dataset.highlightStroke || dataset.strokeColor
116
- }));
117
- },this);
118
-
119
- },this);
120
-
121
- this.buildScale(data.labels);
122
-
123
- this.BarClass.prototype.base = this.scale.endPoint;
124
-
125
- this.eachBars(function(bar, index, datasetIndex){
126
- helpers.extend(bar, {
127
- width : this.scale.calculateBarWidth(this.datasets.length),
128
- x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
129
- y: this.scale.endPoint
130
- });
131
- bar.save();
132
- }, this);
133
-
134
- this.render();
135
- },
136
- update : function(){
137
- this.scale.update();
138
- // Reset any highlight colours before updating.
139
- helpers.each(this.activeElements, function(activeElement){
140
- activeElement.restore(['fillColor', 'strokeColor']);
141
- });
142
-
143
- this.eachBars(function(bar){
144
- bar.save();
145
- });
146
- this.render();
147
- },
148
- eachBars : function(callback){
149
- helpers.each(this.datasets,function(dataset, datasetIndex){
150
- helpers.each(dataset.bars, callback, this, datasetIndex);
151
- },this);
152
- },
153
- getBarsAtEvent : function(e){
154
- var barsArray = [],
155
- eventPosition = helpers.getRelativePosition(e),
156
- datasetIterator = function(dataset){
157
- barsArray.push(dataset.bars[barIndex]);
158
- },
159
- barIndex;
160
-
161
- for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {
162
- for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {
163
- if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){
164
- helpers.each(this.datasets, datasetIterator);
165
- return barsArray;
166
- }
167
- }
168
- }
169
-
170
- return barsArray;
171
- },
172
- buildScale : function(labels){
173
- var self = this;
174
-
175
- var dataTotal = function(){
176
- var values = [];
177
- self.eachBars(function(bar){
178
- values.push(bar.value);
179
- });
180
- return values;
181
- };
182
-
183
- var scaleOptions = {
184
- templateString : this.options.scaleLabel,
185
- height : this.chart.height,
186
- width : this.chart.width,
187
- ctx : this.chart.ctx,
188
- textColor : this.options.scaleFontColor,
189
- fontSize : this.options.scaleFontSize,
190
- fontStyle : this.options.scaleFontStyle,
191
- fontFamily : this.options.scaleFontFamily,
192
- valuesCount : labels.length,
193
- beginAtZero : this.options.scaleBeginAtZero,
194
- integersOnly : this.options.scaleIntegersOnly,
195
- calculateYRange: function(currentHeight){
196
- var updatedRanges = helpers.calculateScaleRange(
197
- dataTotal(),
198
- currentHeight,
199
- this.fontSize,
200
- this.beginAtZero,
201
- this.integersOnly
202
- );
203
- helpers.extend(this, updatedRanges);
204
- },
205
- xLabels : labels,
206
- font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
207
- lineWidth : this.options.scaleLineWidth,
208
- lineColor : this.options.scaleLineColor,
209
- gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
210
- gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
211
- padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,
212
- showLabels : this.options.scaleShowLabels,
213
- display : this.options.showScale
214
- };
215
-
216
- if (this.options.scaleOverride){
217
- helpers.extend(scaleOptions, {
218
- calculateYRange: helpers.noop,
219
- steps: this.options.scaleSteps,
220
- stepValue: this.options.scaleStepWidth,
221
- min: this.options.scaleStartValue,
222
- max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
223
- });
224
- }
225
-
226
- this.scale = new this.ScaleClass(scaleOptions);
227
- },
228
- addData : function(valuesArray,label){
229
- //Map the values array for each of the datasets
230
- helpers.each(valuesArray,function(value,datasetIndex){
231
- //Add a new point for each piece of data, passing any required data to draw.
232
- this.datasets[datasetIndex].bars.push(new this.BarClass({
233
- value : value,
234
- label : label,
235
- x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1),
236
- y: this.scale.endPoint,
237
- width : this.scale.calculateBarWidth(this.datasets.length),
238
- base : this.scale.endPoint,
239
- strokeColor : this.datasets[datasetIndex].strokeColor,
240
- fillColor : this.datasets[datasetIndex].fillColor
241
- }));
242
- },this);
243
-
244
- this.scale.addXLabel(label);
245
- //Then re-render the chart.
246
- this.update();
247
- },
248
- removeData : function(){
249
- this.scale.removeXLabel();
250
- //Then re-render the chart.
251
- helpers.each(this.datasets,function(dataset){
252
- dataset.bars.shift();
253
- },this);
254
- this.update();
255
- },
256
- reflow : function(){
257
- helpers.extend(this.BarClass.prototype,{
258
- y: this.scale.endPoint,
259
- base : this.scale.endPoint
260
- });
261
- var newScaleProps = helpers.extend({
262
- height : this.chart.height,
263
- width : this.chart.width
264
- });
265
- this.scale.update(newScaleProps);
266
- },
267
- draw : function(ease){
268
- var easingDecimal = ease || 1;
269
- this.clear();
270
-
271
- var ctx = this.chart.ctx;
272
-
273
- this.scale.draw(easingDecimal);
274
-
275
- //Draw all the bars for each dataset
276
- helpers.each(this.datasets,function(dataset,datasetIndex){
277
- helpers.each(dataset.bars,function(bar,index){
278
- if (bar.hasValue()){
279
- bar.base = this.scale.endPoint;
280
- //Transition then draw
281
- bar.transition({
282
- x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
283
- y : this.scale.calculateY(bar.value),
284
- width : this.scale.calculateBarWidth(this.datasets.length)
285
- }, easingDecimal).draw();
286
- }
287
- },this);
288
-
289
- },this);
290
- }
291
- });
292
-
293
-
294
- }).call(this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/src/Chart.Core.js DELETED
@@ -1,1943 +0,0 @@
1
- /*!
2
- * Chart.js
3
- * http://chartjs.org/
4
- * Version: {{ version }}
5
- *
6
- * Copyright 2014 Nick Downie
7
- * Released under the MIT license
8
- * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
9
- */
10
-
11
-
12
- (function(){
13
-
14
- "use strict";
15
-
16
- //Declare root variable - window in the browser, global on the server
17
- var root = this,
18
- previous = root.Chart;
19
-
20
- //Occupy the global variable of Chart, and create a simple base class
21
- var Chart = function(context){
22
- var chart = this;
23
- this.canvas = context.canvas;
24
-
25
- this.ctx = context;
26
-
27
- //Variables global to the chart
28
- var width = this.width = context.canvas.width;
29
- var height = this.height = context.canvas.height;
30
- this.aspectRatio = this.width / this.height;
31
- //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
32
- helpers.retinaScale(this);
33
-
34
- return this;
35
- };
36
- //Globally expose the defaults to allow for user updating/changing
37
- Chart.defaults = {
38
- global: {
39
- // Boolean - Whether to animate the chart
40
- animation: true,
41
-
42
- // Number - Number of animation steps
43
- animationSteps: 60,
44
-
45
- // String - Animation easing effect
46
- animationEasing: "easeOutQuart",
47
-
48
- // Boolean - If we should show the scale at all
49
- showScale: true,
50
-
51
- // Boolean - If we want to override with a hard coded scale
52
- scaleOverride: false,
53
-
54
- // ** Required if scaleOverride is true **
55
- // Number - The number of steps in a hard coded scale
56
- scaleSteps: null,
57
- // Number - The value jump in the hard coded scale
58
- scaleStepWidth: null,
59
- // Number - The scale starting value
60
- scaleStartValue: null,
61
-
62
- // String - Colour of the scale line
63
- scaleLineColor: "rgba(0,0,0,.1)",
64
-
65
- // Number - Pixel width of the scale line
66
- scaleLineWidth: 1,
67
-
68
- // Boolean - Whether to show labels on the scale
69
- scaleShowLabels: true,
70
-
71
- // Interpolated JS string - can access value
72
- scaleLabel: "<%=value%>",
73
-
74
- // Boolean - Whether the scale should stick to integers, and not show any floats even if drawing space is there
75
- scaleIntegersOnly: true,
76
-
77
- // Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
78
- scaleBeginAtZero: false,
79
-
80
- // String - Scale label font declaration for the scale label
81
- scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
82
-
83
- // Number - Scale label font size in pixels
84
- scaleFontSize: 12,
85
-
86
- // String - Scale label font weight style
87
- scaleFontStyle: "normal",
88
-
89
- // String - Scale label font colour
90
- scaleFontColor: "#666",
91
-
92
- // Boolean - whether or not the chart should be responsive and resize when the browser does.
93
- responsive: false,
94
-
95
- // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
96
- maintainAspectRatio: true,
97
-
98
- // Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove
99
- showTooltips: true,
100
-
101
- // Array - Array of string names to attach tooltip events
102
- tooltipEvents: ["mousemove", "touchstart", "touchmove", "mouseout"],
103
-
104
- // String - Tooltip background colour
105
- tooltipFillColor: "rgba(0,0,0,0.8)",
106
-
107
- // String - Tooltip label font declaration for the scale label
108
- tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
109
-
110
- // Number - Tooltip label font size in pixels
111
- tooltipFontSize: 14,
112
-
113
- // String - Tooltip font weight style
114
- tooltipFontStyle: "normal",
115
-
116
- // String - Tooltip label font colour
117
- tooltipFontColor: "#fff",
118
-
119
- // String - Tooltip title font declaration for the scale label
120
- tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
121
-
122
- // Number - Tooltip title font size in pixels
123
- tooltipTitleFontSize: 14,
124
-
125
- // String - Tooltip title font weight style
126
- tooltipTitleFontStyle: "bold",
127
-
128
- // String - Tooltip title font colour
129
- tooltipTitleFontColor: "#fff",
130
-
131
- // Number - pixel width of padding around tooltip text
132
- tooltipYPadding: 6,
133
-
134
- // Number - pixel width of padding around tooltip text
135
- tooltipXPadding: 6,
136
-
137
- // Number - Size of the caret on the tooltip
138
- tooltipCaretSize: 8,
139
-
140
- // Number - Pixel radius of the tooltip border
141
- tooltipCornerRadius: 6,
142
-
143
- // Number - Pixel offset from point x to tooltip edge
144
- tooltipXOffset: 10,
145
-
146
- // String - Template string for single tooltips
147
- tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>",
148
-
149
- // String - Template string for single tooltips
150
- multiTooltipTemplate: "<%= value %>",
151
-
152
- // String - Colour behind the legend colour block
153
- multiTooltipKeyBackground: '#fff',
154
-
155
- // Function - Will fire on animation progression.
156
- onAnimationProgress: function(){},
157
-
158
- // Function - Will fire on animation completion.
159
- onAnimationComplete: function(){}
160
-
161
- }
162
- };
163
-
164
- //Create a dictionary of chart types, to allow for extension of existing types
165
- Chart.types = {};
166
-
167
- //Global Chart helpers object for utility methods and classes
168
- var helpers = Chart.helpers = {};
169
-
170
- //-- Basic js utility methods
171
- var each = helpers.each = function(loopable,callback,self){
172
- var additionalArgs = Array.prototype.slice.call(arguments, 3);
173
- // Check to see if null or undefined firstly.
174
- if (loopable){
175
- if (loopable.length === +loopable.length){
176
- var i;
177
- for (i=0; i<loopable.length; i++){
178
- callback.apply(self,[loopable[i], i].concat(additionalArgs));
179
- }
180
- }
181
- else{
182
- for (var item in loopable){
183
- callback.apply(self,[loopable[item],item].concat(additionalArgs));
184
- }
185
- }
186
- }
187
- },
188
- clone = helpers.clone = function(obj){
189
- var objClone = {};
190
- each(obj,function(value,key){
191
- if (obj.hasOwnProperty(key)) objClone[key] = value;
192
- });
193
- return objClone;
194
- },
195
- extend = helpers.extend = function(base){
196
- each(Array.prototype.slice.call(arguments,1), function(extensionObject) {
197
- each(extensionObject,function(value,key){
198
- if (extensionObject.hasOwnProperty(key)) base[key] = value;
199
- });
200
- });
201
- return base;
202
- },
203
- merge = helpers.merge = function(base,master){
204
- //Merge properties in left object over to a shallow clone of object right.
205
- var args = Array.prototype.slice.call(arguments,0);
206
- args.unshift({});
207
- return extend.apply(null, args);
208
- },
209
- indexOf = helpers.indexOf = function(arrayToSearch, item){
210
- if (Array.prototype.indexOf) {
211
- return arrayToSearch.indexOf(item);
212
- }
213
- else{
214
- for (var i = 0; i < arrayToSearch.length; i++) {
215
- if (arrayToSearch[i] === item) return i;
216
- }
217
- return -1;
218
- }
219
- },
220
- where = helpers.where = function(collection, filterCallback){
221
- var filtered = [];
222
-
223
- helpers.each(collection, function(item){
224
- if (filterCallback(item)){
225
- filtered.push(item);
226
- }
227
- });
228
-
229
- return filtered;
230
- },
231
- findNextWhere = helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex){
232
- // Default to start of the array
233
- if (!startIndex){
234
- startIndex = -1;
235
- }
236
- for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
237
- var currentItem = arrayToSearch[i];
238
- if (filterCallback(currentItem)){
239
- return currentItem;
240
- }
241
- };
242
- },
243
- findPreviousWhere = helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex){
244
- // Default to end of the array
245
- if (!startIndex){
246
- startIndex = arrayToSearch.length;
247
- }
248
- for (var i = startIndex - 1; i >= 0; i--) {
249
- var currentItem = arrayToSearch[i];
250
- if (filterCallback(currentItem)){
251
- return currentItem;
252
- }
253
- };
254
- },
255
- inherits = helpers.inherits = function(extensions){
256
- //Basic javascript inheritance based on the model created in Backbone.js
257
- var parent = this;
258
- var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function(){ return parent.apply(this, arguments); };
259
-
260
- var Surrogate = function(){ this.constructor = ChartElement;};
261
- Surrogate.prototype = parent.prototype;
262
- ChartElement.prototype = new Surrogate();
263
-
264
- ChartElement.extend = inherits;
265
-
266
- if (extensions) extend(ChartElement.prototype, extensions);
267
-
268
- ChartElement.__super__ = parent.prototype;
269
-
270
- return ChartElement;
271
- },
272
- noop = helpers.noop = function(){},
273
- uid = helpers.uid = (function(){
274
- var id=0;
275
- return function(){
276
- return "chart-" + id++;
277
- };
278
- })(),
279
- warn = helpers.warn = function(str){
280
- //Method for warning of errors
281
- if (window.console && typeof window.console.warn == "function") console.warn(str);
282
- },
283
- amd = helpers.amd = (typeof define == 'function' && define.amd),
284
- //-- Math methods
285
- isNumber = helpers.isNumber = function(n){
286
- return !isNaN(parseFloat(n)) && isFinite(n);
287
- },
288
- max = helpers.max = function(array){
289
- return Math.max.apply( Math, array );
290
- },
291
- min = helpers.min = function(array){
292
- return Math.min.apply( Math, array );
293
- },
294
- cap = helpers.cap = function(valueToCap,maxValue,minValue){
295
- if(isNumber(maxValue)) {
296
- if( valueToCap > maxValue ) {
297
- return maxValue;
298
- }
299
- }
300
- else if(isNumber(minValue)){
301
- if ( valueToCap < minValue ){
302
- return minValue;
303
- }
304
- }
305
- return valueToCap;
306
- },
307
- getDecimalPlaces = helpers.getDecimalPlaces = function(num){
308
- if (num%1!==0 && isNumber(num)){
309
- return num.toString().split(".")[1].length;
310
- }
311
- else {
312
- return 0;
313
- }
314
- },
315
- toRadians = helpers.radians = function(degrees){
316
- return degrees * (Math.PI/180);
317
- },
318
- // Gets the angle from vertical upright to the point about a centre.
319
- getAngleFromPoint = helpers.getAngleFromPoint = function(centrePoint, anglePoint){
320
- var distanceFromXCenter = anglePoint.x - centrePoint.x,
321
- distanceFromYCenter = anglePoint.y - centrePoint.y,
322
- radialDistanceFromCenter = Math.sqrt( distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
323
-
324
-
325
- var angle = Math.PI * 2 + Math.atan2(distanceFromYCenter, distanceFromXCenter);
326
-
327
- //If the segment is in the top left quadrant, we need to add another rotation to the angle
328
- if (distanceFromXCenter < 0 && distanceFromYCenter < 0){
329
- angle += Math.PI*2;
330
- }
331
-
332
- return {
333
- angle: angle,
334
- distance: radialDistanceFromCenter
335
- };
336
- },
337
- aliasPixel = helpers.aliasPixel = function(pixelWidth){
338
- return (pixelWidth % 2 === 0) ? 0 : 0.5;
339
- },
340
- splineCurve = helpers.splineCurve = function(FirstPoint,MiddlePoint,AfterPoint,t){
341
- //Props to Rob Spencer at scaled innovation for his post on splining between points
342
- //http://scaledinnovation.com/analytics/splines/aboutSplines.html
343
- var d01=Math.sqrt(Math.pow(MiddlePoint.x-FirstPoint.x,2)+Math.pow(MiddlePoint.y-FirstPoint.y,2)),
344
- d12=Math.sqrt(Math.pow(AfterPoint.x-MiddlePoint.x,2)+Math.pow(AfterPoint.y-MiddlePoint.y,2)),
345
- fa=t*d01/(d01+d12),// scaling factor for triangle Ta
346
- fb=t*d12/(d01+d12);
347
- return {
348
- inner : {
349
- x : MiddlePoint.x-fa*(AfterPoint.x-FirstPoint.x),
350
- y : MiddlePoint.y-fa*(AfterPoint.y-FirstPoint.y)
351
- },
352
- outer : {
353
- x: MiddlePoint.x+fb*(AfterPoint.x-FirstPoint.x),
354
- y : MiddlePoint.y+fb*(AfterPoint.y-FirstPoint.y)
355
- }
356
- };
357
- },
358
- calculateOrderOfMagnitude = helpers.calculateOrderOfMagnitude = function(val){
359
- return Math.floor(Math.log(val) / Math.LN10);
360
- },
361
- calculateScaleRange = helpers.calculateScaleRange = function(valuesArray, drawingSize, textSize, startFromZero, integersOnly){
362
-
363
- //Set a minimum step of two - a point at the top of the graph, and a point at the base
364
- var minSteps = 2,
365
- maxSteps = Math.floor(drawingSize/(textSize * 1.5)),
366
- skipFitting = (minSteps >= maxSteps);
367
-
368
- var maxValue = max(valuesArray),
369
- minValue = min(valuesArray);
370
-
371
- // We need some degree of seperation here to calculate the scales if all the values are the same
372
- // Adding/minusing 0.5 will give us a range of 1.
373
- if (maxValue === minValue){
374
- maxValue += 0.5;
375
- // So we don't end up with a graph with a negative start value if we've said always start from zero
376
- if (minValue >= 0.5 && !startFromZero){
377
- minValue -= 0.5;
378
- }
379
- else{
380
- // Make up a whole number above the values
381
- maxValue += 0.5;
382
- }
383
- }
384
-
385
- var valueRange = Math.abs(maxValue - minValue),
386
- rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange),
387
- graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),
388
- graphMin = (startFromZero) ? 0 : Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),
389
- graphRange = graphMax - graphMin,
390
- stepValue = Math.pow(10, rangeOrderOfMagnitude),
391
- numberOfSteps = Math.round(graphRange / stepValue);
392
-
393
- //If we have more space on the graph we'll use it to give more definition to the data
394
- while((numberOfSteps > maxSteps || (numberOfSteps * 2) < maxSteps) && !skipFitting) {
395
- if(numberOfSteps > maxSteps){
396
- stepValue *=2;
397
- numberOfSteps = Math.round(graphRange/stepValue);
398
- // Don't ever deal with a decimal number of steps - cancel fitting and just use the minimum number of steps.
399
- if (numberOfSteps % 1 !== 0){
400
- skipFitting = true;
401
- }
402
- }
403
- //We can fit in double the amount of scale points on the scale
404
- else{
405
- //If user has declared ints only, and the step value isn't a decimal
406
- if (integersOnly && rangeOrderOfMagnitude >= 0){
407
- //If the user has said integers only, we need to check that making the scale more granular wouldn't make it a float
408
- if(stepValue/2 % 1 === 0){
409
- stepValue /=2;
410
- numberOfSteps = Math.round(graphRange/stepValue);
411
- }
412
- //If it would make it a float break out of the loop
413
- else{
414
- break;
415
- }
416
- }
417
- //If the scale doesn't have to be an int, make the scale more granular anyway.
418
- else{
419
- stepValue /=2;
420
- numberOfSteps = Math.round(graphRange/stepValue);
421
- }
422
-
423
- }
424
- }
425
-
426
- if (skipFitting){
427
- numberOfSteps = minSteps;
428
- stepValue = graphRange / numberOfSteps;
429
- }
430
-
431
- return {
432
- steps : numberOfSteps,
433
- stepValue : stepValue,
434
- min : graphMin,
435
- max : graphMin + (numberOfSteps * stepValue)
436
- };
437
-
438
- },
439
- /* jshint ignore:start */
440
- // Blows up jshint errors based on the new Function constructor
441
- //Templating methods
442
- //Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/
443
- template = helpers.template = function(templateString, valuesObject){
444
- // If templateString is function rather than string-template - call the function for valuesObject
445
- if(templateString instanceof Function){
446
- return templateString(valuesObject);
447
- }
448
-
449
- var cache = {};
450
- function tmpl(str, data){
451
- // Figure out if we're getting a template, or if we need to
452
- // load the template - and be sure to cache the result.
453
- var fn = !/\W/.test(str) ?
454
- cache[str] = cache[str] :
455
-
456
- // Generate a reusable function that will serve as a template
457
- // generator (and which will be cached).
458
- new Function("obj",
459
- "var p=[],print=function(){p.push.apply(p,arguments);};" +
460
-
461
- // Introduce the data as local variables using with(){}
462
- "with(obj){p.push('" +
463
-
464
- // Convert the template into pure JavaScript
465
- str
466
- .replace(/[\r\t\n]/g, " ")
467
- .split("<%").join("\t")
468
- .replace(/((^|%>)[^\t]*)'/g, "$1\r")
469
- .replace(/\t=(.*?)%>/g, "',$1,'")
470
- .split("\t").join("');")
471
- .split("%>").join("p.push('")
472
- .split("\r").join("\\'") +
473
- "');}return p.join('');"
474
- );
475
-
476
- // Provide some basic currying to the user
477
- return data ? fn( data ) : fn;
478
- }
479
- return tmpl(templateString,valuesObject);
480
- },
481
- /* jshint ignore:end */
482
- generateLabels = helpers.generateLabels = function(templateString,numberOfSteps,graphMin,stepValue){
483
- var labelsArray = new Array(numberOfSteps);
484
- if (labelTemplateString){
485
- each(labelsArray,function(val,index){
486
- labelsArray[index] = template(templateString,{value: (graphMin + (stepValue*(index+1)))});
487
- });
488
- }
489
- return labelsArray;
490
- },
491
- //--Animation methods
492
- //Easing functions adapted from Robert Penner's easing equations
493
- //http://www.robertpenner.com/easing/
494
- easingEffects = helpers.easingEffects = {
495
- linear: function (t) {
496
- return t;
497
- },
498
- easeInQuad: function (t) {
499
- return t * t;
500
- },
501
- easeOutQuad: function (t) {
502
- return -1 * t * (t - 2);
503
- },
504
- easeInOutQuad: function (t) {
505
- if ((t /= 1 / 2) < 1) return 1 / 2 * t * t;
506
- return -1 / 2 * ((--t) * (t - 2) - 1);
507
- },
508
- easeInCubic: function (t) {
509
- return t * t * t;
510
- },
511
- easeOutCubic: function (t) {
512
- return 1 * ((t = t / 1 - 1) * t * t + 1);
513
- },
514
- easeInOutCubic: function (t) {
515
- if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t;
516
- return 1 / 2 * ((t -= 2) * t * t + 2);
517
- },
518
- easeInQuart: function (t) {
519
- return t * t * t * t;
520
- },
521
- easeOutQuart: function (t) {
522
- return -1 * ((t = t / 1 - 1) * t * t * t - 1);
523
- },
524
- easeInOutQuart: function (t) {
525
- if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t;
526
- return -1 / 2 * ((t -= 2) * t * t * t - 2);
527
- },
528
- easeInQuint: function (t) {
529
- return 1 * (t /= 1) * t * t * t * t;
530
- },
531
- easeOutQuint: function (t) {
532
- return 1 * ((t = t / 1 - 1) * t * t * t * t + 1);
533
- },
534
- easeInOutQuint: function (t) {
535
- if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t * t;
536
- return 1 / 2 * ((t -= 2) * t * t * t * t + 2);
537
- },
538
- easeInSine: function (t) {
539
- return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;
540
- },
541
- easeOutSine: function (t) {
542
- return 1 * Math.sin(t / 1 * (Math.PI / 2));
543
- },
544
- easeInOutSine: function (t) {
545
- return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);
546
- },
547
- easeInExpo: function (t) {
548
- return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));
549
- },
550
- easeOutExpo: function (t) {
551
- return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);
552
- },
553
- easeInOutExpo: function (t) {
554
- if (t === 0) return 0;
555
- if (t === 1) return 1;
556
- if ((t /= 1 / 2) < 1) return 1 / 2 * Math.pow(2, 10 * (t - 1));
557
- return 1 / 2 * (-Math.pow(2, -10 * --t) + 2);
558
- },
559
- easeInCirc: function (t) {
560
- if (t >= 1) return t;
561
- return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);
562
- },
563
- easeOutCirc: function (t) {
564
- return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);
565
- },
566
- easeInOutCirc: function (t) {
567
- if ((t /= 1 / 2) < 1) return -1 / 2 * (Math.sqrt(1 - t * t) - 1);
568
- return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);
569
- },
570
- easeInElastic: function (t) {
571
- var s = 1.70158;
572
- var p = 0;
573
- var a = 1;
574
- if (t === 0) return 0;
575
- if ((t /= 1) == 1) return 1;
576
- if (!p) p = 1 * 0.3;
577
- if (a < Math.abs(1)) {
578
- a = 1;
579
- s = p / 4;
580
- } else s = p / (2 * Math.PI) * Math.asin(1 / a);
581
- return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
582
- },
583
- easeOutElastic: function (t) {
584
- var s = 1.70158;
585
- var p = 0;
586
- var a = 1;
587
- if (t === 0) return 0;
588
- if ((t /= 1) == 1) return 1;
589
- if (!p) p = 1 * 0.3;
590
- if (a < Math.abs(1)) {
591
- a = 1;
592
- s = p / 4;
593
- } else s = p / (2 * Math.PI) * Math.asin(1 / a);
594
- return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;
595
- },
596
- easeInOutElastic: function (t) {
597
- var s = 1.70158;
598
- var p = 0;
599
- var a = 1;
600
- if (t === 0) return 0;
601
- if ((t /= 1 / 2) == 2) return 1;
602
- if (!p) p = 1 * (0.3 * 1.5);
603
- if (a < Math.abs(1)) {
604
- a = 1;
605
- s = p / 4;
606
- } else s = p / (2 * Math.PI) * Math.asin(1 / a);
607
- if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
608
- return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;
609
- },
610
- easeInBack: function (t) {
611
- var s = 1.70158;
612
- return 1 * (t /= 1) * t * ((s + 1) * t - s);
613
- },
614
- easeOutBack: function (t) {
615
- var s = 1.70158;
616
- return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);
617
- },
618
- easeInOutBack: function (t) {
619
- var s = 1.70158;
620
- if ((t /= 1 / 2) < 1) return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));
621
- return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
622
- },
623
- easeInBounce: function (t) {
624
- return 1 - easingEffects.easeOutBounce(1 - t);
625
- },
626
- easeOutBounce: function (t) {
627
- if ((t /= 1) < (1 / 2.75)) {
628
- return 1 * (7.5625 * t * t);
629
- } else if (t < (2 / 2.75)) {
630
- return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);
631
- } else if (t < (2.5 / 2.75)) {
632
- return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);
633
- } else {
634
- return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);
635
- }
636
- },
637
- easeInOutBounce: function (t) {
638
- if (t < 1 / 2) return easingEffects.easeInBounce(t * 2) * 0.5;
639
- return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;
640
- }
641
- },
642
- //Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
643
- requestAnimFrame = helpers.requestAnimFrame = (function(){
644
- return window.requestAnimationFrame ||
645
- window.webkitRequestAnimationFrame ||
646
- window.mozRequestAnimationFrame ||
647
- window.oRequestAnimationFrame ||
648
- window.msRequestAnimationFrame ||
649
- function(callback) {
650
- return window.setTimeout(callback, 1000 / 60);
651
- };
652
- })(),
653
- cancelAnimFrame = helpers.cancelAnimFrame = (function(){
654
- return window.cancelAnimationFrame ||
655
- window.webkitCancelAnimationFrame ||
656
- window.mozCancelAnimationFrame ||
657
- window.oCancelAnimationFrame ||
658
- window.msCancelAnimationFrame ||
659
- function(callback) {
660
- return window.clearTimeout(callback, 1000 / 60);
661
- };
662
- })(),
663
- animationLoop = helpers.animationLoop = function(callback,totalSteps,easingString,onProgress,onComplete,chartInstance){
664
-
665
- var currentStep = 0,
666
- easingFunction = easingEffects[easingString] || easingEffects.linear;
667
-
668
- var animationFrame = function(){
669
- currentStep++;
670
- var stepDecimal = currentStep/totalSteps;
671
- var easeDecimal = easingFunction(stepDecimal);
672
-
673
- callback.call(chartInstance,easeDecimal,stepDecimal, currentStep);
674
- onProgress.call(chartInstance,easeDecimal,stepDecimal);
675
- if (currentStep < totalSteps){
676
- chartInstance.animationFrame = requestAnimFrame(animationFrame);
677
- } else{
678
- onComplete.apply(chartInstance);
679
- }
680
- };
681
- requestAnimFrame(animationFrame);
682
- },
683
- //-- DOM methods
684
- getRelativePosition = helpers.getRelativePosition = function(evt){
685
- var mouseX, mouseY;
686
- var e = evt.originalEvent || evt,
687
- canvas = evt.currentTarget || evt.srcElement,
688
- boundingRect = canvas.getBoundingClientRect();
689
-
690
- if (e.touches){
691
- mouseX = e.touches[0].clientX - boundingRect.left;
692
- mouseY = e.touches[0].clientY - boundingRect.top;
693
-
694
- }
695
- else{
696
- mouseX = e.clientX - boundingRect.left;
697
- mouseY = e.clientY - boundingRect.top;
698
- }
699
-
700
- return {
701
- x : mouseX,
702
- y : mouseY
703
- };
704
-
705
- },
706
- addEvent = helpers.addEvent = function(node,eventType,method){
707
- if (node.addEventListener){
708
- node.addEventListener(eventType,method);
709
- } else if (node.attachEvent){
710
- node.attachEvent("on"+eventType, method);
711
- } else {
712
- node["on"+eventType] = method;
713
- }
714
- },
715
- removeEvent = helpers.removeEvent = function(node, eventType, handler){
716
- if (node.removeEventListener){
717
- node.removeEventListener(eventType, handler, false);
718
- } else if (node.detachEvent){
719
- node.detachEvent("on"+eventType,handler);
720
- } else{
721
- node["on" + eventType] = noop;
722
- }
723
- },
724
- bindEvents = helpers.bindEvents = function(chartInstance, arrayOfEvents, handler){
725
- // Create the events object if it's not already present
726
- if (!chartInstance.events) chartInstance.events = {};
727
-
728
- each(arrayOfEvents,function(eventName){
729
- chartInstance.events[eventName] = function(){
730
- handler.apply(chartInstance, arguments);
731
- };
732
- addEvent(chartInstance.chart.canvas,eventName,chartInstance.events[eventName]);
733
- });
734
- },
735
- unbindEvents = helpers.unbindEvents = function (chartInstance, arrayOfEvents) {
736
- each(arrayOfEvents, function(handler,eventName){
737
- removeEvent(chartInstance.chart.canvas, eventName, handler);
738
- });
739
- },
740
- getMaximumWidth = helpers.getMaximumWidth = function(domNode){
741
- var container = domNode.parentNode;
742
- // TODO = check cross browser stuff with this.
743
- return container.clientWidth;
744
- },
745
- getMaximumHeight = helpers.getMaximumHeight = function(domNode){
746
- var container = domNode.parentNode;
747
- // TODO = check cross browser stuff with this.
748
- return container.clientHeight;
749
- },
750
- getMaximumSize = helpers.getMaximumSize = helpers.getMaximumWidth, // legacy support
751
- retinaScale = helpers.retinaScale = function(chart){
752
- var ctx = chart.ctx,
753
- width = chart.canvas.width,
754
- height = chart.canvas.height;
755
-
756
- if (window.devicePixelRatio) {
757
- ctx.canvas.style.width = width + "px";
758
- ctx.canvas.style.height = height + "px";
759
- ctx.canvas.height = height * window.devicePixelRatio;
760
- ctx.canvas.width = width * window.devicePixelRatio;
761
- ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
762
- }
763
- },
764
- //-- Canvas methods
765
- clear = helpers.clear = function(chart){
766
- chart.ctx.clearRect(0,0,chart.width,chart.height);
767
- },
768
- fontString = helpers.fontString = function(pixelSize,fontStyle,fontFamily){
769
- return fontStyle + " " + pixelSize+"px " + fontFamily;
770
- },
771
- longestText = helpers.longestText = function(ctx,font,arrayOfStrings){
772
- ctx.font = font;
773
- var longest = 0;
774
- each(arrayOfStrings,function(string){
775
- var textWidth = ctx.measureText(string).width;
776
- longest = (textWidth > longest) ? textWidth : longest;
777
- });
778
- return longest;
779
- },
780
- drawRoundedRectangle = helpers.drawRoundedRectangle = function(ctx,x,y,width,height,radius){
781
- ctx.beginPath();
782
- ctx.moveTo(x + radius, y);
783
- ctx.lineTo(x + width - radius, y);
784
- ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
785
- ctx.lineTo(x + width, y + height - radius);
786
- ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
787
- ctx.lineTo(x + radius, y + height);
788
- ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
789
- ctx.lineTo(x, y + radius);
790
- ctx.quadraticCurveTo(x, y, x + radius, y);
791
- ctx.closePath();
792
- };
793
-
794
-
795
- //Store a reference to each instance - allowing us to globally resize chart instances on window resize.
796
- //Destroy method on the chart will remove the instance of the chart from this reference.
797
- Chart.instances = {};
798
-
799
- Chart.Type = function(data,options,chart){
800
- this.options = options;
801
- this.chart = chart;
802
- this.id = uid();
803
- //Add the chart instance to the global namespace
804
- Chart.instances[this.id] = this;
805
-
806
- // Initialize is always called when a chart type is created
807
- // By default it is a no op, but it should be extended
808
- if (options.responsive){
809
- this.resize();
810
- }
811
- this.initialize.call(this,data);
812
- };
813
-
814
- //Core methods that'll be a part of every chart type
815
- extend(Chart.Type.prototype,{
816
- initialize : function(){return this;},
817
- clear : function(){
818
- clear(this.chart);
819
- return this;
820
- },
821
- stop : function(){
822
- // Stops any current animation loop occuring
823
- helpers.cancelAnimFrame.call(root, this.animationFrame);
824
- return this;
825
- },
826
- resize : function(callback){
827
- this.stop();
828
- var canvas = this.chart.canvas,
829
- newWidth = getMaximumWidth(this.chart.canvas),
830
- newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas);
831
-
832
- canvas.width = this.chart.width = newWidth;
833
- canvas.height = this.chart.height = newHeight;
834
-
835
- retinaScale(this.chart);
836
-
837
- if (typeof callback === "function"){
838
- callback.apply(this, Array.prototype.slice.call(arguments, 1));
839
- }
840
- return this;
841
- },
842
- reflow : noop,
843
- render : function(reflow){
844
- if (reflow){
845
- this.reflow();
846
- }
847
- if (this.options.animation && !reflow){
848
- helpers.animationLoop(
849
- this.draw,
850
- this.options.animationSteps,
851
- this.options.animationEasing,
852
- this.options.onAnimationProgress,
853
- this.options.onAnimationComplete,
854
- this
855
- );
856
- }
857
- else{
858
- this.draw();
859
- this.options.onAnimationComplete.call(this);
860
- }
861
- return this;
862
- },
863
- generateLegend : function(){
864
- return template(this.options.legendTemplate,this);
865
- },
866
- destroy : function(){
867
- this.clear();
868
- unbindEvents(this, this.events);
869
- delete Chart.instances[this.id];
870
- },
871
- showTooltip : function(ChartElements, forceRedraw){
872
- // Only redraw the chart if we've actually changed what we're hovering on.
873
- if (typeof this.activeElements === 'undefined') this.activeElements = [];
874
-
875
- var isChanged = (function(Elements){
876
- var changed = false;
877
-
878
- if (Elements.length !== this.activeElements.length){
879
- changed = true;
880
- return changed;
881
- }
882
-
883
- each(Elements, function(element, index){
884
- if (element !== this.activeElements[index]){
885
- changed = true;
886
- }
887
- }, this);
888
- return changed;
889
- }).call(this, ChartElements);
890
-
891
- if (!isChanged && !forceRedraw){
892
- return;
893
- }
894
- else{
895
- this.activeElements = ChartElements;
896
- }
897
- this.draw();
898
- if (ChartElements.length > 0){
899
- // If we have multiple datasets, show a MultiTooltip for all of the data points at that index
900
- if (this.datasets && this.datasets.length > 1) {
901
- var dataArray,
902
- dataIndex;
903
-
904
- for (var i = this.datasets.length - 1; i >= 0; i--) {
905
- dataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;
906
- dataIndex = indexOf(dataArray, ChartElements[0]);
907
- if (dataIndex !== -1){
908
- break;
909
- }
910
- }
911
- var tooltipLabels = [],
912
- tooltipColors = [],
913
- medianPosition = (function(index) {
914
-
915
- // Get all the points at that particular index
916
- var Elements = [],
917
- dataCollection,
918
- xPositions = [],
919
- yPositions = [],
920
- xMax,
921
- yMax,
922
- xMin,
923
- yMin;
924
- helpers.each(this.datasets, function(dataset){
925
- dataCollection = dataset.points || dataset.bars || dataset.segments;
926
- if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){
927
- Elements.push(dataCollection[dataIndex]);
928
- }
929
- });
930
-
931
- helpers.each(Elements, function(element) {
932
- xPositions.push(element.x);
933
- yPositions.push(element.y);
934
-
935
-
936
- //Include any colour information about the element
937
- tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element));
938
- tooltipColors.push({
939
- fill: element._saved.fillColor || element.fillColor,
940
- stroke: element._saved.strokeColor || element.strokeColor
941
- });
942
-
943
- }, this);
944
-
945
- yMin = min(yPositions);
946
- yMax = max(yPositions);
947
-
948
- xMin = min(xPositions);
949
- xMax = max(xPositions);
950
-
951
- return {
952
- x: (xMin > this.chart.width/2) ? xMin : xMax,
953
- y: (yMin + yMax)/2
954
- };
955
- }).call(this, dataIndex);
956
-
957
- new Chart.MultiTooltip({
958
- x: medianPosition.x,
959
- y: medianPosition.y,
960
- xPadding: this.options.tooltipXPadding,
961
- yPadding: this.options.tooltipYPadding,
962
- xOffset: this.options.tooltipXOffset,
963
- fillColor: this.options.tooltipFillColor,
964
- textColor: this.options.tooltipFontColor,
965
- fontFamily: this.options.tooltipFontFamily,
966
- fontStyle: this.options.tooltipFontStyle,
967
- fontSize: this.options.tooltipFontSize,
968
- titleTextColor: this.options.tooltipTitleFontColor,
969
- titleFontFamily: this.options.tooltipTitleFontFamily,
970
- titleFontStyle: this.options.tooltipTitleFontStyle,
971
- titleFontSize: this.options.tooltipTitleFontSize,
972
- cornerRadius: this.options.tooltipCornerRadius,
973
- labels: tooltipLabels,
974
- legendColors: tooltipColors,
975
- legendColorBackground : this.options.multiTooltipKeyBackground,
976
- title: ChartElements[0].label,
977
- chart: this.chart,
978
- ctx: this.chart.ctx
979
- }).draw();
980
-
981
- } else {
982
- each(ChartElements, function(Element) {
983
- var tooltipPosition = Element.tooltipPosition();
984
- new Chart.Tooltip({
985
- x: Math.round(tooltipPosition.x),
986
- y: Math.round(tooltipPosition.y),
987
- xPadding: this.options.tooltipXPadding,
988
- yPadding: this.options.tooltipYPadding,
989
- fillColor: this.options.tooltipFillColor,
990
- textColor: this.options.tooltipFontColor,
991
- fontFamily: this.options.tooltipFontFamily,
992
- fontStyle: this.options.tooltipFontStyle,
993
- fontSize: this.options.tooltipFontSize,
994
- caretHeight: this.options.tooltipCaretSize,
995
- cornerRadius: this.options.tooltipCornerRadius,
996
- text: template(this.options.tooltipTemplate, Element),
997
- chart: this.chart
998
- }).draw();
999
- }, this);
1000
- }
1001
- }
1002
- return this;
1003
- },
1004
- toBase64Image : function(){
1005
- return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
1006
- }
1007
- });
1008
-
1009
- Chart.Type.extend = function(extensions){
1010
-
1011
- var parent = this;
1012
-
1013
- var ChartType = function(){
1014
- return parent.apply(this,arguments);
1015
- };
1016
-
1017
- //Copy the prototype object of the this class
1018
- ChartType.prototype = clone(parent.prototype);
1019
- //Now overwrite some of the properties in the base class with the new extensions
1020
- extend(ChartType.prototype, extensions);
1021
-
1022
- ChartType.extend = Chart.Type.extend;
1023
-
1024
- if (extensions.name || parent.prototype.name){
1025
-
1026
- var chartName = extensions.name || parent.prototype.name;
1027
- //Assign any potential default values of the new chart type
1028
-
1029
- //If none are defined, we'll use a clone of the chart type this is being extended from.
1030
- //I.e. if we extend a line chart, we'll use the defaults from the line chart if our new chart
1031
- //doesn't define some defaults of their own.
1032
-
1033
- var baseDefaults = (Chart.defaults[parent.prototype.name]) ? clone(Chart.defaults[parent.prototype.name]) : {};
1034
-
1035
- Chart.defaults[chartName] = extend(baseDefaults,extensions.defaults);
1036
-
1037
- Chart.types[chartName] = ChartType;
1038
-
1039
- //Register this new chart type in the Chart prototype
1040
- Chart.prototype[chartName] = function(data,options){
1041
- var config = merge(Chart.defaults.global, Chart.defaults[chartName], options || {});
1042
- return new ChartType(data,config,this);
1043
- };
1044
- } else{
1045
- warn("Name not provided for this chart, so it hasn't been registered");
1046
- }
1047
- return parent;
1048
- };
1049
-
1050
- Chart.Element = function(configuration){
1051
- extend(this,configuration);
1052
- this.initialize.apply(this,arguments);
1053
- this.save();
1054
- };
1055
- extend(Chart.Element.prototype,{
1056
- initialize : function(){},
1057
- restore : function(props){
1058
- if (!props){
1059
- extend(this,this._saved);
1060
- } else {
1061
- each(props,function(key){
1062
- this[key] = this._saved[key];
1063
- },this);
1064
- }
1065
- return this;
1066
- },
1067
- save : function(){
1068
- this._saved = clone(this);
1069
- delete this._saved._saved;
1070
- return this;
1071
- },
1072
- update : function(newProps){
1073
- each(newProps,function(value,key){
1074
- this._saved[key] = this[key];
1075
- this[key] = value;
1076
- },this);
1077
- return this;
1078
- },
1079
- transition : function(props,ease){
1080
- each(props,function(value,key){
1081
- this[key] = ((value - this._saved[key]) * ease) + this._saved[key];
1082
- },this);
1083
- return this;
1084
- },
1085
- tooltipPosition : function(){
1086
- return {
1087
- x : this.x,
1088
- y : this.y
1089
- };
1090
- },
1091
- hasValue: function(){
1092
- return isNumber(this.value);
1093
- }
1094
- });
1095
-
1096
- Chart.Element.extend = inherits;
1097
-
1098
-
1099
- Chart.Point = Chart.Element.extend({
1100
- display: true,
1101
- inRange: function(chartX,chartY){
1102
- var hitDetectionRange = this.hitDetectionRadius + this.radius;
1103
- return ((Math.pow(chartX-this.x, 2)+Math.pow(chartY-this.y, 2)) < Math.pow(hitDetectionRange,2));
1104
- },
1105
- draw : function(){
1106
- if (this.display){
1107
- var ctx = this.ctx;
1108
- ctx.beginPath();
1109
-
1110
- ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
1111
- ctx.closePath();
1112
-
1113
- ctx.strokeStyle = this.strokeColor;
1114
- ctx.lineWidth = this.strokeWidth;
1115
-
1116
- ctx.fillStyle = this.fillColor;
1117
-
1118
- ctx.fill();
1119
- ctx.stroke();
1120
- }
1121
-
1122
-
1123
- //Quick debug for bezier curve splining
1124
- //Highlights control points and the line between them.
1125
- //Handy for dev - stripped in the min version.
1126
-
1127
- // ctx.save();
1128
- // ctx.fillStyle = "black";
1129
- // ctx.strokeStyle = "black"
1130
- // ctx.beginPath();
1131
- // ctx.arc(this.controlPoints.inner.x,this.controlPoints.inner.y, 2, 0, Math.PI*2);
1132
- // ctx.fill();
1133
-
1134
- // ctx.beginPath();
1135
- // ctx.arc(this.controlPoints.outer.x,this.controlPoints.outer.y, 2, 0, Math.PI*2);
1136
- // ctx.fill();
1137
-
1138
- // ctx.moveTo(this.controlPoints.inner.x,this.controlPoints.inner.y);
1139
- // ctx.lineTo(this.x, this.y);
1140
- // ctx.lineTo(this.controlPoints.outer.x,this.controlPoints.outer.y);
1141
- // ctx.stroke();
1142
-
1143
- // ctx.restore();
1144
-
1145
-
1146
-
1147
- }
1148
- });
1149
-
1150
- Chart.Arc = Chart.Element.extend({
1151
- inRange : function(chartX,chartY){
1152
-
1153
- var pointRelativePosition = helpers.getAngleFromPoint(this, {
1154
- x: chartX,
1155
- y: chartY
1156
- });
1157
-
1158
- //Check if within the range of the open/close angle
1159
- var betweenAngles = (pointRelativePosition.angle >= this.startAngle && pointRelativePosition.angle <= this.endAngle),
1160
- withinRadius = (pointRelativePosition.distance >= this.innerRadius && pointRelativePosition.distance <= this.outerRadius);
1161
-
1162
- return (betweenAngles && withinRadius);
1163
- //Ensure within the outside of the arc centre, but inside arc outer
1164
- },
1165
- tooltipPosition : function(){
1166
- var centreAngle = this.startAngle + ((this.endAngle - this.startAngle) / 2),
1167
- rangeFromCentre = (this.outerRadius - this.innerRadius) / 2 + this.innerRadius;
1168
- return {
1169
- x : this.x + (Math.cos(centreAngle) * rangeFromCentre),
1170
- y : this.y + (Math.sin(centreAngle) * rangeFromCentre)
1171
- };
1172
- },
1173
- draw : function(animationPercent){
1174
-
1175
- var easingDecimal = animationPercent || 1;
1176
-
1177
- var ctx = this.ctx;
1178
-
1179
- ctx.beginPath();
1180
-
1181
- ctx.arc(this.x, this.y, this.outerRadius, this.startAngle, this.endAngle);
1182
-
1183
- ctx.arc(this.x, this.y, this.innerRadius, this.endAngle, this.startAngle, true);
1184
-
1185
- ctx.closePath();
1186
- ctx.strokeStyle = this.strokeColor;
1187
- ctx.lineWidth = this.strokeWidth;
1188
-
1189
- ctx.fillStyle = this.fillColor;
1190
-
1191
- ctx.fill();
1192
- ctx.lineJoin = 'bevel';
1193
-
1194
- if (this.showStroke){
1195
- ctx.stroke();
1196
- }
1197
- }
1198
- });
1199
-
1200
- Chart.Rectangle = Chart.Element.extend({
1201
- draw : function(){
1202
- var ctx = this.ctx,
1203
- halfWidth = this.width/2,
1204
- leftX = this.x - halfWidth,
1205
- rightX = this.x + halfWidth,
1206
- top = this.base - (this.base - this.y),
1207
- halfStroke = this.strokeWidth / 2;
1208
-
1209
- // Canvas doesn't allow us to stroke inside the width so we can
1210
- // adjust the sizes to fit if we're setting a stroke on the line
1211
- if (this.showStroke){
1212
- leftX += halfStroke;
1213
- rightX -= halfStroke;
1214
- top += halfStroke;
1215
- }
1216
-
1217
- ctx.beginPath();
1218
-
1219
- ctx.fillStyle = this.fillColor;
1220
- ctx.strokeStyle = this.strokeColor;
1221
- ctx.lineWidth = this.strokeWidth;
1222
-
1223
- // It'd be nice to keep this class totally generic to any rectangle
1224
- // and simply specify which border to miss out.
1225
- ctx.moveTo(leftX, this.base);
1226
- ctx.lineTo(leftX, top);
1227
- ctx.lineTo(rightX, top);
1228
- ctx.lineTo(rightX, this.base);
1229
- ctx.fill();
1230
- if (this.showStroke){
1231
- ctx.stroke();
1232
- }
1233
- },
1234
- height : function(){
1235
- return this.base - this.y;
1236
- },
1237
- inRange : function(chartX,chartY){
1238
- return (chartX >= this.x - this.width/2 && chartX <= this.x + this.width/2) && (chartY >= this.y && chartY <= this.base);
1239
- }
1240
- });
1241
-
1242
- Chart.Tooltip = Chart.Element.extend({
1243
- draw : function(){
1244
-
1245
- var ctx = this.chart.ctx;
1246
-
1247
- ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
1248
-
1249
- this.xAlign = "center";
1250
- this.yAlign = "above";
1251
-
1252
- //Distance between the actual element.y position and the start of the tooltip caret
1253
- var caretPadding = 2;
1254
-
1255
- var tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding,
1256
- tooltipRectHeight = this.fontSize + 2*this.yPadding,
1257
- tooltipHeight = tooltipRectHeight + this.caretHeight + caretPadding;
1258
-
1259
- if (this.x + tooltipWidth/2 >this.chart.width){
1260
- this.xAlign = "left";
1261
- } else if (this.x - tooltipWidth/2 < 0){
1262
- this.xAlign = "right";
1263
- }
1264
-
1265
- if (this.y - tooltipHeight < 0){
1266
- this.yAlign = "below";
1267
- }
1268
-
1269
-
1270
- var tooltipX = this.x - tooltipWidth/2,
1271
- tooltipY = this.y - tooltipHeight;
1272
-
1273
- ctx.fillStyle = this.fillColor;
1274
-
1275
- switch(this.yAlign)
1276
- {
1277
- case "above":
1278
- //Draw a caret above the x/y
1279
- ctx.beginPath();
1280
- ctx.moveTo(this.x,this.y - caretPadding);
1281
- ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));
1282
- ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));
1283
- ctx.closePath();
1284
- ctx.fill();
1285
- break;
1286
- case "below":
1287
- tooltipY = this.y + caretPadding + this.caretHeight;
1288
- //Draw a caret below the x/y
1289
- ctx.beginPath();
1290
- ctx.moveTo(this.x, this.y + caretPadding);
1291
- ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);
1292
- ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);
1293
- ctx.closePath();
1294
- ctx.fill();
1295
- break;
1296
- }
1297
-
1298
- switch(this.xAlign)
1299
- {
1300
- case "left":
1301
- tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);
1302
- break;
1303
- case "right":
1304
- tooltipX = this.x - (this.cornerRadius + this.caretHeight);
1305
- break;
1306
- }
1307
-
1308
- drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);
1309
-
1310
- ctx.fill();
1311
-
1312
- ctx.fillStyle = this.textColor;
1313
- ctx.textAlign = "center";
1314
- ctx.textBaseline = "middle";
1315
- ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);
1316
- }
1317
- });
1318
-
1319
- Chart.MultiTooltip = Chart.Element.extend({
1320
- initialize : function(){
1321
- this.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
1322
-
1323
- this.titleFont = fontString(this.titleFontSize,this.titleFontStyle,this.titleFontFamily);
1324
-
1325
- this.height = (this.labels.length * this.fontSize) + ((this.labels.length-1) * (this.fontSize/2)) + (this.yPadding*2) + this.titleFontSize *1.5;
1326
-
1327
- this.ctx.font = this.titleFont;
1328
-
1329
- var titleWidth = this.ctx.measureText(this.title).width,
1330
- //Label has a legend square as well so account for this.
1331
- labelWidth = longestText(this.ctx,this.font,this.labels) + this.fontSize + 3,
1332
- longestTextWidth = max([labelWidth,titleWidth]);
1333
-
1334
- this.width = longestTextWidth + (this.xPadding*2);
1335
-
1336
-
1337
- var halfHeight = this.height/2;
1338
-
1339
- //Check to ensure the height will fit on the canvas
1340
- //The three is to buffer form the very
1341
- if (this.y - halfHeight < 0 ){
1342
- this.y = halfHeight;
1343
- } else if (this.y + halfHeight > this.chart.height){
1344
- this.y = this.chart.height - halfHeight;
1345
- }
1346
-
1347
- //Decide whether to align left or right based on position on canvas
1348
- if (this.x > this.chart.width/2){
1349
- this.x -= this.xOffset + this.width;
1350
- } else {
1351
- this.x += this.xOffset;
1352
- }
1353
-
1354
-
1355
- },
1356
- getLineHeight : function(index){
1357
- var baseLineHeight = this.y - (this.height/2) + this.yPadding,
1358
- afterTitleIndex = index-1;
1359
-
1360
- //If the index is zero, we're getting the title
1361
- if (index === 0){
1362
- return baseLineHeight + this.titleFontSize/2;
1363
- } else{
1364
- return baseLineHeight + ((this.fontSize*1.5*afterTitleIndex) + this.fontSize/2) + this.titleFontSize * 1.5;
1365
- }
1366
-
1367
- },
1368
- draw : function(){
1369
- drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);
1370
- var ctx = this.ctx;
1371
- ctx.fillStyle = this.fillColor;
1372
- ctx.fill();
1373
- ctx.closePath();
1374
-
1375
- ctx.textAlign = "left";
1376
- ctx.textBaseline = "middle";
1377
- ctx.fillStyle = this.titleTextColor;
1378
- ctx.font = this.titleFont;
1379
-
1380
- ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));
1381
-
1382
- ctx.font = this.font;
1383
- helpers.each(this.labels,function(label,index){
1384
- ctx.fillStyle = this.textColor;
1385
- ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));
1386
-
1387
- //A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)
1388
- //ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
1389
- //Instead we'll make a white filled block to put the legendColour palette over.
1390
-
1391
- ctx.fillStyle = this.legendColorBackground;
1392
- ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
1393
-
1394
- ctx.fillStyle = this.legendColors[index].fill;
1395
- ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
1396
-
1397
-
1398
- },this);
1399
- }
1400
- });
1401
-
1402
- Chart.Scale = Chart.Element.extend({
1403
- initialize : function(){
1404
- this.fit();
1405
- },
1406
- buildYLabels : function(){
1407
- this.yLabels = [];
1408
-
1409
- var stepDecimalPlaces = getDecimalPlaces(this.stepValue);
1410
-
1411
- for (var i=0; i<=this.steps; i++){
1412
- this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));
1413
- }
1414
- this.yLabelWidth = (this.display && this.showLabels) ? longestText(this.ctx,this.font,this.yLabels) : 0;
1415
- },
1416
- addXLabel : function(label){
1417
- this.xLabels.push(label);
1418
- this.valuesCount++;
1419
- this.fit();
1420
- },
1421
- removeXLabel : function(){
1422
- this.xLabels.shift();
1423
- this.valuesCount--;
1424
- this.fit();
1425
- },
1426
- // Fitting loop to rotate x Labels and figure out what fits there, and also calculate how many Y steps to use
1427
- fit: function(){
1428
- // First we need the width of the yLabels, assuming the xLabels aren't rotated
1429
-
1430
- // To do that we need the base line at the top and base of the chart, assuming there is no x label rotation
1431
- this.startPoint = (this.display) ? this.fontSize : 0;
1432
- this.endPoint = (this.display) ? this.height - (this.fontSize * 1.5) - 5 : this.height; // -5 to pad labels
1433
-
1434
- // Apply padding settings to the start and end point.
1435
- this.startPoint += this.padding;
1436
- this.endPoint -= this.padding;
1437
-
1438
- // Cache the starting height, so can determine if we need to recalculate the scale yAxis
1439
- var cachedHeight = this.endPoint - this.startPoint,
1440
- cachedYLabelWidth;
1441
-
1442
- // Build the current yLabels so we have an idea of what size they'll be to start
1443
- /*
1444
- * This sets what is returned from calculateScaleRange as static properties of this class:
1445
- *
1446
- this.steps;
1447
- this.stepValue;
1448
- this.min;
1449
- this.max;
1450
- *
1451
- */
1452
- this.calculateYRange(cachedHeight);
1453
-
1454
- // With these properties set we can now build the array of yLabels
1455
- // and also the width of the largest yLabel
1456
- this.buildYLabels();
1457
-
1458
- this.calculateXLabelRotation();
1459
-
1460
- while((cachedHeight > this.endPoint - this.startPoint)){
1461
- cachedHeight = this.endPoint - this.startPoint;
1462
- cachedYLabelWidth = this.yLabelWidth;
1463
-
1464
- this.calculateYRange(cachedHeight);
1465
- this.buildYLabels();
1466
-
1467
- // Only go through the xLabel loop again if the yLabel width has changed
1468
- if (cachedYLabelWidth < this.yLabelWidth){
1469
- this.calculateXLabelRotation();
1470
- }
1471
- }
1472
-
1473
- },
1474
- calculateXLabelRotation : function(){
1475
- //Get the width of each grid by calculating the difference
1476
- //between x offsets between 0 and 1.
1477
-
1478
- this.ctx.font = this.font;
1479
-
1480
- var firstWidth = this.ctx.measureText(this.xLabels[0]).width,
1481
- lastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width,
1482
- firstRotated,
1483
- lastRotated;
1484
-
1485
-
1486
- this.xScalePaddingRight = lastWidth/2 + 3;
1487
- this.xScalePaddingLeft = (firstWidth/2 > this.yLabelWidth + 10) ? firstWidth/2 : this.yLabelWidth + 10;
1488
-
1489
- this.xLabelRotation = 0;
1490
- if (this.display){
1491
- var originalLabelWidth = longestText(this.ctx,this.font,this.xLabels),
1492
- cosRotation,
1493
- firstRotatedWidth;
1494
- this.xLabelWidth = originalLabelWidth;
1495
- //Allow 3 pixels x2 padding either side for label readability
1496
- var xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6;
1497
-
1498
- //Max label rotate should be 90 - also act as a loop counter
1499
- while ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)){
1500
- cosRotation = Math.cos(toRadians(this.xLabelRotation));
1501
-
1502
- firstRotated = cosRotation * firstWidth;
1503
- lastRotated = cosRotation * lastWidth;
1504
-
1505
- // We're right aligning the text now.
1506
- if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8){
1507
- this.xScalePaddingLeft = firstRotated + this.fontSize / 2;
1508
- }
1509
- this.xScalePaddingRight = this.fontSize/2;
1510
-
1511
-
1512
- this.xLabelRotation++;
1513
- this.xLabelWidth = cosRotation * originalLabelWidth;
1514
-
1515
- }
1516
- if (this.xLabelRotation > 0){
1517
- this.endPoint -= Math.sin(toRadians(this.xLabelRotation))*originalLabelWidth + 3;
1518
- }
1519
- }
1520
- else{
1521
- this.xLabelWidth = 0;
1522
- this.xScalePaddingRight = this.padding;
1523
- this.xScalePaddingLeft = this.padding;
1524
- }
1525
-
1526
- },
1527
- // Needs to be overidden in each Chart type
1528
- // Otherwise we need to pass all the data into the scale class
1529
- calculateYRange: noop,
1530
- drawingArea: function(){
1531
- return this.startPoint - this.endPoint;
1532
- },
1533
- calculateY : function(value){
1534
- var scalingFactor = this.drawingArea() / (this.min - this.max);
1535
- return this.endPoint - (scalingFactor * (value - this.min));
1536
- },
1537
- calculateX : function(index){
1538
- var isRotated = (this.xLabelRotation > 0),
1539
- // innerWidth = (this.offsetGridLines) ? this.width - offsetLeft - this.padding : this.width - (offsetLeft + halfLabelWidth * 2) - this.padding,
1540
- innerWidth = this.width - (this.xScalePaddingLeft + this.xScalePaddingRight),
1541
- valueWidth = innerWidth/(this.valuesCount - ((this.offsetGridLines) ? 0 : 1)),
1542
- valueOffset = (valueWidth * index) + this.xScalePaddingLeft;
1543
-
1544
- if (this.offsetGridLines){
1545
- valueOffset += (valueWidth/2);
1546
- }
1547
-
1548
- return Math.round(valueOffset);
1549
- },
1550
- update : function(newProps){
1551
- helpers.extend(this, newProps);
1552
- this.fit();
1553
- },
1554
- draw : function(){
1555
- var ctx = this.ctx,
1556
- yLabelGap = (this.endPoint - this.startPoint) / this.steps,
1557
- xStart = Math.round(this.xScalePaddingLeft);
1558
- if (this.display){
1559
- ctx.fillStyle = this.textColor;
1560
- ctx.font = this.font;
1561
- each(this.yLabels,function(labelString,index){
1562
- var yLabelCenter = this.endPoint - (yLabelGap * index),
1563
- linePositionY = Math.round(yLabelCenter);
1564
-
1565
- ctx.textAlign = "right";
1566
- ctx.textBaseline = "middle";
1567
- if (this.showLabels){
1568
- ctx.fillText(labelString,xStart - 10,yLabelCenter);
1569
- }
1570
- ctx.beginPath();
1571
- if (index > 0){
1572
- // This is a grid line in the centre, so drop that
1573
- ctx.lineWidth = this.gridLineWidth;
1574
- ctx.strokeStyle = this.gridLineColor;
1575
- } else {
1576
- // This is the first line on the scale
1577
- ctx.lineWidth = this.lineWidth;
1578
- ctx.strokeStyle = this.lineColor;
1579
- }
1580
-
1581
- linePositionY += helpers.aliasPixel(ctx.lineWidth);
1582
-
1583
- ctx.moveTo(xStart, linePositionY);
1584
- ctx.lineTo(this.width, linePositionY);
1585
- ctx.stroke();
1586
- ctx.closePath();
1587
-
1588
- ctx.lineWidth = this.lineWidth;
1589
- ctx.strokeStyle = this.lineColor;
1590
- ctx.beginPath();
1591
- ctx.moveTo(xStart - 5, linePositionY);
1592
- ctx.lineTo(xStart, linePositionY);
1593
- ctx.stroke();
1594
- ctx.closePath();
1595
-
1596
- },this);
1597
-
1598
- each(this.xLabels,function(label,index){
1599
- var xPos = this.calculateX(index) + aliasPixel(this.lineWidth),
1600
- // Check to see if line/bar here and decide where to place the line
1601
- linePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth),
1602
- isRotated = (this.xLabelRotation > 0);
1603
-
1604
- ctx.beginPath();
1605
-
1606
- if (index > 0){
1607
- // This is a grid line in the centre, so drop that
1608
- ctx.lineWidth = this.gridLineWidth;
1609
- ctx.strokeStyle = this.gridLineColor;
1610
- } else {
1611
- // This is the first line on the scale
1612
- ctx.lineWidth = this.lineWidth;
1613
- ctx.strokeStyle = this.lineColor;
1614
- }
1615
- ctx.moveTo(linePos,this.endPoint);
1616
- ctx.lineTo(linePos,this.startPoint - 3);
1617
- ctx.stroke();
1618
- ctx.closePath();
1619
-
1620
-
1621
- ctx.lineWidth = this.lineWidth;
1622
- ctx.strokeStyle = this.lineColor;
1623
-
1624
-
1625
- // Small lines at the bottom of the base grid line
1626
- ctx.beginPath();
1627
- ctx.moveTo(linePos,this.endPoint);
1628
- ctx.lineTo(linePos,this.endPoint + 5);
1629
- ctx.stroke();
1630
- ctx.closePath();
1631
-
1632
- ctx.save();
1633
- ctx.translate(xPos,(isRotated) ? this.endPoint + 12 : this.endPoint + 8);
1634
- ctx.rotate(toRadians(this.xLabelRotation)*-1);
1635
- ctx.font = this.font;
1636
- ctx.textAlign = (isRotated) ? "right" : "center";
1637
- ctx.textBaseline = (isRotated) ? "middle" : "top";
1638
- ctx.fillText(label, 0, 0);
1639
- ctx.restore();
1640
- },this);
1641
-
1642
- }
1643
- }
1644
-
1645
- });
1646
-
1647
- Chart.RadialScale = Chart.Element.extend({
1648
- initialize: function(){
1649
- this.size = min([this.height, this.width]);
1650
- this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);
1651
- },
1652
- calculateCenterOffset: function(value){
1653
- // Take into account half font size + the yPadding of the top value
1654
- var scalingFactor = this.drawingArea / (this.max - this.min);
1655
-
1656
- return (value - this.min) * scalingFactor;
1657
- },
1658
- update : function(){
1659
- if (!this.lineArc){
1660
- this.setScaleSize();
1661
- } else {
1662
- this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);
1663
- }
1664
- this.buildYLabels();
1665
- },
1666
- buildYLabels: function(){
1667
- this.yLabels = [];
1668
-
1669
- var stepDecimalPlaces = getDecimalPlaces(this.stepValue);
1670
-
1671
- for (var i=0; i<=this.steps; i++){
1672
- this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));
1673
- }
1674
- },
1675
- getCircumference : function(){
1676
- return ((Math.PI*2) / this.valuesCount);
1677
- },
1678
- setScaleSize: function(){
1679
- /*
1680
- * Right, this is really confusing and there is a lot of maths going on here
1681
- * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
1682
- *
1683
- * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif
1684
- *
1685
- * Solution:
1686
- *
1687
- * We assume the radius of the polygon is half the size of the canvas at first
1688
- * at each index we check if the text overlaps.
1689
- *
1690
- * Where it does, we store that angle and that index.
1691
- *
1692
- * After finding the largest index and angle we calculate how much we need to remove
1693
- * from the shape radius to move the point inwards by that x.
1694
- *
1695
- * We average the left and right distances to get the maximum shape radius that can fit in the box
1696
- * along with labels.
1697
- *
1698
- * Once we have that, we can find the centre point for the chart, by taking the x text protrusion
1699
- * on each side, removing that from the size, halving it and adding the left x protrusion width.
1700
- *
1701
- * This will mean we have a shape fitted to the canvas, as large as it can be with the labels
1702
- * and position it in the most space efficient manner
1703
- *
1704
- * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif
1705
- */
1706
-
1707
-
1708
- // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.
1709
- // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points
1710
- var largestPossibleRadius = min([(this.height/2 - this.pointLabelFontSize - 5), this.width/2]),
1711
- pointPosition,
1712
- i,
1713
- textWidth,
1714
- halfTextWidth,
1715
- furthestRight = this.width,
1716
- furthestRightIndex,
1717
- furthestRightAngle,
1718
- furthestLeft = 0,
1719
- furthestLeftIndex,
1720
- furthestLeftAngle,
1721
- xProtrusionLeft,
1722
- xProtrusionRight,
1723
- radiusReductionRight,
1724
- radiusReductionLeft,
1725
- maxWidthRadius;
1726
- this.ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);
1727
- for (i=0;i<this.valuesCount;i++){
1728
- // 5px to space the text slightly out - similar to what we do in the draw function.
1729
- pointPosition = this.getPointPosition(i, largestPossibleRadius);
1730
- textWidth = this.ctx.measureText(template(this.templateString, { value: this.labels[i] })).width + 5;
1731
- if (i === 0 || i === this.valuesCount/2){
1732
- // If we're at index zero, or exactly the middle, we're at exactly the top/bottom
1733
- // of the radar chart, so text will be aligned centrally, so we'll half it and compare
1734
- // w/left and right text sizes
1735
- halfTextWidth = textWidth/2;
1736
- if (pointPosition.x + halfTextWidth > furthestRight) {
1737
- furthestRight = pointPosition.x + halfTextWidth;
1738
- furthestRightIndex = i;
1739
- }
1740
- if (pointPosition.x - halfTextWidth < furthestLeft) {
1741
- furthestLeft = pointPosition.x - halfTextWidth;
1742
- furthestLeftIndex = i;
1743
- }
1744
- }
1745
- else if (i < this.valuesCount/2) {
1746
- // Less than half the values means we'll left align the text
1747
- if (pointPosition.x + textWidth > furthestRight) {
1748
- furthestRight = pointPosition.x + textWidth;
1749
- furthestRightIndex = i;
1750
- }
1751
- }
1752
- else if (i > this.valuesCount/2){
1753
- // More than half the values means we'll right align the text
1754
- if (pointPosition.x - textWidth < furthestLeft) {
1755
- furthestLeft = pointPosition.x - textWidth;
1756
- furthestLeftIndex = i;
1757
- }
1758
- }
1759
- }
1760
-
1761
- xProtrusionLeft = furthestLeft;
1762
-
1763
- xProtrusionRight = Math.ceil(furthestRight - this.width);
1764
-
1765
- furthestRightAngle = this.getIndexAngle(furthestRightIndex);
1766
-
1767
- furthestLeftAngle = this.getIndexAngle(furthestLeftIndex);
1768
-
1769
- radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI/2);
1770
-
1771
- radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI/2);
1772
-
1773
- // Ensure we actually need to reduce the size of the chart
1774
- radiusReductionRight = (isNumber(radiusReductionRight)) ? radiusReductionRight : 0;
1775
- radiusReductionLeft = (isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;
1776
-
1777
- this.drawingArea = largestPossibleRadius - (radiusReductionLeft + radiusReductionRight)/2;
1778
-
1779
- //this.drawingArea = min([maxWidthRadius, (this.height - (2 * (this.pointLabelFontSize + 5)))/2])
1780
- this.setCenterPoint(radiusReductionLeft, radiusReductionRight);
1781
-
1782
- },
1783
- setCenterPoint: function(leftMovement, rightMovement){
1784
-
1785
- var maxRight = this.width - rightMovement - this.drawingArea,
1786
- maxLeft = leftMovement + this.drawingArea;
1787
-
1788
- this.xCenter = (maxLeft + maxRight)/2;
1789
- // Always vertically in the centre as the text height doesn't change
1790
- this.yCenter = (this.height/2);
1791
- },
1792
-
1793
- getIndexAngle : function(index){
1794
- var angleMultiplier = (Math.PI * 2) / this.valuesCount;
1795
- // Start from the top instead of right, so remove a quarter of the circle
1796
-
1797
- return index * angleMultiplier - (Math.PI/2);
1798
- },
1799
- getPointPosition : function(index, distanceFromCenter){
1800
- var thisAngle = this.getIndexAngle(index);
1801
- return {
1802
- x : (Math.cos(thisAngle) * distanceFromCenter) + this.xCenter,
1803
- y : (Math.sin(thisAngle) * distanceFromCenter) + this.yCenter
1804
- };
1805
- },
1806
- draw: function(){
1807
- if (this.display){
1808
- var ctx = this.ctx;
1809
- each(this.yLabels, function(label, index){
1810
- // Don't draw a centre value
1811
- if (index > 0){
1812
- var yCenterOffset = index * (this.drawingArea/this.steps),
1813
- yHeight = this.yCenter - yCenterOffset,
1814
- pointPosition;
1815
-
1816
- // Draw circular lines around the scale
1817
- if (this.lineWidth > 0){
1818
- ctx.strokeStyle = this.lineColor;
1819
- ctx.lineWidth = this.lineWidth;
1820
-
1821
- if(this.lineArc){
1822
- ctx.beginPath();
1823
- ctx.arc(this.xCenter, this.yCenter, yCenterOffset, 0, Math.PI*2);
1824
- ctx.closePath();
1825
- ctx.stroke();
1826
- } else{
1827
- ctx.beginPath();
1828
- for (var i=0;i<this.valuesCount;i++)
1829
- {
1830
- pointPosition = this.getPointPosition(i, this.calculateCenterOffset(this.min + (index * this.stepValue)));
1831
- if (i === 0){
1832
- ctx.moveTo(pointPosition.x, pointPosition.y);
1833
- } else {
1834
- ctx.lineTo(pointPosition.x, pointPosition.y);
1835
- }
1836
- }
1837
- ctx.closePath();
1838
- ctx.stroke();
1839
- }
1840
- }
1841
- if(this.showLabels){
1842
- ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
1843
- if (this.showLabelBackdrop){
1844
- var labelWidth = ctx.measureText(label).width;
1845
- ctx.fillStyle = this.backdropColor;
1846
- ctx.fillRect(
1847
- this.xCenter - labelWidth/2 - this.backdropPaddingX,
1848
- yHeight - this.fontSize/2 - this.backdropPaddingY,
1849
- labelWidth + this.backdropPaddingX*2,
1850
- this.fontSize + this.backdropPaddingY*2
1851
- );
1852
- }
1853
- ctx.textAlign = 'center';
1854
- ctx.textBaseline = "middle";
1855
- ctx.fillStyle = this.fontColor;
1856
- ctx.fillText(label, this.xCenter, yHeight);
1857
- }
1858
- }
1859
- }, this);
1860
-
1861
- if (!this.lineArc){
1862
- ctx.lineWidth = this.angleLineWidth;
1863
- ctx.strokeStyle = this.angleLineColor;
1864
- for (var i = this.valuesCount - 1; i >= 0; i--) {
1865
- if (this.angleLineWidth > 0){
1866
- var outerPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max));
1867
- ctx.beginPath();
1868
- ctx.moveTo(this.xCenter, this.yCenter);
1869
- ctx.lineTo(outerPosition.x, outerPosition.y);
1870
- ctx.stroke();
1871
- ctx.closePath();
1872
- }
1873
- // Extra 3px out for some label spacing
1874
- var pointLabelPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max) + 5);
1875
- ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);
1876
- ctx.fillStyle = this.pointLabelFontColor;
1877
-
1878
- var labelsCount = this.labels.length,
1879
- halfLabelsCount = this.labels.length/2,
1880
- quarterLabelsCount = halfLabelsCount/2,
1881
- upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
1882
- exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
1883
- if (i === 0){
1884
- ctx.textAlign = 'center';
1885
- } else if(i === halfLabelsCount){
1886
- ctx.textAlign = 'center';
1887
- } else if (i < halfLabelsCount){
1888
- ctx.textAlign = 'left';
1889
- } else {
1890
- ctx.textAlign = 'right';
1891
- }
1892
-
1893
- // Set the correct text baseline based on outer positioning
1894
- if (exactQuarter){
1895
- ctx.textBaseline = 'middle';
1896
- } else if (upperHalf){
1897
- ctx.textBaseline = 'bottom';
1898
- } else {
1899
- ctx.textBaseline = 'top';
1900
- }
1901
-
1902
- ctx.fillText(this.labels[i], pointLabelPosition.x, pointLabelPosition.y);
1903
- }
1904
- }
1905
- }
1906
- }
1907
- });
1908
-
1909
- // Attach global event to resize each chart instance when the browser resizes
1910
- helpers.addEvent(window, "resize", (function(){
1911
- // Basic debounce of resize function so it doesn't hurt performance when resizing browser.
1912
- var timeout;
1913
- return function(){
1914
- clearTimeout(timeout);
1915
- timeout = setTimeout(function(){
1916
- each(Chart.instances,function(instance){
1917
- // If the responsive flag is set in the chart instance config
1918
- // Cascade the resize event down to the chart.
1919
- if (instance.options.responsive){
1920
- instance.resize(instance.render, true);
1921
- }
1922
- });
1923
- }, 50);
1924
- };
1925
- })());
1926
-
1927
-
1928
- if (amd) {
1929
- define(function(){
1930
- return Chart;
1931
- });
1932
- } else if (typeof module === 'object' && module.exports) {
1933
- module.exports = Chart;
1934
- }
1935
-
1936
- root.Chart = Chart;
1937
-
1938
- Chart.noConflict = function(){
1939
- root.Chart = previous;
1940
- return Chart;
1941
- };
1942
-
1943
- }).call(this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/src/Chart.Doughnut.js DELETED
@@ -1,184 +0,0 @@
1
- (function(){
2
- "use strict";
3
-
4
- var root = this,
5
- Chart = root.Chart,
6
- //Cache a local reference to Chart.helpers
7
- helpers = Chart.helpers;
8
-
9
- var defaultConfig = {
10
- //Boolean - Whether we should show a stroke on each segment
11
- segmentShowStroke : true,
12
-
13
- //String - The colour of each segment stroke
14
- segmentStrokeColor : "#fff",
15
-
16
- //Number - The width of each segment stroke
17
- segmentStrokeWidth : 2,
18
-
19
- //The percentage of the chart that we cut out of the middle.
20
- percentageInnerCutout : 50,
21
-
22
- //Number - Amount of animation steps
23
- animationSteps : 100,
24
-
25
- //String - Animation easing effect
26
- animationEasing : "easeOutBounce",
27
-
28
- //Boolean - Whether we animate the rotation of the Doughnut
29
- animateRotate : true,
30
-
31
- //Boolean - Whether we animate scaling the Doughnut from the centre
32
- animateScale : false,
33
-
34
- //String - A legend template
35
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
36
-
37
- };
38
-
39
-
40
- Chart.Type.extend({
41
- //Passing in a name registers this chart in the Chart namespace
42
- name: "Doughnut",
43
- //Providing a defaults will also register the deafults in the chart namespace
44
- defaults : defaultConfig,
45
- //Initialize is fired when the chart is initialized - Data is passed in as a parameter
46
- //Config is automatically merged by the core of Chart.js, and is available at this.options
47
- initialize: function(data){
48
-
49
- //Declare segments as a static property to prevent inheriting across the Chart type prototype
50
- this.segments = [];
51
- this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
52
-
53
- this.SegmentArc = Chart.Arc.extend({
54
- ctx : this.chart.ctx,
55
- x : this.chart.width/2,
56
- y : this.chart.height/2
57
- });
58
-
59
- //Set up tooltip events on the chart
60
- if (this.options.showTooltips){
61
- helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
62
- var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
63
-
64
- helpers.each(this.segments,function(segment){
65
- segment.restore(["fillColor"]);
66
- });
67
- helpers.each(activeSegments,function(activeSegment){
68
- activeSegment.fillColor = activeSegment.highlightColor;
69
- });
70
- this.showTooltip(activeSegments);
71
- });
72
- }
73
- this.calculateTotal(data);
74
-
75
- helpers.each(data,function(datapoint, index){
76
- this.addData(datapoint, index, true);
77
- },this);
78
-
79
- this.render();
80
- },
81
- getSegmentsAtEvent : function(e){
82
- var segmentsArray = [];
83
-
84
- var location = helpers.getRelativePosition(e);
85
-
86
- helpers.each(this.segments,function(segment){
87
- if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
88
- },this);
89
- return segmentsArray;
90
- },
91
- addData : function(segment, atIndex, silent){
92
- var index = atIndex || this.segments.length;
93
- this.segments.splice(index, 0, new this.SegmentArc({
94
- value : segment.value,
95
- outerRadius : (this.options.animateScale) ? 0 : this.outerRadius,
96
- innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,
97
- fillColor : segment.color,
98
- highlightColor : segment.highlight || segment.color,
99
- showStroke : this.options.segmentShowStroke,
100
- strokeWidth : this.options.segmentStrokeWidth,
101
- strokeColor : this.options.segmentStrokeColor,
102
- startAngle : Math.PI * 1.5,
103
- circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
104
- label : segment.label
105
- }));
106
- if (!silent){
107
- this.reflow();
108
- this.update();
109
- }
110
- },
111
- calculateCircumference : function(value){
112
- return (Math.PI*2)*(value / this.total);
113
- },
114
- calculateTotal : function(data){
115
- this.total = 0;
116
- helpers.each(data,function(segment){
117
- this.total += segment.value;
118
- },this);
119
- },
120
- update : function(){
121
- this.calculateTotal(this.segments);
122
-
123
- // Reset any highlight colours before updating.
124
- helpers.each(this.activeElements, function(activeElement){
125
- activeElement.restore(['fillColor']);
126
- });
127
-
128
- helpers.each(this.segments,function(segment){
129
- segment.save();
130
- });
131
- this.render();
132
- },
133
-
134
- removeData: function(atIndex){
135
- var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
136
- this.segments.splice(indexToDelete, 1);
137
- this.reflow();
138
- this.update();
139
- },
140
-
141
- reflow : function(){
142
- helpers.extend(this.SegmentArc.prototype,{
143
- x : this.chart.width/2,
144
- y : this.chart.height/2
145
- });
146
- this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
147
- helpers.each(this.segments, function(segment){
148
- segment.update({
149
- outerRadius : this.outerRadius,
150
- innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
151
- });
152
- }, this);
153
- },
154
- draw : function(easeDecimal){
155
- var animDecimal = (easeDecimal) ? easeDecimal : 1;
156
- this.clear();
157
- helpers.each(this.segments,function(segment,index){
158
- segment.transition({
159
- circumference : this.calculateCircumference(segment.value),
160
- outerRadius : this.outerRadius,
161
- innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
162
- },animDecimal);
163
-
164
- segment.endAngle = segment.startAngle + segment.circumference;
165
-
166
- segment.draw();
167
- if (index === 0){
168
- segment.startAngle = Math.PI * 1.5;
169
- }
170
- //Check to see if it's the last segment, if not get the next and update the start angle
171
- if (index < this.segments.length-1){
172
- this.segments[index+1].startAngle = segment.endAngle;
173
- }
174
- },this);
175
-
176
- }
177
- });
178
-
179
- Chart.types.Doughnut.extend({
180
- name : "Pie",
181
- defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0})
182
- });
183
-
184
- }).call(this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/src/Chart.Line.js DELETED
@@ -1,366 +0,0 @@
1
- (function(){
2
- "use strict";
3
-
4
- var root = this,
5
- Chart = root.Chart,
6
- helpers = Chart.helpers;
7
-
8
- var defaultConfig = {
9
-
10
- ///Boolean - Whether grid lines are shown across the chart
11
- scaleShowGridLines : true,
12
-
13
- //String - Colour of the grid lines
14
- scaleGridLineColor : "rgba(0,0,0,.05)",
15
-
16
- //Number - Width of the grid lines
17
- scaleGridLineWidth : 1,
18
-
19
- //Boolean - Whether the line is curved between points
20
- bezierCurve : true,
21
-
22
- //Number - Tension of the bezier curve between points
23
- bezierCurveTension : 0.4,
24
-
25
- //Boolean - Whether to show a dot for each point
26
- pointDot : true,
27
-
28
- //Number - Radius of each point dot in pixels
29
- pointDotRadius : 4,
30
-
31
- //Number - Pixel width of point dot stroke
32
- pointDotStrokeWidth : 1,
33
-
34
- //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
35
- pointHitDetectionRadius : 20,
36
-
37
- //Boolean - Whether to show a stroke for datasets
38
- datasetStroke : true,
39
-
40
- //Number - Pixel width of dataset stroke
41
- datasetStrokeWidth : 2,
42
-
43
- //Boolean - Whether to fill the dataset with a colour
44
- datasetFill : true,
45
-
46
- //String - A legend template
47
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
48
-
49
- };
50
-
51
-
52
- Chart.Type.extend({
53
- name: "Line",
54
- defaults : defaultConfig,
55
- initialize: function(data){
56
- //Declare the extension of the default point, to cater for the options passed in to the constructor
57
- this.PointClass = Chart.Point.extend({
58
- strokeWidth : this.options.pointDotStrokeWidth,
59
- radius : this.options.pointDotRadius,
60
- display: this.options.pointDot,
61
- hitDetectionRadius : this.options.pointHitDetectionRadius,
62
- ctx : this.chart.ctx,
63
- inRange : function(mouseX){
64
- return (Math.pow(mouseX-this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius,2));
65
- }
66
- });
67
-
68
- this.datasets = [];
69
-
70
- //Set up tooltip events on the chart
71
- if (this.options.showTooltips){
72
- helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
73
- var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
74
- this.eachPoints(function(point){
75
- point.restore(['fillColor', 'strokeColor']);
76
- });
77
- helpers.each(activePoints, function(activePoint){
78
- activePoint.fillColor = activePoint.highlightFill;
79
- activePoint.strokeColor = activePoint.highlightStroke;
80
- });
81
- this.showTooltip(activePoints);
82
- });
83
- }
84
-
85
- //Iterate through each of the datasets, and build this into a property of the chart
86
- helpers.each(data.datasets,function(dataset){
87
-
88
- var datasetObject = {
89
- label : dataset.label || null,
90
- fillColor : dataset.fillColor,
91
- strokeColor : dataset.strokeColor,
92
- pointColor : dataset.pointColor,
93
- pointStrokeColor : dataset.pointStrokeColor,
94
- points : []
95
- };
96
-
97
- this.datasets.push(datasetObject);
98
-
99
-
100
- helpers.each(dataset.data,function(dataPoint,index){
101
- //Add a new point for each piece of data, passing any required data to draw.
102
- datasetObject.points.push(new this.PointClass({
103
- value : dataPoint,
104
- label : data.labels[index],
105
- datasetLabel: dataset.label,
106
- strokeColor : dataset.pointStrokeColor,
107
- fillColor : dataset.pointColor,
108
- highlightFill : dataset.pointHighlightFill || dataset.pointColor,
109
- highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
110
- }));
111
- },this);
112
-
113
- this.buildScale(data.labels);
114
-
115
-
116
- this.eachPoints(function(point, index){
117
- helpers.extend(point, {
118
- x: this.scale.calculateX(index),
119
- y: this.scale.endPoint
120
- });
121
- point.save();
122
- }, this);
123
-
124
- },this);
125
-
126
-
127
- this.render();
128
- },
129
- update : function(){
130
- this.scale.update();
131
- // Reset any highlight colours before updating.
132
- helpers.each(this.activeElements, function(activeElement){
133
- activeElement.restore(['fillColor', 'strokeColor']);
134
- });
135
- this.eachPoints(function(point){
136
- point.save();
137
- });
138
- this.render();
139
- },
140
- eachPoints : function(callback){
141
- helpers.each(this.datasets,function(dataset){
142
- helpers.each(dataset.points,callback,this);
143
- },this);
144
- },
145
- getPointsAtEvent : function(e){
146
- var pointsArray = [],
147
- eventPosition = helpers.getRelativePosition(e);
148
- helpers.each(this.datasets,function(dataset){
149
- helpers.each(dataset.points,function(point){
150
- if (point.inRange(eventPosition.x,eventPosition.y)) pointsArray.push(point);
151
- });
152
- },this);
153
- return pointsArray;
154
- },
155
- buildScale : function(labels){
156
- var self = this;
157
-
158
- var dataTotal = function(){
159
- var values = [];
160
- self.eachPoints(function(point){
161
- values.push(point.value);
162
- });
163
-
164
- return values;
165
- };
166
-
167
- var scaleOptions = {
168
- templateString : this.options.scaleLabel,
169
- height : this.chart.height,
170
- width : this.chart.width,
171
- ctx : this.chart.ctx,
172
- textColor : this.options.scaleFontColor,
173
- fontSize : this.options.scaleFontSize,
174
- fontStyle : this.options.scaleFontStyle,
175
- fontFamily : this.options.scaleFontFamily,
176
- valuesCount : labels.length,
177
- beginAtZero : this.options.scaleBeginAtZero,
178
- integersOnly : this.options.scaleIntegersOnly,
179
- calculateYRange : function(currentHeight){
180
- var updatedRanges = helpers.calculateScaleRange(
181
- dataTotal(),
182
- currentHeight,
183
- this.fontSize,
184
- this.beginAtZero,
185
- this.integersOnly
186
- );
187
- helpers.extend(this, updatedRanges);
188
- },
189
- xLabels : labels,
190
- font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
191
- lineWidth : this.options.scaleLineWidth,
192
- lineColor : this.options.scaleLineColor,
193
- gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
194
- gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
195
- padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
196
- showLabels : this.options.scaleShowLabels,
197
- display : this.options.showScale
198
- };
199
-
200
- if (this.options.scaleOverride){
201
- helpers.extend(scaleOptions, {
202
- calculateYRange: helpers.noop,
203
- steps: this.options.scaleSteps,
204
- stepValue: this.options.scaleStepWidth,
205
- min: this.options.scaleStartValue,
206
- max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
207
- });
208
- }
209
-
210
-
211
- this.scale = new Chart.Scale(scaleOptions);
212
- },
213
- addData : function(valuesArray,label){
214
- //Map the values array for each of the datasets
215
-
216
- helpers.each(valuesArray,function(value,datasetIndex){
217
- //Add a new point for each piece of data, passing any required data to draw.
218
- this.datasets[datasetIndex].points.push(new this.PointClass({
219
- value : value,
220
- label : label,
221
- x: this.scale.calculateX(this.scale.valuesCount+1),
222
- y: this.scale.endPoint,
223
- strokeColor : this.datasets[datasetIndex].pointStrokeColor,
224
- fillColor : this.datasets[datasetIndex].pointColor
225
- }));
226
- },this);
227
-
228
- this.scale.addXLabel(label);
229
- //Then re-render the chart.
230
- this.update();
231
- },
232
- removeData : function(){
233
- this.scale.removeXLabel();
234
- //Then re-render the chart.
235
- helpers.each(this.datasets,function(dataset){
236
- dataset.points.shift();
237
- },this);
238
- this.update();
239
- },
240
- reflow : function(){
241
- var newScaleProps = helpers.extend({
242
- height : this.chart.height,
243
- width : this.chart.width
244
- });
245
- this.scale.update(newScaleProps);
246
- },
247
- draw : function(ease){
248
- var easingDecimal = ease || 1;
249
- this.clear();
250
-
251
- var ctx = this.chart.ctx;
252
-
253
- // Some helper methods for getting the next/prev points
254
- var hasValue = function(item){
255
- return item.value !== null;
256
- },
257
- nextPoint = function(point, collection, index){
258
- return helpers.findNextWhere(collection, hasValue, index) || point;
259
- },
260
- previousPoint = function(point, collection, index){
261
- return helpers.findPreviousWhere(collection, hasValue, index) || point;
262
- };
263
-
264
- this.scale.draw(easingDecimal);
265
-
266
-
267
- helpers.each(this.datasets,function(dataset){
268
- var pointsWithValues = helpers.where(dataset.points, hasValue);
269
-
270
- //Transition each point first so that the line and point drawing isn't out of sync
271
- //We can use this extra loop to calculate the control points of this dataset also in this loop
272
-
273
- helpers.each(dataset.points, function(point, index){
274
- if (point.hasValue()){
275
- point.transition({
276
- y : this.scale.calculateY(point.value),
277
- x : this.scale.calculateX(index)
278
- }, easingDecimal);
279
- }
280
- },this);
281
-
282
-
283
- // Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point
284
- // This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed
285
- if (this.options.bezierCurve){
286
- helpers.each(pointsWithValues, function(point, index){
287
- var tension = (index > 0 && index < pointsWithValues.length - 1) ? this.options.bezierCurveTension : 0;
288
- point.controlPoints = helpers.splineCurve(
289
- previousPoint(point, pointsWithValues, index),
290
- point,
291
- nextPoint(point, pointsWithValues, index),
292
- tension
293
- );
294
-
295
- // Prevent the bezier going outside of the bounds of the graph
296
-
297
- // Cap puter bezier handles to the upper/lower scale bounds
298
- if (point.controlPoints.outer.y > this.scale.endPoint){
299
- point.controlPoints.outer.y = this.scale.endPoint;
300
- }
301
- else if (point.controlPoints.outer.y < this.scale.startPoint){
302
- point.controlPoints.outer.y = this.scale.startPoint;
303
- }
304
-
305
- // Cap inner bezier handles to the upper/lower scale bounds
306
- if (point.controlPoints.inner.y > this.scale.endPoint){
307
- point.controlPoints.inner.y = this.scale.endPoint;
308
- }
309
- else if (point.controlPoints.inner.y < this.scale.startPoint){
310
- point.controlPoints.inner.y = this.scale.startPoint;
311
- }
312
- },this);
313
- }
314
-
315
-
316
- //Draw the line between all the points
317
- ctx.lineWidth = this.options.datasetStrokeWidth;
318
- ctx.strokeStyle = dataset.strokeColor;
319
- ctx.beginPath();
320
-
321
- helpers.each(pointsWithValues, function(point, index){
322
- if (index === 0){
323
- ctx.moveTo(point.x, point.y);
324
- }
325
- else{
326
- if(this.options.bezierCurve){
327
- var previous = previousPoint(point, pointsWithValues, index);
328
-
329
- ctx.bezierCurveTo(
330
- previous.controlPoints.outer.x,
331
- previous.controlPoints.outer.y,
332
- point.controlPoints.inner.x,
333
- point.controlPoints.inner.y,
334
- point.x,
335
- point.y
336
- );
337
- }
338
- else{
339
- ctx.lineTo(point.x,point.y);
340
- }
341
- }
342
- }, this);
343
-
344
- ctx.stroke();
345
-
346
- if (this.options.datasetFill && pointsWithValues.length > 0){
347
- //Round off the line by going to the base of the chart, back to the start, then fill.
348
- ctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint);
349
- ctx.lineTo(pointsWithValues[0].x, this.scale.endPoint);
350
- ctx.fillStyle = dataset.fillColor;
351
- ctx.closePath();
352
- ctx.fill();
353
- }
354
-
355
- //Now draw the points over the line
356
- //A little inefficient double looping, but better than the line
357
- //lagging behind the point positions
358
- helpers.each(pointsWithValues,function(point){
359
- point.draw();
360
- });
361
- },this);
362
- }
363
- });
364
-
365
-
366
- }).call(this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/src/Chart.PolarArea.js DELETED
@@ -1,248 +0,0 @@
1
- (function(){
2
- "use strict";
3
-
4
- var root = this,
5
- Chart = root.Chart,
6
- //Cache a local reference to Chart.helpers
7
- helpers = Chart.helpers;
8
-
9
- var defaultConfig = {
10
- //Boolean - Show a backdrop to the scale label
11
- scaleShowLabelBackdrop : true,
12
-
13
- //String - The colour of the label backdrop
14
- scaleBackdropColor : "rgba(255,255,255,0.75)",
15
-
16
- // Boolean - Whether the scale should begin at zero
17
- scaleBeginAtZero : true,
18
-
19
- //Number - The backdrop padding above & below the label in pixels
20
- scaleBackdropPaddingY : 2,
21
-
22
- //Number - The backdrop padding to the side of the label in pixels
23
- scaleBackdropPaddingX : 2,
24
-
25
- //Boolean - Show line for each value in the scale
26
- scaleShowLine : true,
27
-
28
- //Boolean - Stroke a line around each segment in the chart
29
- segmentShowStroke : true,
30
-
31
- //String - The colour of the stroke on each segement.
32
- segmentStrokeColor : "#fff",
33
-
34
- //Number - The width of the stroke value in pixels
35
- segmentStrokeWidth : 2,
36
-
37
- //Number - Amount of animation steps
38
- animationSteps : 100,
39
-
40
- //String - Animation easing effect.
41
- animationEasing : "easeOutBounce",
42
-
43
- //Boolean - Whether to animate the rotation of the chart
44
- animateRotate : true,
45
-
46
- //Boolean - Whether to animate scaling the chart from the centre
47
- animateScale : false,
48
-
49
- //String - A legend template
50
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
51
- };
52
-
53
-
54
- Chart.Type.extend({
55
- //Passing in a name registers this chart in the Chart namespace
56
- name: "PolarArea",
57
- //Providing a defaults will also register the deafults in the chart namespace
58
- defaults : defaultConfig,
59
- //Initialize is fired when the chart is initialized - Data is passed in as a parameter
60
- //Config is automatically merged by the core of Chart.js, and is available at this.options
61
- initialize: function(data){
62
- this.segments = [];
63
- //Declare segment class as a chart instance specific class, so it can share props for this instance
64
- this.SegmentArc = Chart.Arc.extend({
65
- showStroke : this.options.segmentShowStroke,
66
- strokeWidth : this.options.segmentStrokeWidth,
67
- strokeColor : this.options.segmentStrokeColor,
68
- ctx : this.chart.ctx,
69
- innerRadius : 0,
70
- x : this.chart.width/2,
71
- y : this.chart.height/2
72
- });
73
- this.scale = new Chart.RadialScale({
74
- display: this.options.showScale,
75
- fontStyle: this.options.scaleFontStyle,
76
- fontSize: this.options.scaleFontSize,
77
- fontFamily: this.options.scaleFontFamily,
78
- fontColor: this.options.scaleFontColor,
79
- showLabels: this.options.scaleShowLabels,
80
- showLabelBackdrop: this.options.scaleShowLabelBackdrop,
81
- backdropColor: this.options.scaleBackdropColor,
82
- backdropPaddingY : this.options.scaleBackdropPaddingY,
83
- backdropPaddingX: this.options.scaleBackdropPaddingX,
84
- lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
85
- lineColor: this.options.scaleLineColor,
86
- lineArc: true,
87
- width: this.chart.width,
88
- height: this.chart.height,
89
- xCenter: this.chart.width/2,
90
- yCenter: this.chart.height/2,
91
- ctx : this.chart.ctx,
92
- templateString: this.options.scaleLabel,
93
- valuesCount: data.length
94
- });
95
-
96
- this.updateScaleRange(data);
97
-
98
- this.scale.update();
99
-
100
- helpers.each(data,function(segment,index){
101
- this.addData(segment,index,true);
102
- },this);
103
-
104
- //Set up tooltip events on the chart
105
- if (this.options.showTooltips){
106
- helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
107
- var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
108
- helpers.each(this.segments,function(segment){
109
- segment.restore(["fillColor"]);
110
- });
111
- helpers.each(activeSegments,function(activeSegment){
112
- activeSegment.fillColor = activeSegment.highlightColor;
113
- });
114
- this.showTooltip(activeSegments);
115
- });
116
- }
117
-
118
- this.render();
119
- },
120
- getSegmentsAtEvent : function(e){
121
- var segmentsArray = [];
122
-
123
- var location = helpers.getRelativePosition(e);
124
-
125
- helpers.each(this.segments,function(segment){
126
- if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
127
- },this);
128
- return segmentsArray;
129
- },
130
- addData : function(segment, atIndex, silent){
131
- var index = atIndex || this.segments.length;
132
-
133
- this.segments.splice(index, 0, new this.SegmentArc({
134
- fillColor: segment.color,
135
- highlightColor: segment.highlight || segment.color,
136
- label: segment.label,
137
- value: segment.value,
138
- outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),
139
- circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),
140
- startAngle: Math.PI * 1.5
141
- }));
142
- if (!silent){
143
- this.reflow();
144
- this.update();
145
- }
146
- },
147
- removeData: function(atIndex){
148
- var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
149
- this.segments.splice(indexToDelete, 1);
150
- this.reflow();
151
- this.update();
152
- },
153
- calculateTotal: function(data){
154
- this.total = 0;
155
- helpers.each(data,function(segment){
156
- this.total += segment.value;
157
- },this);
158
- this.scale.valuesCount = this.segments.length;
159
- },
160
- updateScaleRange: function(datapoints){
161
- var valuesArray = [];
162
- helpers.each(datapoints,function(segment){
163
- valuesArray.push(segment.value);
164
- });
165
-
166
- var scaleSizes = (this.options.scaleOverride) ?
167
- {
168
- steps: this.options.scaleSteps,
169
- stepValue: this.options.scaleStepWidth,
170
- min: this.options.scaleStartValue,
171
- max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
172
- } :
173
- helpers.calculateScaleRange(
174
- valuesArray,
175
- helpers.min([this.chart.width, this.chart.height])/2,
176
- this.options.scaleFontSize,
177
- this.options.scaleBeginAtZero,
178
- this.options.scaleIntegersOnly
179
- );
180
-
181
- helpers.extend(
182
- this.scale,
183
- scaleSizes,
184
- {
185
- size: helpers.min([this.chart.width, this.chart.height]),
186
- xCenter: this.chart.width/2,
187
- yCenter: this.chart.height/2
188
- }
189
- );
190
-
191
- },
192
- update : function(){
193
- this.calculateTotal(this.segments);
194
-
195
- helpers.each(this.segments,function(segment){
196
- segment.save();
197
- });
198
- this.render();
199
- },
200
- reflow : function(){
201
- helpers.extend(this.SegmentArc.prototype,{
202
- x : this.chart.width/2,
203
- y : this.chart.height/2
204
- });
205
- this.updateScaleRange(this.segments);
206
- this.scale.update();
207
-
208
- helpers.extend(this.scale,{
209
- xCenter: this.chart.width/2,
210
- yCenter: this.chart.height/2
211
- });
212
-
213
- helpers.each(this.segments, function(segment){
214
- segment.update({
215
- outerRadius : this.scale.calculateCenterOffset(segment.value)
216
- });
217
- }, this);
218
-
219
- },
220
- draw : function(ease){
221
- var easingDecimal = ease || 1;
222
- //Clear & draw the canvas
223
- this.clear();
224
- helpers.each(this.segments,function(segment, index){
225
- segment.transition({
226
- circumference : this.scale.getCircumference(),
227
- outerRadius : this.scale.calculateCenterOffset(segment.value)
228
- },easingDecimal);
229
-
230
- segment.endAngle = segment.startAngle + segment.circumference;
231
-
232
- // If we've removed the first segment we need to set the first one to
233
- // start at the top.
234
- if (index === 0){
235
- segment.startAngle = Math.PI * 1.5;
236
- }
237
-
238
- //Check to see if it's the last segment, if not get the next and update the start angle
239
- if (index < this.segments.length - 1){
240
- this.segments[index+1].startAngle = segment.endAngle;
241
- }
242
- segment.draw();
243
- }, this);
244
- this.scale.draw();
245
- }
246
- });
247
-
248
- }).call(this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/src/Chart.Radar.js DELETED
@@ -1,343 +0,0 @@
1
- (function(){
2
- "use strict";
3
-
4
- var root = this,
5
- Chart = root.Chart,
6
- helpers = Chart.helpers;
7
-
8
-
9
-
10
- Chart.Type.extend({
11
- name: "Radar",
12
- defaults:{
13
- //Boolean - Whether to show lines for each scale point
14
- scaleShowLine : true,
15
-
16
- //Boolean - Whether we show the angle lines out of the radar
17
- angleShowLineOut : true,
18
-
19
- //Boolean - Whether to show labels on the scale
20
- scaleShowLabels : false,
21
-
22
- // Boolean - Whether the scale should begin at zero
23
- scaleBeginAtZero : true,
24
-
25
- //String - Colour of the angle line
26
- angleLineColor : "rgba(0,0,0,.1)",
27
-
28
- //Number - Pixel width of the angle line
29
- angleLineWidth : 1,
30
-
31
- //String - Point label font declaration
32
- pointLabelFontFamily : "'Arial'",
33
-
34
- //String - Point label font weight
35
- pointLabelFontStyle : "normal",
36
-
37
- //Number - Point label font size in pixels
38
- pointLabelFontSize : 10,
39
-
40
- //String - Point label font colour
41
- pointLabelFontColor : "#666",
42
-
43
- //Boolean - Whether to show a dot for each point
44
- pointDot : true,
45
-
46
- //Number - Radius of each point dot in pixels
47
- pointDotRadius : 3,
48
-
49
- //Number - Pixel width of point dot stroke
50
- pointDotStrokeWidth : 1,
51
-
52
- //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
53
- pointHitDetectionRadius : 20,
54
-
55
- //Boolean - Whether to show a stroke for datasets
56
- datasetStroke : true,
57
-
58
- //Number - Pixel width of dataset stroke
59
- datasetStrokeWidth : 2,
60
-
61
- //Boolean - Whether to fill the dataset with a colour
62
- datasetFill : true,
63
-
64
- //String - A legend template
65
- legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
66
-
67
- },
68
-
69
- initialize: function(data){
70
- this.PointClass = Chart.Point.extend({
71
- strokeWidth : this.options.pointDotStrokeWidth,
72
- radius : this.options.pointDotRadius,
73
- display: this.options.pointDot,
74
- hitDetectionRadius : this.options.pointHitDetectionRadius,
75
- ctx : this.chart.ctx
76
- });
77
-
78
- this.datasets = [];
79
-
80
- this.buildScale(data);
81
-
82
- //Set up tooltip events on the chart
83
- if (this.options.showTooltips){
84
- helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
85
- var activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
86
-
87
- this.eachPoints(function(point){
88
- point.restore(['fillColor', 'strokeColor']);
89
- });
90
- helpers.each(activePointsCollection, function(activePoint){
91
- activePoint.fillColor = activePoint.highlightFill;
92
- activePoint.strokeColor = activePoint.highlightStroke;
93
- });
94
-
95
- this.showTooltip(activePointsCollection);
96
- });
97
- }
98
-
99
- //Iterate through each of the datasets, and build this into a property of the chart
100
- helpers.each(data.datasets,function(dataset){
101
-
102
- var datasetObject = {
103
- label: dataset.label || null,
104
- fillColor : dataset.fillColor,
105
- strokeColor : dataset.strokeColor,
106
- pointColor : dataset.pointColor,
107
- pointStrokeColor : dataset.pointStrokeColor,
108
- points : []
109
- };
110
-
111
- this.datasets.push(datasetObject);
112
-
113
- helpers.each(dataset.data,function(dataPoint,index){
114
- //Add a new point for each piece of data, passing any required data to draw.
115
- var pointPosition;
116
- if (!this.scale.animation){
117
- pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));
118
- }
119
- datasetObject.points.push(new this.PointClass({
120
- value : dataPoint,
121
- label : data.labels[index],
122
- datasetLabel: dataset.label,
123
- x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
124
- y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
125
- strokeColor : dataset.pointStrokeColor,
126
- fillColor : dataset.pointColor,
127
- highlightFill : dataset.pointHighlightFill || dataset.pointColor,
128
- highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
129
- }));
130
- },this);
131
-
132
- },this);
133
-
134
- this.render();
135
- },
136
- eachPoints : function(callback){
137
- helpers.each(this.datasets,function(dataset){
138
- helpers.each(dataset.points,callback,this);
139
- },this);
140
- },
141
-
142
- getPointsAtEvent : function(evt){
143
- var mousePosition = helpers.getRelativePosition(evt),
144
- fromCenter = helpers.getAngleFromPoint({
145
- x: this.scale.xCenter,
146
- y: this.scale.yCenter
147
- }, mousePosition);
148
-
149
- var anglePerIndex = (Math.PI * 2) /this.scale.valuesCount,
150
- pointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex),
151
- activePointsCollection = [];
152
-
153
- // If we're at the top, make the pointIndex 0 to get the first of the array.
154
- if (pointIndex >= this.scale.valuesCount || pointIndex < 0){
155
- pointIndex = 0;
156
- }
157
-
158
- if (fromCenter.distance <= this.scale.drawingArea){
159
- helpers.each(this.datasets, function(dataset){
160
- activePointsCollection.push(dataset.points[pointIndex]);
161
- });
162
- }
163
-
164
- return activePointsCollection;
165
- },
166
-
167
- buildScale : function(data){
168
- this.scale = new Chart.RadialScale({
169
- display: this.options.showScale,
170
- fontStyle: this.options.scaleFontStyle,
171
- fontSize: this.options.scaleFontSize,
172
- fontFamily: this.options.scaleFontFamily,
173
- fontColor: this.options.scaleFontColor,
174
- showLabels: this.options.scaleShowLabels,
175
- showLabelBackdrop: this.options.scaleShowLabelBackdrop,
176
- backdropColor: this.options.scaleBackdropColor,
177
- backdropPaddingY : this.options.scaleBackdropPaddingY,
178
- backdropPaddingX: this.options.scaleBackdropPaddingX,
179
- lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
180
- lineColor: this.options.scaleLineColor,
181
- angleLineColor : this.options.angleLineColor,
182
- angleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0,
183
- // Point labels at the edge of each line
184
- pointLabelFontColor : this.options.pointLabelFontColor,
185
- pointLabelFontSize : this.options.pointLabelFontSize,
186
- pointLabelFontFamily : this.options.pointLabelFontFamily,
187
- pointLabelFontStyle : this.options.pointLabelFontStyle,
188
- height : this.chart.height,
189
- width: this.chart.width,
190
- xCenter: this.chart.width/2,
191
- yCenter: this.chart.height/2,
192
- ctx : this.chart.ctx,
193
- templateString: this.options.scaleLabel,
194
- labels: data.labels,
195
- valuesCount: data.datasets[0].data.length
196
- });
197
-
198
- this.scale.setScaleSize();
199
- this.updateScaleRange(data.datasets);
200
- this.scale.buildYLabels();
201
- },
202
- updateScaleRange: function(datasets){
203
- var valuesArray = (function(){
204
- var totalDataArray = [];
205
- helpers.each(datasets,function(dataset){
206
- if (dataset.data){
207
- totalDataArray = totalDataArray.concat(dataset.data);
208
- }
209
- else {
210
- helpers.each(dataset.points, function(point){
211
- totalDataArray.push(point.value);
212
- });
213
- }
214
- });
215
- return totalDataArray;
216
- })();
217
-
218
-
219
- var scaleSizes = (this.options.scaleOverride) ?
220
- {
221
- steps: this.options.scaleSteps,
222
- stepValue: this.options.scaleStepWidth,
223
- min: this.options.scaleStartValue,
224
- max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
225
- } :
226
- helpers.calculateScaleRange(
227
- valuesArray,
228
- helpers.min([this.chart.width, this.chart.height])/2,
229
- this.options.scaleFontSize,
230
- this.options.scaleBeginAtZero,
231
- this.options.scaleIntegersOnly
232
- );
233
-
234
- helpers.extend(
235
- this.scale,
236
- scaleSizes
237
- );
238
-
239
- },
240
- addData : function(valuesArray,label){
241
- //Map the values array for each of the datasets
242
- this.scale.valuesCount++;
243
- helpers.each(valuesArray,function(value,datasetIndex){
244
- var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));
245
- this.datasets[datasetIndex].points.push(new this.PointClass({
246
- value : value,
247
- label : label,
248
- x: pointPosition.x,
249
- y: pointPosition.y,
250
- strokeColor : this.datasets[datasetIndex].pointStrokeColor,
251
- fillColor : this.datasets[datasetIndex].pointColor
252
- }));
253
- },this);
254
-
255
- this.scale.labels.push(label);
256
-
257
- this.reflow();
258
-
259
- this.update();
260
- },
261
- removeData : function(){
262
- this.scale.valuesCount--;
263
- this.scale.labels.shift();
264
- helpers.each(this.datasets,function(dataset){
265
- dataset.points.shift();
266
- },this);
267
- this.reflow();
268
- this.update();
269
- },
270
- update : function(){
271
- this.eachPoints(function(point){
272
- point.save();
273
- });
274
- this.reflow();
275
- this.render();
276
- },
277
- reflow: function(){
278
- helpers.extend(this.scale, {
279
- width : this.chart.width,
280
- height: this.chart.height,
281
- size : helpers.min([this.chart.width, this.chart.height]),
282
- xCenter: this.chart.width/2,
283
- yCenter: this.chart.height/2
284
- });
285
- this.updateScaleRange(this.datasets);
286
- this.scale.setScaleSize();
287
- this.scale.buildYLabels();
288
- },
289
- draw : function(ease){
290
- var easeDecimal = ease || 1,
291
- ctx = this.chart.ctx;
292
- this.clear();
293
- this.scale.draw();
294
-
295
- helpers.each(this.datasets,function(dataset){
296
-
297
- //Transition each point first so that the line and point drawing isn't out of sync
298
- helpers.each(dataset.points,function(point,index){
299
- if (point.hasValue()){
300
- point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);
301
- }
302
- },this);
303
-
304
-
305
-
306
- //Draw the line between all the points
307
- ctx.lineWidth = this.options.datasetStrokeWidth;
308
- ctx.strokeStyle = dataset.strokeColor;
309
- ctx.beginPath();
310
- helpers.each(dataset.points,function(point,index){
311
- if (index === 0){
312
- ctx.moveTo(point.x,point.y);
313
- }
314
- else{
315
- ctx.lineTo(point.x,point.y);
316
- }
317
- },this);
318
- ctx.closePath();
319
- ctx.stroke();
320
-
321
- ctx.fillStyle = dataset.fillColor;
322
- ctx.fill();
323
-
324
- //Now draw the points over the line
325
- //A little inefficient double looping, but better than the line
326
- //lagging behind the point positions
327
- helpers.each(dataset.points,function(point){
328
- if (point.hasValue()){
329
- point.draw();
330
- }
331
- });
332
-
333
- },this);
334
-
335
- }
336
-
337
- });
338
-
339
-
340
-
341
-
342
-
343
- }).call(this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Chart_js/utils.js ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use strict';
2
+
3
+ window.chartColors = {
4
+ red: 'rgb(255, 99, 132)',
5
+ orange: 'rgb(255, 159, 64)',
6
+ yellow: 'rgb(255, 205, 86)',
7
+ green: 'rgb(75, 192, 192)',
8
+ blue: 'rgb(54, 162, 235)',
9
+ purple: 'rgb(153, 102, 255)',
10
+ grey: 'rgb(201, 203, 207)'
11
+ };
12
+
13
+ (function(global) {
14
+ var MONTHS = [
15
+ 'January',
16
+ 'February',
17
+ 'March',
18
+ 'April',
19
+ 'May',
20
+ 'June',
21
+ 'July',
22
+ 'August',
23
+ 'September',
24
+ 'October',
25
+ 'November',
26
+ 'December'
27
+ ];
28
+
29
+ var COLORS = [
30
+ '#4dc9f6',
31
+ '#f67019',
32
+ '#f53794',
33
+ '#537bc4',
34
+ '#acc236',
35
+ '#166a8f',
36
+ '#00a950',
37
+ '#58595b',
38
+ '#8549ba'
39
+ ];
40
+
41
+ var Samples = global.Samples || (global.Samples = {});
42
+ var Color = global.Color;
43
+
44
+ Samples.utils = {
45
+ // Adapted from http://indiegamr.com/generate-repeatable-random-numbers-in-js/
46
+ srand: function(seed) {
47
+ this._seed = seed;
48
+ },
49
+
50
+ rand: function(min, max) {
51
+ var seed = this._seed;
52
+ min = min === undefined ? 0 : min;
53
+ max = max === undefined ? 1 : max;
54
+ this._seed = (seed * 9301 + 49297) % 233280;
55
+ return min + (this._seed / 233280) * (max - min);
56
+ },
57
+
58
+ numbers: function(config) {
59
+ var cfg = config || {};
60
+ var min = cfg.min || 0;
61
+ var max = cfg.max || 1;
62
+ var from = cfg.from || [];
63
+ var count = cfg.count || 8;
64
+ var decimals = cfg.decimals || 8;
65
+ var continuity = cfg.continuity || 1;
66
+ var dfactor = Math.pow(10, decimals) || 0;
67
+ var data = [];
68
+ var i, value;
69
+
70
+ for (i = 0; i < count; ++i) {
71
+ value = (from[i] || 0) + this.rand(min, max);
72
+ if (this.rand() <= continuity) {
73
+ data.push(Math.round(dfactor * value) / dfactor);
74
+ } else {
75
+ data.push(null);
76
+ }
77
+ }
78
+
79
+ return data;
80
+ },
81
+
82
+ labels: function(config) {
83
+ var cfg = config || {};
84
+ var min = cfg.min || 0;
85
+ var max = cfg.max || 100;
86
+ var count = cfg.count || 8;
87
+ var step = (max - min) / count;
88
+ var decimals = cfg.decimals || 8;
89
+ var dfactor = Math.pow(10, decimals) || 0;
90
+ var prefix = cfg.prefix || '';
91
+ var values = [];
92
+ var i;
93
+
94
+ for (i = min; i < max; i += step) {
95
+ values.push(prefix + Math.round(dfactor * i) / dfactor);
96
+ }
97
+
98
+ return values;
99
+ },
100
+
101
+ months: function(config) {
102
+ var cfg = config || {};
103
+ var count = cfg.count || 12;
104
+ var section = cfg.section;
105
+ var values = [];
106
+ var i, value;
107
+
108
+ for (i = 0; i < count; ++i) {
109
+ value = MONTHS[Math.ceil(i) % 12];
110
+ values.push(value.substring(0, section));
111
+ }
112
+
113
+ return values;
114
+ },
115
+
116
+ color: function(index) {
117
+ return COLORS[index % COLORS.length];
118
+ },
119
+
120
+ transparentize: function(color, opacity) {
121
+ var alpha = opacity === undefined ? 0.5 : 1 - opacity;
122
+ return Color(color).alpha(alpha).rgbString();
123
+ }
124
+ };
125
+
126
+ // DEPRECATED
127
+ window.randomScalingFactor = function() {
128
+ return Math.round(Samples.utils.rand(-100, 100));
129
+ };
130
+
131
+ // INITIALIZATION
132
+
133
+ Samples.utils.srand(Date.now());
134
+
135
+ // Google Analytics
136
+ /* eslint-disable */
137
+ if (document.location.hostname.match(/^(www\.)?chartjs\.org$/)) {
138
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
139
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
140
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
141
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
142
+ ga('create', 'UA-28909194-3', 'auto');
143
+ ga('send', 'pageview');
144
+ }
145
+ /* eslint-enable */
146
+
147
+ }(this));
lib/bootstrap/css/bootstrap-rtl.min.css ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
1
+ @charset "UTF-8";/*!
2
+ * Bootstrap v4.4.1 (https://getbootstrap.com/)
3
+ * Copyright 2011-2019 The Bootstrap Authors
4
+ * Copyright 2011-2019 Twitter, Inc.
5
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6
+ * RTL-ized by Arash Laylazi (https://github.com/PerseusTheGreat)
7
+ * RTL rev. 1 (https://github.com/PerseusTheGreat/bootstrap-rtl)
8
+ */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent;direction:rtl}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:right;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-right:0;margin-bottom:.5rem}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:right;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}[type=email],[type=file],[type=number],[type=password],[type=tel],[type=url],code,samp,var{text-align:left;direction:ltr}kbd{display:inline-block}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-right:0;list-style:none}.list-inline{padding-right:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-left:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-right:8.333333%}.offset-2{margin-right:16.666667%}.offset-3{margin-right:25%}.offset-4{margin-right:33.333333%}.offset-5{margin-right:41.666667%}.offset-6{margin-right:50%}.offset-7{margin-right:58.333333%}.offset-8{margin-right:66.666667%}.offset-9{margin-right:75%}.offset-10{margin-right:83.333333%}.offset-11{margin-right:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-right:0}.offset-sm-1{margin-right:8.333333%}.offset-sm-2{margin-right:16.666667%}.offset-sm-3{margin-right:25%}.offset-sm-4{margin-right:33.333333%}.offset-sm-5{margin-right:41.666667%}.offset-sm-6{margin-right:50%}.offset-sm-7{margin-right:58.333333%}.offset-sm-8{margin-right:66.666667%}.offset-sm-9{margin-right:75%}.offset-sm-10{margin-right:83.333333%}.offset-sm-11{margin-right:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-right:0}.offset-md-1{margin-right:8.333333%}.offset-md-2{margin-right:16.666667%}.offset-md-3{margin-right:25%}.offset-md-4{margin-right:33.333333%}.offset-md-5{margin-right:41.666667%}.offset-md-6{margin-right:50%}.offset-md-7{margin-right:58.333333%}.offset-md-8{margin-right:66.666667%}.offset-md-9{margin-right:75%}.offset-md-10{margin-right:83.333333%}.offset-md-11{margin-right:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-right:0}.offset-lg-1{margin-right:8.333333%}.offset-lg-2{margin-right:16.666667%}.offset-lg-3{margin-right:25%}.offset-lg-4{margin-right:33.333333%}.offset-lg-5{margin-right:41.666667%}.offset-lg-6{margin-right:50%}.offset-lg-7{margin-right:58.333333%}.offset-lg-8{margin-right:66.666667%}.offset-lg-9{margin-right:75%}.offset-lg-10{margin-right:83.333333%}.offset-lg-11{margin-right:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-right:0}.offset-xl-1{margin-right:8.333333%}.offset-xl-2{margin-right:16.666667%}.offset-xl-3{margin-right:25%}.offset-xl-4{margin-right:33.333333%}.offset-xl-5{margin-right:41.666667%}.offset-xl-6{margin-right:50%}.offset-xl-7{margin-right:58.333333%}.offset-xl-8{margin-right:66.666667%}.offset-xl-9{margin-right:75%}.offset-xl-10{margin-right:83.333333%}.offset-xl-11{margin-right:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-right:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-right:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-right:0;margin-left:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:0;margin-left:.3125rem}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-left:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:left calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-left:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) left calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-left:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat left .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center left 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-left:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:left calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-left:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) left calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-left:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat left .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center left 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-right:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:0;margin-left:.25rem}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#0069d9;border-color:#0062cc;box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline;box-shadow:none}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-right:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:right;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-right:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-right:.255em;vertical-align:.255em;content:""}.dropright .dropdown-toggle::after{display:none}.dropright .dropdown-toggle::before{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-right:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-right:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-right:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-right-radius:0;border-bottom-right-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-right:0}.dropleft .dropdown-toggle-split::before{margin-left:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 0%;flex:1 1 0%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-right:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-right:-1px}.input-group-prepend{margin-left:-1px}.input-group-append{margin-right:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-left:1.75rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-right:1.5rem}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-left:1rem}.custom-control-input{position:absolute;right:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before,.custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;right:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:.25rem;right:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50%/50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-right:2.25rem}.custom-switch .custom-control-label::before{right:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);right:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(-.75rem);transform:translateX(-.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem .375rem 1.75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat left .75rem center/8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-left:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-right:.5rem;padding-bottom:.25rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-right:1rem;padding-bottom:.5rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input:lang(fa)~.custom-file-label::after{content:"از فهرست"}.custom-file-input:lang(ar)~.custom-file-label::after{content:"تصفح"}.custom-file-input:lang(iw)~.custom-file-label::after{content:"דפדוף"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;bottom:0;left:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-right:inherit;border-radius:.25rem 0 0 .25rem}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-left:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-right:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-left:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-right:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-right:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img,.card-img-bottom,.card-img-top{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-right:0;border-right:0}.card-group>.card:not(:last-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-left-radius:0}.card-group>.card:not(:first-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-right-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-right:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-left:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-right:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-right:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item:last-child .page-link{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-left:4rem}.alert-dismissible .close{position:absolute;top:0;left:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-right:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal .list-group-item:first-child{border-bottom-right-radius:.25rem;border-top-left-radius:0}.list-group-horizontal .list-group-item:last-child{border-top-left-radius:.25rem;border-bottom-right-radius:0}.list-group-horizontal .list-group-item.active{margin-top:0}.list-group-horizontal .list-group-item+.list-group-item{border-top-width:1px;border-right-width:0}.list-group-horizontal .list-group-item+.list-group-item.active{margin-right:-1px;border-right-width:1px}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm .list-group-item:first-child{border-bottom-right-radius:.25rem;border-top-left-radius:0}.list-group-horizontal-sm .list-group-item:last-child{border-top-left-radius:.25rem;border-bottom-right-radius:0}.list-group-horizontal-sm .list-group-item.active{margin-top:0}.list-group-horizontal-sm .list-group-item+.list-group-item{border-top-width:1px;border-right-width:0}.list-group-horizontal-sm .list-group-item+.list-group-item.active{margin-right:-1px;border-right-width:1px}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md .list-group-item:first-child{border-bottom-right-radius:.25rem;border-top-left-radius:0}.list-group-horizontal-md .list-group-item:last-child{border-top-left-radius:.25rem;border-bottom-right-radius:0}.list-group-horizontal-md .list-group-item.active{margin-top:0}.list-group-horizontal-md .list-group-item+.list-group-item{border-top-width:1px;border-right-width:0}.list-group-horizontal-md .list-group-item+.list-group-item.active{margin-right:-1px;border-right-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg .list-group-item:first-child{border-bottom-right-radius:.25rem;border-top-left-radius:0}.list-group-horizontal-lg .list-group-item:last-child{border-top-left-radius:.25rem;border-bottom-right-radius:0}.list-group-horizontal-lg .list-group-item.active{margin-top:0}.list-group-horizontal-lg .list-group-item+.list-group-item{border-top-width:1px;border-right-width:0}.list-group-horizontal-lg .list-group-item+.list-group-item.active{margin-right:-1px;border-right-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl .list-group-item:first-child{border-bottom-right-radius:.25rem;border-top-left-radius:0}.list-group-horizontal-xl .list-group-item:last-child{border-top-left-radius:.25rem;border-bottom-right-radius:0}.list-group-horizontal-xl .list-group-item.active{margin-top:0}.list-group-horizontal-xl .list-group-item+.list-group-item{border-top-width:1px;border-right-width:0}.list-group-horizontal-xl .list-group-item+.list-group-item.active{margin-right:-1px;border-right-width:1px}}.list-group-flush .list-group-item{border-right-width:0;border-left-width:0;border-radius:0}.list-group-flush .list-group-item:first-child{border-top-width:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:left;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;right:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;right:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem auto -1rem -1rem}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:right;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;bord