Count per Day - Version 2.16.1

Version Description

Bugfix: widget was empty

Download this release

Release Info

Developer Tom Braider
Plugin Icon 128x128 Count per Day
Version 2.16.1
Comparing to
See all releases

Code changes from version 2.16 to 2.16.1

ajax.php CHANGED
@@ -1,27 +1,32 @@
1
- <?php
2
- if ( $_GET['f'] == 'count' )
3
- {
4
- if (!session_id()) session_start();
5
- require_once($_SESSION['cpd_wp'].'wp-load.php');
6
-
7
- $cpd_funcs = CountPerDay_Widget::getWidgetFuncs();
8
- $page = intval($_GET['page']);
9
- if ( is_numeric($page) )
10
- {
11
- $count_per_day->count( '', $page );
12
- foreach ( $cpd_funcs as $f )
13
- {
14
- if ( ($f == 'show' && $page) || $f != 'show' )
15
- {
16
- echo $f.'===';
17
- if ( $f == 'getUserPerDay' )
18
- eval('echo $count_per_day->getUserPerDay('.$count_per_day->options['dashboard_last_days'].');');
19
- else if ( $f == 'show' )
20
- eval('echo $count_per_day->show("", "", false, false, '.$page.');');
21
- else
22
- eval('echo $count_per_day->'.$f.'();');
23
- echo '|';
24
- }
25
- }
26
- }
27
- }
1
+ <?php
2
+ if ( $_GET['f'] == 'count' )
3
+ {
4
+ if (!session_id()) session_start();
5
+ require_once($_SESSION['cpd_wp'].'wp-load.php');
6
+
7
+ // $cpd_funcs = CountPerDay_Widget::getWidgetFuncs();
8
+ $cpd_funcs = array ( 'show',
9
+ 'getReadsAll', 'getReadsToday', 'getReadsYesterday', 'getReadsLastWeek', 'getReadsThisMonth',
10
+ 'getUserAll', 'getUserToday', 'getUserYesterday', 'getUserLastWeek', 'getUserThisMonth',
11
+ 'getUserPerDay', 'getUserOnline', 'getFirstCount' );
12
+
13
+ $page = intval($_GET['page']);
14
+ if ( is_numeric($page) )
15
+ {
16
+ $count_per_day->count( '', $page );
17
+ foreach ( $cpd_funcs as $f )
18
+ {
19
+ if ( ($f == 'show' && $page) || $f != 'show' )
20
+ {
21
+ echo $f.'===';
22
+ if ( $f == 'getUserPerDay' )
23
+ eval('echo $count_per_day->getUserPerDay('.$count_per_day->options['dashboard_last_days'].');');
24
+ else if ( $f == 'show' )
25
+ eval('echo $count_per_day->show("", "", false, false, '.$page.');');
26
+ else
27
+ eval('echo $count_per_day->'.$f.'();');
28
+ echo '|';
29
+ }
30
+ }
31
+ }
32
+ }
counter.css CHANGED
@@ -128,7 +128,6 @@
128
129
.cpd_widget_item {
130
padding: 2px 5px;
131
- height: 25x;
132
background: #eee;
133
cursor: move;
134
border-radius: 4px;
128
129
.cpd_widget_item {
130
padding: 2px 5px;
131
background: #eee;
132
cursor: move;
133
border-radius: 4px;
counter.php CHANGED
@@ -3,14 +3,14 @@
3
Plugin Name: Count Per Day
4
Plugin URI: http://www.tomsdimension.de/wp-plugins/count-per-day
5
Description: Counter, shows reads per page; today, yesterday, last week, last months ... on dashboard, per shortcode or in widget.
6
- Version: 2.16
7
License: Postcardware :)
8
Author: Tom Braider
9
Author URI: http://www.tomsdimension.de
10
*/
11
12
$cpd_dir_name = 'count-per-day';
13
- $cpd_version = '2.16';
14
15
/**
16
* include GeoIP addon
@@ -2118,20 +2118,24 @@ class CountPerDay_Widget extends WP_Widget
2118
'getreadsall_name', 'getreadstoday_name', 'getreadsyesterday_name', 'getreadslastweek_name', 'getreadsthismonth_name',
2119
'getuserall_name', 'getusertoday_name', 'getuseryesterday_name', 'getuserlastweek_name', 'getuserthismonth_name',
2120
'getuserperday_name', 'getuseronline_name', 'getfirstcount_name' );
2121
- const CPDF = 'show,getReadsAll,getReadsToday,getReadsYesterday,getReadsLastWeek,getReadsThisMonth,getUserAll,getUserToday,getUserYesterday,getUserLastWeek,getUserThisMonth,getUserPerDay,getUserOnline,getFirstCount';
2122
- var $cpd_funcs;
2123
var $funcs;
2124
var $names;
2125
2126
// export functions to ajax script
2127
- public static function getWidgetFuncs()
2128
- {
2129
- return explode(',', self::CPDF);
2130
- }
2131
2132
// constructor
2133
function CountPerDay_Widget() {
2134
- $this->cpd_funcs = explode(',', self::CPDF);
2135
$this->funcs = array_slice( $this->fields, 2, 14);
2136
$this->names = array_slice( $this->fields, 16, 14);
2137
parent::WP_Widget('countperday_widget', 'Count per Day',
@@ -2191,7 +2195,7 @@ class CountPerDay_Widget extends WP_Widget
2191
{
2192
$default = array(
2193
'title' => 'Count per Day',
2194
- 'order' => '',
2195
'show' => 0,
2196
'getreadsall' => 0,
2197
'getreadstoday' => 0,
@@ -2252,7 +2256,7 @@ class CountPerDay_Widget extends WP_Widget
2252
<li itemid="'.$f.'" class="cpd_widget_item">
2253
<input type="checkbox" class="checkbox" id="'.$check_id.'" name="'.$check_name.'" value="1" '.$check_status.' />
2254
<label for="'.$check_id.'"> '.$default[$fl].'</label>
2255
- <input type="text" class="widefat" id="'.$label_id.'" name="'.$label_name.'" value="'.$label_value.'" style="width:200px" />
2256
</li>';
2257
}
2258
}
3
Plugin Name: Count Per Day
4
Plugin URI: http://www.tomsdimension.de/wp-plugins/count-per-day
5
Description: Counter, shows reads per page; today, yesterday, last week, last months ... on dashboard, per shortcode or in widget.
6
+ Version: 2.16.1
7
License: Postcardware :)
8
Author: Tom Braider
9
Author URI: http://www.tomsdimension.de
10
*/
11
12
$cpd_dir_name = 'count-per-day';
13
+ $cpd_version = '2.16.1';
14
15
/**
16
* include GeoIP addon
2118
'getreadsall_name', 'getreadstoday_name', 'getreadsyesterday_name', 'getreadslastweek_name', 'getreadsthismonth_name',
2119
'getuserall_name', 'getusertoday_name', 'getuseryesterday_name', 'getuserlastweek_name', 'getuserthismonth_name',
2120
'getuserperday_name', 'getuseronline_name', 'getfirstcount_name' );
2121
+ // const CPDF = 'show,getReadsAll,getReadsToday,getReadsYesterday,getReadsLastWeek,getReadsThisMonth,getUserAll,getUserToday,getUserYesterday,getUserLastWeek,getUserThisMonth,getUserPerDay,getUserOnline,getFirstCount';
2122
+ // var $cpd_funcs;
2123
+ var $cpd_funcs = array ( 'show',
2124
+ 'getReadsAll', 'getReadsToday', 'getReadsYesterday', 'getReadsLastWeek', 'getReadsThisMonth',
2125
+ 'getUserAll', 'getUserToday', 'getUserYesterday', 'getUserLastWeek', 'getUserThisMonth',
2126
+ 'getUserPerDay', 'getUserOnline', 'getFirstCount' );
2127
var $funcs;
2128
var $names;
2129
2130
// export functions to ajax script
2131
+ // public static function getWidgetFuncs()
2132
+ // {
2133
+ // return explode(',', self::CPDF);
2134
+ // }
2135
2136
// constructor
2137
function CountPerDay_Widget() {
2138
+ // $this->cpd_funcs = explode(',', self::CPDF);
2139
$this->funcs = array_slice( $this->fields, 2, 14);
2140
$this->names = array_slice( $this->fields, 16, 14);
2141
parent::WP_Widget('countperday_widget', 'Count per Day',
2195
{
2196
$default = array(
2197
'title' => 'Count per Day',
2198
+ 'order' => implode('|', $this->funcs),
2199
'show' => 0,
2200
'getreadsall' => 0,
2201
'getreadstoday' => 0,
2256
<li itemid="'.$f.'" class="cpd_widget_item">
2257
<input type="checkbox" class="checkbox" id="'.$check_id.'" name="'.$check_name.'" value="1" '.$check_status.' />
2258
<label for="'.$check_id.'"> '.$default[$fl].'</label>
2259
+ <input type="text" class="widefat" id="'.$label_id.'" name="'.$label_name.'" value="'.$label_value.'" />
2260
</li>';
2261
}
2262
}
geoip/GeoIP.dat CHANGED
Binary file
geoip/geoip.php CHANGED
@@ -15,7 +15,7 @@ class CpdGeoIp
15
/**
16
* gets country of ip adress
17
* @param $ip IP
18
- * @return array e.g. ( 'de', image link to easywhois.com , 'Germany' )
19
*/
20
function getCountry( $ip )
21
{
@@ -33,62 +33,47 @@ function getCountry( $ip )
33
return $country;
34
}
35
36
-
37
-
38
/**
39
* updates CountPerDay table
40
*/
41
function updateDB()
42
{
43
- global $count_per_day;
44
- global $cpd_path;
45
- global $wpdb;
46
47
- $count_per_day->getQuery("SELECT country FROM `".CPD_C_TABLE."`", 'GeoIP updateDB Table');
48
if ((int) mysql_errno() == 1054)
49
// add row "country" to table
50
- $count_per_day->getQuery("ALTER TABLE `".CPD_C_TABLE."` ADD `country` CHAR( 2 ) NOT NULL", 'GeoIP updateDB create column');
51
52
- $limit = 10;
53
- $res = $count_per_day->getQuery("SELECT ip, INET_NTOA(ip) AS realip FROM ".CPD_C_TABLE." WHERE country LIKE '' GROUP BY ip LIMIT $limit;", 'GeoIP updateDB');
54
$gi = cpd_geoip_open($cpd_path.'/geoip/GeoIP.dat', GEOIP_STANDARD);
55
56
- if ( @mysql_num_rows($res) )
57
- while ( $r = mysql_fetch_array($res) )
58
- {
59
- $c = '';
60
- $ip = explode('.', $r['realip']);
61
- if ( $ip[0] == 10
62
- || $ip[0] == 127
63
- || ($ip[0] == 169 && $ip[1] == 254)
64
- || ($ip[0] == 172 && $ip[1] >= 16 && $ip[1] <= 31)
65
- || ($ip[0] == 192 && $ip[1] == 168) )
66
- // set local IPs to '-'
67
- $c = '-';
68
- else
69
- // get country
70
- $c = strtolower(cpd_geoip_country_code_by_addr($gi, $r['realip']));
71
-
72
- if ( !empty($c) )
73
- $count_per_day->getQuery("UPDATE ".CPD_C_TABLE." SET country = '".$c."' WHERE ip = '".$r['ip']."'", 'GeoIP updateDB');
74
- }
75
-
76
- cpd_geoip_close($gi);
77
-
78
- $res = $count_per_day->getQuery("SELECT count(*) FROM ".CPD_C_TABLE." WHERE country like ''", 'GeoIP updateDB');
79
- if ( @mysql_num_rows($res) )
80
{
81
- $row = mysql_fetch_array($res);
82
- $rest = (!empty($row[0])) ? $row[0] : 0;
83
}
84
- else
85
- $rest = 0;
86
87
- return $rest;
88
}
89
90
-
91
-
92
/**
93
* updates the GeoIP database file
94
* works only if directory geoip has rights 777, set it in ftp client
15
/**
16
* gets country of ip adress
17
* @param $ip IP
18
+ * @return array e.g. ( 'de', image div , 'Germany' )
19
*/
20
function getCountry( $ip )
21
{
33
return $country;
34
}
35
36
/**
37
* updates CountPerDay table
38
*/
39
function updateDB()
40
{
41
+ global $count_per_day, $cpd_path, $wpdb;
42
43
+ $count_per_day->mysqlQuery('rows', "SELECT country FROM $wpdb->cpd_counter LIMIT 1", 'GeoIP updateDB Table '.__LINE__);
44
if ((int) mysql_errno() == 1054)
45
// add row "country" to table
46
+ $count_per_day->mysqlQuery('', "ALTER TABLE $wpdb->cpd_counter ADD `country` CHAR( 2 ) NOT NULL", 'GeoIP updateDB create column '.__LINE__);
47
48
+ $limit = 20;
49
+ $res = $count_per_day->mysqlQuery('rows', "SELECT ip, INET_NTOA(ip) realip FROM $wpdb->cpd_counter WHERE country LIKE '' GROUP BY ip LIMIT $limit", 'GeoIP updateDB '.__LINE__);
50
$gi = cpd_geoip_open($cpd_path.'/geoip/GeoIP.dat', GEOIP_STANDARD);
51
52
+ foreach ($res as $r)
53
{
54
+ $c = '';
55
+ $ip = explode('.', $r->realip);
56
+ if ( $ip[0] == 10
57
+ || $ip[0] == 127
58
+ || ($ip[0] == 169 && $ip[1] == 254)
59
+ || ($ip[0] == 172 && $ip[1] >= 16 && $ip[1] <= 31)
60
+ || ($ip[0] == 192 && $ip[1] == 168) )
61
+ // set local IPs to '-'
62
+ $c = '-';
63
+ else
64
+ // get country
65
+ $c = strtolower(cpd_geoip_country_code_by_addr($gi, $r->realip));
66
+
67
+ if ( !empty($c) )
68
+ $count_per_day->mysqlQuery('', "UPDATE $wpdb->cpd_counter SET country = '$c' WHERE ip = '$r->ip'", 'GeoIP updateDB '.__LINE__);
69
}
70
71
+ cpd_geoip_close($gi);
72
+
73
+ $rest = $count_per_day->mysqlQuery('var', "SELECT COUNT(*) FROM $wpdb->cpd_counter WHERE country like ''", 'GeoIP updateDB '.__LINE__);
74
+ return (int) $rest;
75
}
76
77
/**
78
* updates the GeoIP database file
79
* works only if directory geoip has rights 777, set it in ftp client
img/cpd_calendar.png CHANGED
Binary file
img/cpd_flags.png CHANGED
Binary file
img/cpd_pen.png CHANGED
Binary file
img/cpd_sprites.png ADDED
Binary file
js/jquery.flot.min.js CHANGED
@@ -1 +1,1988 @@
1
- (function(){jQuery.color={};jQuery.color.make=function(G,H,J,I){var A={};A.r=G||0;A.g=H||0;A.b=J||0;A.a=I!=null?I:1;A.add=function(C,D){for(var E=0;E<C.length;++E){A[C.charAt(E)]+=D}return A.normalize()};A.scale=function(C,D){for(var E=0;E<C.length;++E){A[C.charAt(E)]*=D}return A.normalize()};A.toString=function(){if(A.a>=1){return"rgb("+[A.r,A.g,A.b].join(",")+")"}else{return"rgba("+[A.r,A.g,A.b,A.a].join(",")+")"}};A.normalize=function(){function C(E,D,F){return D<E?E:(D>F?F:D)}A.r=C(0,parseInt(A.r),255);A.g=C(0,parseInt(A.g),255);A.b=C(0,parseInt(A.b),255);A.a=C(0,A.a,1);return A};A.clone=function(){return jQuery.color.make(A.r,A.b,A.g,A.a)};return A.normalize()};jQuery.color.extract=function(E,F){var A;do{A=E.css(F).toLowerCase();if(A!=""&&A!="transparent"){break}E=E.parent()}while(!jQuery.nodeName(E.get(0),"body"));if(A=="rgba(0, 0, 0, 0)"){A="transparent"}return jQuery.color.parse(A)};jQuery.color.parse=function(A){var F,H=jQuery.color.make;if(F=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(A)){return H(parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10))}if(F=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(A)){return H(parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10),parseFloat(F[4]))}if(F=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(A)){return H(parseFloat(F[1])*2.55,parseFloat(F[2])*2.55,parseFloat(F[3])*2.55)}if(F=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(A)){return H(parseFloat(F[1])*2.55,parseFloat(F[2])*2.55,parseFloat(F[3])*2.55,parseFloat(F[4]))}if(F=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(A)){return H(parseInt(F[1],16),parseInt(F[2],16),parseInt(F[3],16))}if(F=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(A)){return H(parseInt(F[1]+F[1],16),parseInt(F[2]+F[2],16),parseInt(F[3]+F[3],16))}var G=jQuery.trim(A).toLowerCase();if(G=="transparent"){return H(255,255,255,0)}else{F=B[G];return H(F[0],F[1],F[2])}};var B={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],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],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})();(function(C){function B(l,W,X,E){var O=[],g={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:true,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:0.85},xaxis:{mode:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,tickDecimals:null,tickSize:null,minTickSize:null,monthNames:null,timeformat:null,twelveHourClock:false},yaxis:{autoscaleMargin:0.02},x2axis:{autoscaleMargin:null},y2axis:{autoscaleMargin:0.02},series:{points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#ffffff"},lines:{lineWidth:2,fill:false,fillColor:null,steps:false},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,align:"left",horizontal:false},shadowSize:3},grid:{show:true,aboveData:false,color:"#545454",backgroundColor:null,tickColor:"rgba(0,0,0,0.15)",labelMargin:5,borderWidth:2,borderColor:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:false,hoverable:false,autoHighlight:true,mouseActiveRadius:10},hooks:{}},P=null,AC=null,AD=null,Y=null,AJ=null,s={xaxis:{},yaxis:{},x2axis:{},y2axis:{}},e={left:0,right:0,top:0,bottom:0},y=0,Q=0,I=0,t=0,L={processOptions:[],processRawData:[],processDatapoints:[],draw:[],bindEvents:[],drawOverlay:[]},G=this;G.setData=f;G.setupGrid=k;G.draw=AH;G.getPlaceholder=function(){return l};G.getCanvas=function(){return P};G.getPlotOffset=function(){return e};G.width=function(){return I};G.height=function(){return t};G.offset=function(){var AK=AD.offset();AK.left+=e.left;AK.top+=e.top;return AK};G.getData=function(){return O};G.getAxes=function(){return s};G.getOptions=function(){return g};G.highlight=AE;G.unhighlight=x;G.triggerRedrawOverlay=q;G.pointOffset=function(AK){return{left:parseInt(T(AK,"xaxis").p2c(+AK.x)+e.left),top:parseInt(T(AK,"yaxis").p2c(+AK.y)+e.top)}};G.hooks=L;b(G);r(X);c();f(W);k();AH();AG();function Z(AM,AK){AK=[G].concat(AK);for(var AL=0;AL<AM.length;++AL){AM[AL].apply(this,AK)}}function b(){for(var AK=0;AK<E.length;++AK){var AL=E[AK];AL.init(G);if(AL.options){C.extend(true,g,AL.options)}}}function r(AK){C.extend(true,g,AK);if(g.grid.borderColor==null){g.grid.borderColor=g.grid.color}if(g.xaxis.noTicks&&g.xaxis.ticks==null){g.xaxis.ticks=g.xaxis.noTicks}if(g.yaxis.noTicks&&g.yaxis.ticks==null){g.yaxis.ticks=g.yaxis.noTicks}if(g.grid.coloredAreas){g.grid.markings=g.grid.coloredAreas}if(g.grid.coloredAreasColor){g.grid.markingsColor=g.grid.coloredAreasColor}if(g.lines){C.extend(true,g.series.lines,g.lines)}if(g.points){C.extend(true,g.series.points,g.points)}if(g.bars){C.extend(true,g.series.bars,g.bars)}if(g.shadowSize){g.series.shadowSize=g.shadowSize}for(var AL in L){if(g.hooks[AL]&&g.hooks[AL].length){L[AL]=L[AL].concat(g.hooks[AL])}}Z(L.processOptions,[g])}function f(AK){O=M(AK);U();m()}function M(AN){var AL=[];for(var AK=0;AK<AN.length;++AK){var AM=C.extend(true,{},g.series);if(AN[AK].data){AM.data=AN[AK].data;delete AN[AK].data;C.extend(true,AM,AN[AK]);AN[AK].data=AM.data}else{AM.data=AN[AK]}AL.push(AM)}return AL}function T(AM,AK){var AL=AM[AK];if(!AL||AL==1){return s[AK]}if(typeof AL=="number"){return s[AK.charAt(0)+AL+AK.slice(1)]}return AL}function U(){var AP;var AV=O.length,AK=[],AN=[];for(AP=0;AP<O.length;++AP){var AS=O[AP].color;if(AS!=null){--AV;if(typeof AS=="number"){AN.push(AS)}else{AK.push(C.color.parse(O[AP].color))}}}for(AP=0;AP<AN.length;++AP){AV=Math.max(AV,AN[AP]+1)}var AL=[],AO=0;AP=0;while(AL.length<AV){var AR;if(g.colors.length==AP){AR=C.color.make(100,100,100)}else{AR=C.color.parse(g.colors[AP])}var AM=AO%2==1?-1:1;AR.scale("rgb",1+AM*Math.ceil(AO/2)*0.2);AL.push(AR);++AP;if(AP>=g.colors.length){AP=0;++AO}}var AQ=0,AW;for(AP=0;AP<O.length;++AP){AW=O[AP];if(AW.color==null){AW.color=AL[AQ].toString();++AQ}else{if(typeof AW.color=="number"){AW.color=AL[AW.color].toString()}}if(AW.lines.show==null){var AU,AT=true;for(AU in AW){if(AW[AU].show){AT=false;break}}if(AT){AW.lines.show=true}}AW.xaxis=T(AW,"xaxis");AW.yaxis=T(AW,"yaxis")}}function m(){var AW=Number.POSITIVE_INFINITY,AQ=Number.NEGATIVE_INFINITY,Ac,Aa,AZ,AV,AL,AR,Ab,AX,AP,AO,AK,Ai,Af,AT;for(AK in s){s[AK].datamin=AW;s[AK].datamax=AQ;s[AK].used=false}function AN(Al,Ak,Aj){if(Ak<Al.datamin){Al.datamin=Ak}if(Aj>Al.datamax){Al.datamax=Aj}}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];AR.datapoints={points:[]};Z(L.processRawData,[AR,AR.data,AR.datapoints])}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];var Ah=AR.data,Ae=AR.datapoints.format;if(!Ae){Ae=[];Ae.push({x:true,number:true,required:true});Ae.push({y:true,number:true,required:true});if(AR.bars.show){Ae.push({y:true,number:true,required:false,defaultValue:0})}AR.datapoints.format=Ae}if(AR.datapoints.pointsize!=null){continue}if(AR.datapoints.pointsize==null){AR.datapoints.pointsize=Ae.length}AX=AR.datapoints.pointsize;Ab=AR.datapoints.points;insertSteps=AR.lines.show&&AR.lines.steps;AR.xaxis.used=AR.yaxis.used=true;for(Aa=AZ=0;Aa<Ah.length;++Aa,AZ+=AX){AT=Ah[Aa];var AM=AT==null;if(!AM){for(AV=0;AV<AX;++AV){Ai=AT[AV];Af=Ae[AV];if(Af){if(Af.number&&Ai!=null){Ai=+Ai;if(isNaN(Ai)){Ai=null}}if(Ai==null){if(Af.required){AM=true}if(Af.defaultValue!=null){Ai=Af.defaultValue}}}Ab[AZ+AV]=Ai}}if(AM){for(AV=0;AV<AX;++AV){Ai=Ab[AZ+AV];if(Ai!=null){Af=Ae[AV];if(Af.x){AN(AR.xaxis,Ai,Ai)}if(Af.y){AN(AR.yaxis,Ai,Ai)}}Ab[AZ+AV]=null}}else{if(insertSteps&&AZ>0&&Ab[AZ-AX]!=null&&Ab[AZ-AX]!=Ab[AZ]&&Ab[AZ-AX+1]!=Ab[AZ+1]){for(AV=0;AV<AX;++AV){Ab[AZ+AX+AV]=Ab[AZ+AV]}Ab[AZ+1]=Ab[AZ-AX+1];AZ+=AX}}}}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];Z(L.processDatapoints,[AR,AR.datapoints])}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];Ab=AR.datapoints.points,AX=AR.datapoints.pointsize;var AS=AW,AY=AW,AU=AQ,Ad=AQ;for(Aa=0;Aa<Ab.length;Aa+=AX){if(Ab[Aa]==null){continue}for(AV=0;AV<AX;++AV){Ai=Ab[Aa+AV];Af=Ae[AV];if(!Af){continue}if(Af.x){if(Ai<AS){AS=Ai}if(Ai>AU){AU=Ai}}if(Af.y){if(Ai<AY){AY=Ai}if(Ai>Ad){Ad=Ai}}}}if(AR.bars.show){var Ag=AR.bars.align=="left"?0:-AR.bars.barWidth/2;if(AR.bars.horizontal){AY+=Ag;Ad+=Ag+AR.bars.barWidth}else{AS+=Ag;AU+=Ag+AR.bars.barWidth}}AN(AR.xaxis,AS,AU);AN(AR.yaxis,AY,Ad)}for(AK in s){if(s[AK].datamin==AW){s[AK].datamin=null}if(s[AK].datamax==AQ){s[AK].datamax=null}}}function c(){function AK(AM,AL){var AN=document.createElement("canvas");AN.width=AM;AN.height=AL;if(C.browser.msie){AN=window.G_vmlCanvasManager.initElement(AN)}return AN}y=l.width();Q=l.height();l.html("");if(l.css("position")=="static"){l.css("position","relative")}if(y<=0||Q<=0){throw"Invalid dimensions for plot, width = "+y+", height = "+Q}if(C.browser.msie){window.G_vmlCanvasManager.init_(document)}P=C(AK(y,Q)).appendTo(l).get(0);Y=P.getContext("2d");AC=C(AK(y,Q)).css({position:"absolute",left:0,top:0}).appendTo(l).get(0);AJ=AC.getContext("2d");AJ.stroke()}function AG(){AD=C([AC,P]);if(g.grid.hoverable){AD.mousemove(D)}if(g.grid.clickable){AD.click(d)}Z(L.bindEvents,[AD])}function k(){function AL(AT,AU){function AP(AV){return AV}var AS,AO,AQ=AU.transform||AP,AR=AU.inverseTransform;if(AT==s.xaxis||AT==s.x2axis){AS=AT.scale=I/(AQ(AT.max)-AQ(AT.min));AO=AQ(AT.min);if(AQ==AP){AT.p2c=function(AV){return(AV-AO)*AS}}else{AT.p2c=function(AV){return(AQ(AV)-AO)*AS}}if(!AR){AT.c2p=function(AV){return AO+AV/AS}}else{AT.c2p=function(AV){return AR(AO+AV/AS)}}}else{AS=AT.scale=t/(AQ(AT.max)-AQ(AT.min));AO=AQ(AT.max);if(AQ==AP){AT.p2c=function(AV){return(AO-AV)*AS}}else{AT.p2c=function(AV){return(AO-AQ(AV))*AS}}if(!AR){AT.c2p=function(AV){return AO-AV/AS}}else{AT.c2p=function(AV){return AR(AO-AV/AS)}}}}function AN(AR,AT){var AQ,AS=[],AP;AR.labelWidth=AT.labelWidth;AR.labelHeight=AT.labelHeight;if(AR==s.xaxis||AR==s.x2axis){if(AR.labelWidth==null){AR.labelWidth=y/(AR.ticks.length>0?AR.ticks.length:1)}if(AR.labelHeight==null){AS=[];for(AQ=0;AQ<AR.ticks.length;++AQ){AP=AR.ticks[AQ].label;if(AP){AS.push('<div class="tickLabel" style="float:left;width:'+AR.labelWidth+'px">'+AP+"</div>")}}if(AS.length>0){var AO=C('<div style="position:absolute;top:-10000px;width:10000px;font-size:smaller">'+AS.join("")+'<div style="clear:left"></div></div>').appendTo(l);AR.labelHeight=AO.height();AO.remove()}}}else{if(AR.labelWidth==null||AR.labelHeight==null){for(AQ=0;AQ<AR.ticks.length;++AQ){AP=AR.ticks[AQ].label;if(AP){AS.push('<div class="tickLabel">'+AP+"</div>")}}if(AS.length>0){var AO=C('<div style="position:absolute;top:-10000px;font-size:smaller">'+AS.join("")+"</div>").appendTo(l);if(AR.labelWidth==null){AR.labelWidth=AO.width()}if(AR.labelHeight==null){AR.labelHeight=AO.find("div").height()}AO.remove()}}}if(AR.labelWidth==null){AR.labelWidth=0}if(AR.labelHeight==null){AR.labelHeight=0}}function AM(){var AP=g.grid.borderWidth;for(i=0;i<O.length;++i){AP=Math.max(AP,2*(O[i].points.radius+O[i].points.lineWidth/2))}e.left=e.right=e.top=e.bottom=AP;var AO=g.grid.labelMargin+g.grid.borderWidth;if(s.xaxis.labelHeight>0){e.bottom=Math.max(AP,s.xaxis.labelHeight+AO)}if(s.yaxis.labelWidth>0){e.left=Math.max(AP,s.yaxis.labelWidth+AO)}if(s.x2axis.labelHeight>0){e.top=Math.max(AP,s.x2axis.labelHeight+AO)}if(s.y2axis.labelWidth>0){e.right=Math.max(AP,s.y2axis.labelWidth+AO)}I=y-e.left-e.right;t=Q-e.bottom-e.top}var AK;for(AK in s){K(s[AK],g[AK])}if(g.grid.show){for(AK in s){F(s[AK],g[AK]);p(s[AK],g[AK]);AN(s[AK],g[AK])}AM()}else{e.left=e.right=e.top=e.bottom=0;I=y;t=Q}for(AK in s){AL(s[AK],g[AK])}if(g.grid.show){h()}AI()}function K(AN,AQ){var AM=+(AQ.min!=null?AQ.min:AN.datamin),AK=+(AQ.max!=null?AQ.max:AN.datamax),AP=AK-AM;if(AP==0){var AL=AK==0?1:0.01;if(AQ.min==null){AM-=AL}if(AQ.max==null||AQ.min!=null){AK+=AL}}else{var AO=AQ.autoscaleMargin;if(AO!=null){if(AQ.min==null){AM-=AP*AO;if(AM<0&&AN.datamin!=null&&AN.datamin>=0){AM=0}}if(AQ.max==null){AK+=AP*AO;if(AK>0&&AN.datamax!=null&&AN.datamax<=0){AK=0}}}}AN.min=AM;AN.max=AK}function F(AP,AS){var AO;if(typeof AS.ticks=="number"&&AS.ticks>0){AO=AS.ticks}else{if(AP==s.xaxis||AP==s.x2axis){AO=0.3*Math.sqrt(y)}else{AO=0.3*Math.sqrt(Q)}}var AX=(AP.max-AP.min)/AO,AZ,AT,AV,AW,AR,AM,AL;if(AS.mode=="time"){var AU={second:1000,minute:60*1000,hour:60*60*1000,day:24*60*60*1000,month:30*24*60*60*1000,year:365.2425*24*60*60*1000};var AY=[[1,"second"],[2,"second"],[5,"second"],[10,"second"],[30,"second"],[1,"minute"],[2,"minute"],[5,"minute"],[10,"minute"],[30,"minute"],[1,"hour"],[2,"hour"],[4,"hour"],[8,"hour"],[12,"hour"],[1,"day"],[2,"day"],[3,"day"],[0.25,"month"],[0.5,"month"],[1,"month"],[2,"month"],[3,"month"],[6,"month"],[1,"year"]];var AN=0;if(AS.minTickSize!=null){if(typeof AS.tickSize=="number"){AN=AS.tickSize}else{AN=AS.minTickSize[0]*AU[AS.minTickSize[1]]}}for(AR=0;AR<AY.length-1;++AR){if(AX<(AY[AR][0]*AU[AY[AR][1]]+AY[AR+1][0]*AU[AY[AR+1][1]])/2&&AY[AR][0]*AU[AY[AR][1]]>=AN){break}}AZ=AY[AR][0];AV=AY[AR][1];if(AV=="year"){AM=Math.pow(10,Math.floor(Math.log(AX/AU.year)/Math.LN10));AL=(AX/AU.year)/AM;if(AL<1.5){AZ=1}else{if(AL<3){AZ=2}else{if(AL<7.5){AZ=5}else{AZ=10}}}AZ*=AM}if(AS.tickSize){AZ=AS.tickSize[0];AV=AS.tickSize[1]}AT=function(Ac){var Ah=[],Af=Ac.tickSize[0],Ai=Ac.tickSize[1],Ag=new Date(Ac.min);var Ab=Af*AU[Ai];if(Ai=="second"){Ag.setUTCSeconds(A(Ag.getUTCSeconds(),Af))}if(Ai=="minute"){Ag.setUTCMinutes(A(Ag.getUTCMinutes(),Af))}if(Ai=="hour"){Ag.setUTCHours(A(Ag.getUTCHours(),Af))}if(Ai=="month"){Ag.setUTCMonth(A(Ag.getUTCMonth(),Af))}if(Ai=="year"){Ag.setUTCFullYear(A(Ag.getUTCFullYear(),Af))}Ag.setUTCMilliseconds(0);if(Ab>=AU.minute){Ag.setUTCSeconds(0)}if(Ab>=AU.hour){Ag.setUTCMinutes(0)}if(Ab>=AU.day){Ag.setUTCHours(0)}if(Ab>=AU.day*4){Ag.setUTCDate(1)}if(Ab>=AU.year){Ag.setUTCMonth(0)}var Ak=0,Aj=Number.NaN,Ad;do{Ad=Aj;Aj=Ag.getTime();Ah.push({v:Aj,label:Ac.tickFormatter(Aj,Ac)});if(Ai=="month"){if(Af<1){Ag.setUTCDate(1);var Aa=Ag.getTime();Ag.setUTCMonth(Ag.getUTCMonth()+1);var Ae=Ag.getTime();Ag.setTime(Aj+Ak*AU.hour+(Ae-Aa)*Af);Ak=Ag.getUTCHours();Ag.setUTCHours(0)}else{Ag.setUTCMonth(Ag.getUTCMonth()+Af)}}else{if(Ai=="year"){Ag.setUTCFullYear(Ag.getUTCFullYear()+Af)}else{Ag.setTime(Aj+Ab)}}}while(Aj<Ac.max&&Aj!=Ad);return Ah};AW=function(Aa,Ad){var Af=new Date(Aa);if(AS.timeformat!=null){return C.plot.formatDate(Af,AS.timeformat,AS.monthNames)}var Ab=Ad.tickSize[0]*AU[Ad.tickSize[1]];var Ac=Ad.max-Ad.min;var Ae=(AS.twelveHourClock)?" %p":"";if(Ab<AU.minute){fmt="%h:%M:%S"+Ae}else{if(Ab<AU.day){if(Ac<2*AU.day){fmt="%h:%M"+Ae}else{fmt="%b %d %h:%M"+Ae}}else{if(Ab<AU.month){fmt="%b %d"}else{if(Ab<AU.year){if(Ac<AU.year){fmt="%b"}else{fmt="%b %y"}}else{fmt="%y"}}}}return C.plot.formatDate(Af,fmt,AS.monthNames)}}else{var AK=AS.tickDecimals;var AQ=-Math.floor(Math.log(AX)/Math.LN10);if(AK!=null&&AQ>AK){AQ=AK}AM=Math.pow(10,-AQ);AL=AX/AM;if(AL<1.5){AZ=1}else{if(AL<3){AZ=2;if(AL>2.25&&(AK==null||AQ+1<=AK)){AZ=2.5;++AQ}}else{if(AL<7.5){AZ=5}else{AZ=10}}}AZ*=AM;if(AS.minTickSize!=null&&AZ<AS.minTickSize){AZ=AS.minTickSize}if(AS.tickSize!=null){AZ=AS.tickSize}AP.tickDecimals=Math.max(0,(AK!=null)?AK:AQ);AT=function(Ac){var Ae=[];var Af=A(Ac.min,Ac.tickSize),Ab=0,Aa=Number.NaN,Ad;do{Ad=Aa;Aa=Af+Ab*Ac.tickSize;Ae.push({v:Aa,label:Ac.tickFormatter(Aa,Ac)});++Ab}while(Aa<Ac.max&&Aa!=Ad);return Ae};AW=function(Aa,Ab){return Aa.toFixed(Ab.tickDecimals)}}AP.tickSize=AV?[AZ,AV]:AZ;AP.tickGenerator=AT;if(C.isFunction(AS.tickFormatter)){AP.tickFormatter=function(Aa,Ab){return""+AS.tickFormatter(Aa,Ab)}}else{AP.tickFormatter=AW}}function p(AO,AQ){AO.ticks=[];if(!AO.used){return }if(AQ.ticks==null){AO.ticks=AO.tickGenerator(AO)}else{if(typeof AQ.ticks=="number"){if(AQ.ticks>0){AO.ticks=AO.tickGenerator(AO)}}else{if(AQ.ticks){var AP=AQ.ticks;if(C.isFunction(AP)){AP=AP({min:AO.min,max:AO.max})}var AN,AK;for(AN=0;AN<AP.length;++AN){var AL=null;var AM=AP[AN];if(typeof AM=="object"){AK=AM[0];if(AM.length>1){AL=AM[1]}}else{AK=AM}if(AL==null){AL=AO.tickFormatter(AK,AO)}AO.ticks[AN]={v:AK,label:AL}}}}}if(AQ.autoscaleMargin!=null&&AO.ticks.length>0){if(AQ.min==null){AO.min=Math.min(AO.min,AO.ticks[0].v)}if(AQ.max==null&&AO.ticks.length>1){AO.max=Math.max(AO.max,AO.ticks[AO.ticks.length-1].v)}}}function AH(){Y.clearRect(0,0,y,Q);var AL=g.grid;if(AL.show&&!AL.aboveData){S()}for(var AK=0;AK<O.length;++AK){AA(O[AK])}Z(L.draw,[Y]);if(AL.show&&AL.aboveData){S()}}function N(AL,AR){var AO=AR+"axis",AK=AR+"2axis",AN,AQ,AP,AM;if(AL[AO]){AN=s[AO];AQ=AL[AO].from;AP=AL[AO].to}else{if(AL[AK]){AN=s[AK];AQ=AL[AK].from;AP=AL[AK].to}else{AN=s[AO];AQ=AL[AR+"1"];AP=AL[AR+"2"]}}if(AQ!=null&&AP!=null&&AQ>AP){return{from:AP,to:AQ,axis:AN}}return{from:AQ,to:AP,axis:AN}}function S(){var AO;Y.save();Y.translate(e.left,e.top);if(g.grid.backgroundColor){Y.fillStyle=R(g.grid.backgroundColor,t,0,"rgba(255, 255, 255, 0)");Y.fillRect(0,0,I,t)}var AL=g.grid.markings;if(AL){if(C.isFunction(AL)){AL=AL({xmin:s.xaxis.min,xmax:s.xaxis.max,ymin:s.yaxis.min,ymax:s.yaxis.max,xaxis:s.xaxis,yaxis:s.yaxis,x2axis:s.x2axis,y2axis:s.y2axis})}for(AO=0;AO<AL.length;++AO){var AK=AL[AO],AQ=N(AK,"x"),AN=N(AK,"y");if(AQ.from==null){AQ.from=AQ.axis.min}if(AQ.to==null){AQ.to=AQ.axis.max}if(AN.from==null){AN.from=AN.axis.min}if(AN.to==null){AN.to=AN.axis.max}if(AQ.to<AQ.axis.min||AQ.from>AQ.axis.max||AN.to<AN.axis.min||AN.from>AN.axis.max){continue}AQ.from=Math.max(AQ.from,AQ.axis.min);AQ.to=Math.min(AQ.to,AQ.axis.max);AN.from=Math.max(AN.from,AN.axis.min);AN.to=Math.min(AN.to,AN.axis.max);if(AQ.from==AQ.to&&AN.from==AN.to){continue}AQ.from=AQ.axis.p2c(AQ.from);AQ.to=AQ.axis.p2c(AQ.to);AN.from=AN.axis.p2c(AN.from);AN.to=AN.axis.p2c(AN.to);if(AQ.from==AQ.to||AN.from==AN.to){Y.beginPath();Y.strokeStyle=AK.color||g.grid.markingsColor;Y.lineWidth=AK.lineWidth||g.grid.markingsLineWidth;Y.moveTo(AQ.from,AN.from);Y.lineTo(AQ.to,AN.to);Y.stroke()}else{Y.fillStyle=AK.color||g.grid.markingsColor;Y.fillRect(AQ.from,AN.to,AQ.to-AQ.from,AN.from-AN.to)}}}Y.lineWidth=1;Y.strokeStyle=g.grid.tickColor;Y.beginPath();var AM,AP=s.xaxis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=s.xaxis.max){continue}Y.moveTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,0);Y.lineTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,t)}AP=s.yaxis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(0,Math.floor(AP.p2c(AM))+Y.lineWidth/2);Y.lineTo(I,Math.floor(AP.p2c(AM))+Y.lineWidth/2)}AP=s.x2axis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,-5);Y.lineTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,5)}AP=s.y2axis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(I-5,Math.floor(AP.p2c(AM))+Y.lineWidth/2);Y.lineTo(I+5,Math.floor(AP.p2c(AM))+Y.lineWidth/2)}Y.stroke();if(g.grid.borderWidth){var AR=g.grid.borderWidth;Y.lineWidth=AR;Y.strokeStyle=g.grid.borderColor;Y.strokeRect(-AR/2,-AR/2,I+AR,t+AR)}Y.restore()}function h(){l.find(".tickLabels").remove();var AK=['<div class="tickLabels" style="font-size:smaller;color:'+g.grid.color+'">'];function AM(AP,AQ){for(var AO=0;AO<AP.ticks.length;++AO){var AN=AP.ticks[AO];if(!AN.label||AN.v<AP.min||AN.v>AP.max){continue}AK.push(AQ(AN,AP))}}var AL=g.grid.labelMargin+g.grid.borderWidth;AM(s.xaxis,function(AN,AO){return'<div style="position:absolute;top:'+(e.top+t+AL)+"px;left:"+Math.round(e.left+AO.p2c(AN.v)-AO.labelWidth/2)+"px;width:"+AO.labelWidth+'px;text-align:center" class="tickLabel">'+AN.label+"</div>"});AM(s.yaxis,function(AN,AO){return'<div style="position:absolute;top:'+Math.round(e.top+AO.p2c(AN.v)-AO.labelHeight/2)+"px;right:"+(e.right+I+AL)+"px;width:"+AO.labelWidth+'px;text-align:right" class="tickLabel">'+AN.label+"</div>"});AM(s.x2axis,function(AN,AO){return'<div style="position:absolute;bottom:'+(e.bottom+t+AL)+"px;left:"+Math.round(e.left+AO.p2c(AN.v)-AO.labelWidth/2)+"px;width:"+AO.labelWidth+'px;text-align:center" class="tickLabel">'+AN.label+"</div>"});AM(s.y2axis,function(AN,AO){return'<div style="position:absolute;top:'+Math.round(e.top+AO.p2c(AN.v)-AO.labelHeight/2)+"px;left:"+(e.left+I+AL)+"px;width:"+AO.labelWidth+'px;text-align:left" class="tickLabel">'+AN.label+"</div>"});AK.push("</div>");l.append(AK.join(""))}function AA(AK){if(AK.lines.show){a(AK)}if(AK.bars.show){n(AK)}if(AK.points.show){o(AK)}}function a(AN){function AM(AY,AZ,AR,Ad,Ac){var Ae=AY.points,AS=AY.pointsize,AW=null,AV=null;Y.beginPath();for(var AX=AS;AX<Ae.length;AX+=AS){var AU=Ae[AX-AS],Ab=Ae[AX-AS+1],AT=Ae[AX],Aa=Ae[AX+1];if(AU==null||AT==null){continue}if(Ab<=Aa&&Ab<Ac.min){if(Aa<Ac.min){continue}AU=(Ac.min-Ab)/(Aa-Ab)*(AT-AU)+AU;Ab=Ac.min}else{if(Aa<=Ab&&Aa<Ac.min){if(Ab<Ac.min){continue}AT=(Ac.min-Ab)/(Aa-Ab)*(AT-AU)+AU;Aa=Ac.min}}if(Ab>=Aa&&Ab>Ac.max){if(Aa>Ac.max){continue}AU=(Ac.max-Ab)/(Aa-Ab)*(AT-AU)+AU;Ab=Ac.max}else{if(Aa>=Ab&&Aa>Ac.max){if(Ab>Ac.max){continue}AT=(Ac.max-Ab)/(Aa-Ab)*(AT-AU)+AU;Aa=Ac.max}}if(AU<=AT&&AU<Ad.min){if(AT<Ad.min){continue}Ab=(Ad.min-AU)/(AT-AU)*(Aa-Ab)+Ab;AU=Ad.min}else{if(AT<=AU&&AT<Ad.min){if(AU<Ad.min){continue}Aa=(Ad.min-AU)/(AT-AU)*(Aa-Ab)+Ab;AT=Ad.min}}if(AU>=AT&&AU>Ad.max){if(AT>Ad.max){continue}Ab=(Ad.max-AU)/(AT-AU)*(Aa-Ab)+Ab;AU=Ad.max}else{if(AT>=AU&&AT>Ad.max){if(AU>Ad.max){continue}Aa=(Ad.max-AU)/(AT-AU)*(Aa-Ab)+Ab;AT=Ad.max}}if(AU!=AW||Ab!=AV){Y.moveTo(Ad.p2c(AU)+AZ,Ac.p2c(Ab)+AR)}AW=AT;AV=Aa;Y.lineTo(Ad.p2c(AT)+AZ,Ac.p2c(Aa)+AR)}Y.stroke()}function AO(AX,Ae,Ac){var Af=AX.points,AR=AX.pointsize,AS=Math.min(Math.max(0,Ac.min),Ac.max),Aa,AV=0,Ad=false;for(var AW=AR;AW<Af.length;AW+=AR){var AU=Af[AW-AR],Ab=Af[AW-AR+1],AT=Af[AW],AZ=Af[AW+1];if(Ad&&AU!=null&&AT==null){Y.lineTo(Ae.p2c(AV),Ac.p2c(AS));Y.fill();Ad=false;continue}if(AU==null||AT==null){continue}if(AU<=AT&&AU<Ae.min){if(AT<Ae.min){continue}Ab=(Ae.min-AU)/(AT-AU)*(AZ-Ab)+Ab;AU=Ae.min}else{if(AT<=AU&&AT<Ae.min){if(AU<Ae.min){continue}AZ=(Ae.min-AU)/(AT-AU)*(AZ-Ab)+Ab;AT=Ae.min}}if(AU>=AT&&AU>Ae.max){if(AT>Ae.max){continue}Ab=(Ae.max-AU)/(AT-AU)*(AZ-Ab)+Ab;AU=Ae.max}else{if(AT>=AU&&AT>Ae.max){if(AU>Ae.max){continue}AZ=(Ae.max-AU)/(AT-AU)*(AZ-Ab)+Ab;AT=Ae.max}}if(!Ad){Y.beginPath();Y.moveTo(Ae.p2c(AU),Ac.p2c(AS));Ad=true}if(Ab>=Ac.max&&AZ>=Ac.max){Y.lineTo(Ae.p2c(AU),Ac.p2c(Ac.max));Y.lineTo(Ae.p2c(AT),Ac.p2c(Ac.max));AV=AT;continue}else{if(Ab<=Ac.min&&AZ<=Ac.min){Y.lineTo(Ae.p2c(AU),Ac.p2c(Ac.min));Y.lineTo(Ae.p2c(AT),Ac.p2c(Ac.min));AV=AT;continue}}var Ag=AU,AY=AT;if(Ab<=AZ&&Ab<Ac.min&&AZ>=Ac.min){AU=(Ac.min-Ab)/(AZ-Ab)*(AT-AU)+AU;Ab=Ac.min}else{if(AZ<=Ab&&AZ<Ac.min&&Ab>=Ac.min){AT=(Ac.min-Ab)/(AZ-Ab)*(AT-AU)+AU;AZ=Ac.min}}if(Ab>=AZ&&Ab>Ac.max&&AZ<=Ac.max){AU=(Ac.max-Ab)/(AZ-Ab)*(AT-AU)+AU;Ab=Ac.max}else{if(AZ>=Ab&&AZ>Ac.max&&Ab<=Ac.max){AT=(Ac.max-Ab)/(AZ-Ab)*(AT-AU)+AU;AZ=Ac.max}}if(AU!=Ag){if(Ab<=Ac.min){Aa=Ac.min}else{Aa=Ac.max}Y.lineTo(Ae.p2c(Ag),Ac.p2c(Aa));Y.lineTo(Ae.p2c(AU),Ac.p2c(Aa))}Y.lineTo(Ae.p2c(AU),Ac.p2c(Ab));Y.lineTo(Ae.p2c(AT),Ac.p2c(AZ));if(AT!=AY){if(AZ<=Ac.min){Aa=Ac.min}else{Aa=Ac.max}Y.lineTo(Ae.p2c(AT),Ac.p2c(Aa));Y.lineTo(Ae.p2c(AY),Ac.p2c(Aa))}AV=Math.max(AT,AY)}if(Ad){Y.lineTo(Ae.p2c(AV),Ac.p2c(AS));Y.fill()}}Y.save();Y.translate(e.left,e.top);Y.lineJoin="round";var AP=AN.lines.lineWidth,AK=AN.shadowSize;if(AP>0&&AK>0){Y.lineWidth=AK;Y.strokeStyle="rgba(0,0,0,0.1)";var AQ=Math.PI/18;AM(AN.datapoints,Math.sin(AQ)*(AP/2+AK/2),Math.cos(AQ)*(AP/2+AK/2),AN.xaxis,AN.yaxis);Y.lineWidth=AK/2;AM(AN.datapoints,Math.sin(AQ)*(AP/2+AK/4),Math.cos(AQ)*(AP/2+AK/4),AN.xaxis,AN.yaxis)}Y.lineWidth=AP;Y.strokeStyle=AN.color;var AL=V(AN.lines,AN.color,0,t);if(AL){Y.fillStyle=AL;AO(AN.datapoints,AN.xaxis,AN.yaxis)}if(AP>0){AM(AN.datapoints,0,0,AN.xaxis,AN.yaxis)}Y.restore()}function o(AN){function AP(AU,AT,Ab,AR,AV,AZ,AY){var Aa=AU.points,AQ=AU.pointsize;for(var AS=0;AS<Aa.length;AS+=AQ){var AX=Aa[AS],AW=Aa[AS+1];if(AX==null||AX<AZ.min||AX>AZ.max||AW<AY.min||AW>AY.max){continue}Y.beginPath();Y.arc(AZ.p2c(AX),AY.p2c(AW)+AR,AT,0,AV,false);if(Ab){Y.fillStyle=Ab;Y.fill()}Y.stroke()}}Y.save();Y.translate(e.left,e.top);var AO=AN.lines.lineWidth,AL=AN.shadowSize,AK=AN.points.radius;if(AO>0&&AL>0){var AM=AL/2;Y.lineWidth=AM;Y.strokeStyle="rgba(0,0,0,0.1)";AP(AN.datapoints,AK,null,AM+AM/2,Math.PI,AN.xaxis,AN.yaxis);Y.strokeStyle="rgba(0,0,0,0.2)";AP(AN.datapoints,AK,null,AM/2,Math.PI,AN.xaxis,AN.yaxis)}Y.lineWidth=AO;Y.strokeStyle=AN.color;AP(AN.datapoints,AK,V(AN.points,AN.color),0,2*Math.PI,AN.xaxis,AN.yaxis);Y.restore()}function AB(AV,AU,Ad,AQ,AY,AN,AL,AT,AS,Ac,AZ){var AM,Ab,AR,AX,AO,AK,AW,AP,Aa;if(AZ){AP=AK=AW=true;AO=false;AM=Ad;Ab=AV;AX=AU+AQ;AR=AU+AY;if(Ab<AM){Aa=Ab;Ab=AM;AM=Aa;AO=true;AK=false}}else{AO=AK=AW=true;AP=false;AM=AV+AQ;Ab=AV+AY;AR=Ad;AX=AU;if(AX<AR){Aa=AX;AX=AR;AR=Aa;AP=true;AW=false}}if(Ab<AT.min||AM>AT.max||AX<AS.min||AR>AS.max){return }if(AM<AT.min){AM=AT.min;AO=false}if(Ab>AT.max){Ab=AT.max;AK=false}if(AR<AS.min){AR=AS.min;AP=false}if(AX>AS.max){AX=AS.max;AW=false}AM=AT.p2c(AM);AR=AS.p2c(AR);Ab=AT.p2c(Ab);AX=AS.p2c(AX);if(AL){Ac.beginPath();Ac.moveTo(AM,AR);Ac.lineTo(AM,AX);Ac.lineTo(Ab,AX);Ac.lineTo(Ab,AR);Ac.fillStyle=AL(AR,AX);Ac.fill()}if(AO||AK||AW||AP){Ac.beginPath();Ac.moveTo(AM,AR+AN);if(AO){Ac.lineTo(AM,AX+AN)}else{Ac.moveTo(AM,AX+AN)}if(AW){Ac.lineTo(Ab,AX+AN)}else{Ac.moveTo(Ab,AX+AN)}if(AK){Ac.lineTo(Ab,AR+AN)}else{Ac.moveTo(Ab,AR+AN)}if(AP){Ac.lineTo(AM,AR+AN)}else{Ac.moveTo(AM,AR+AN)}Ac.stroke()}}function n(AM){function AL(AS,AR,AU,AP,AT,AW,AV){var AX=AS.points,AO=AS.pointsize;for(var AQ=0;AQ<AX.length;AQ+=AO){if(AX[AQ]==null){continue}AB(AX[AQ],AX[AQ+1],AX[AQ+2],AR,AU,AP,AT,AW,AV,Y,AM.bars.horizontal)}}Y.save();Y.translate(e.left,e.top);Y.lineWidth=AM.bars.lineWidth;Y.strokeStyle=AM.color;var AK=AM.bars.align=="left"?0:-AM.bars.barWidth/2;var AN=AM.bars.fill?function(AO,AP){return V(AM.bars,AM.color,AO,AP)}:null;AL(AM.datapoints,AK,AK+AM.bars.barWidth,0,AN,AM.xaxis,AM.yaxis);Y.restore()}function V(AM,AK,AL,AO){var AN=AM.fill;if(!AN){return null}if(AM.fillColor){return R(AM.fillColor,AL,AO,AK)}var AP=C.color.parse(AK);AP.a=typeof AN=="number"?AN:0.4;AP.normalize();return AP.toString()}function AI(){l.find(".legend").remove();if(!g.legend.show){return }var AP=[],AN=false,AV=g.legend.labelFormatter,AU,AR;for(i=0;i<O.length;++i){AU=O[i];AR=AU.label;if(!AR){continue}if(i%g.legend.noColumns==0){if(AN){AP.push("</tr>")}AP.push("<tr>");AN=true}if(AV){AR=AV(AR,AU)}AP.push('<td class="legendColorBox"><div style="border:1px solid '+g.legend.labelBoxBorderColor+';padding:1px"><div style="width:4px;height:0;border:5px solid '+AU.color+';overflow:hidden"></div></div></td><td class="legendLabel">'+AR+"</td>")}if(AN){AP.push("</tr>")}if(AP.length==0){return }var AT='<table style="font-size:smaller;color:'+g.grid.color+'">'+AP.join("")+"</table>";if(g.legend.container!=null){C(g.legend.container).html(AT)}else{var AQ="",AL=g.legend.position,AM=g.legend.margin;if(AM[0]==null){AM=[AM,AM]}if(AL.charAt(0)=="n"){AQ+="top:"+(AM[1]+e.top)+"px;"}else{if(AL.charAt(0)=="s"){AQ+="bottom:"+(AM[1]+e.bottom)+"px;"}}if(AL.charAt(1)=="e"){AQ+="right:"+(AM[0]+e.right)+"px;"}else{if(AL.charAt(1)=="w"){AQ+="left:"+(AM[0]+e.left)+"px;"}}var AS=C('<div class="legend">'+AT.replace('style="','style="position:absolute;'+AQ+";")+"</div>").appendTo(l);if(g.legend.backgroundOpacity!=0){var AO=g.legend.backgroundColor;if(AO==null){AO=g.grid.backgroundColor;if(AO&&typeof AO=="string"){AO=C.color.parse(AO)}else{AO=C.color.extract(AS,"background-color")}AO.a=1;AO=AO.toString()}var AK=AS.children();C('<div style="position:absolute;width:'+AK.width()+"px;height:"+AK.height()+"px;"+AQ+"background-color:"+AO+';"> </div>').prependTo(AS).css("opacity",g.legend.backgroundOpacity)}}}var w=[],J=null;function AF(AR,AP,AM){var AX=g.grid.mouseActiveRadius,Aj=AX*AX+1,Ah=null,Aa=false,Af,Ad;for(Af=0;Af<O.length;++Af){if(!AM(O[Af])){continue}var AY=O[Af],AQ=AY.xaxis,AO=AY.yaxis,Ae=AY.datapoints.points,Ac=AY.datapoints.pointsize,AZ=AQ.c2p(AR),AW=AO.c2p(AP),AL=AX/AQ.scale,AK=AX/AO.scale;if(AY.lines.show||AY.points.show){for(Ad=0;Ad<Ae.length;Ad+=Ac){var AT=Ae[Ad],AS=Ae[Ad+1];if(AT==null){continue}if(AT-AZ>AL||AT-AZ<-AL||AS-AW>AK||AS-AW<-AK){continue}var AV=Math.abs(AQ.p2c(AT)-AR),AU=Math.abs(AO.p2c(AS)-AP),Ab=AV*AV+AU*AU;if(Ab<=Aj){Aj=Ab;Ah=[Af,Ad/Ac]}}}if(AY.bars.show&&!Ah){var AN=AY.bars.align=="left"?0:-AY.bars.barWidth/2,Ag=AN+AY.bars.barWidth;for(Ad=0;Ad<Ae.length;Ad+=Ac){var AT=Ae[Ad],AS=Ae[Ad+1],Ai=Ae[Ad+2];if(AT==null){continue}if(O[Af].bars.horizontal?(AZ<=Math.max(Ai,AT)&&AZ>=Math.min(Ai,AT)&&AW>=AS+AN&&AW<=AS+Ag):(AZ>=AT+AN&&AZ<=AT+Ag&&AW>=Math.min(Ai,AS)&&AW<=Math.max(Ai,AS))){Ah=[Af,Ad/Ac]}}}}if(Ah){Af=Ah[0];Ad=Ah[1];Ac=O[Af].datapoints.pointsize;return{datapoint:O[Af].datapoints.points.slice(Ad*Ac,(Ad+1)*Ac),dataIndex:Ad,series:O[Af],seriesIndex:Af}}return null}function D(AK){if(g.grid.hoverable){H("plothover",AK,function(AL){return AL.hoverable!=false})}}function d(AK){H("plotclick",AK,function(AL){return AL.clickable!=false})}function H(AL,AK,AM){var AN=AD.offset(),AS={pageX:AK.pageX,pageY:AK.pageY},AQ=AK.pageX-AN.left-e.left,AO=AK.pageY-AN.top-e.top;if(s.xaxis.used){AS.x=s.xaxis.c2p(AQ)}if(s.yaxis.used){AS.y=s.yaxis.c2p(AO)}if(s.x2axis.used){AS.x2=s.x2axis.c2p(AQ)}if(s.y2axis.used){AS.y2=s.y2axis.c2p(AO)}var AT=AF(AQ,AO,AM);if(AT){AT.pageX=parseInt(AT.series.xaxis.p2c(AT.datapoint[0])+AN.left+e.left);AT.pageY=parseInt(AT.series.yaxis.p2c(AT.datapoint[1])+AN.top+e.top)}if(g.grid.autoHighlight){for(var AP=0;AP<w.length;++AP){var AR=w[AP];if(AR.auto==AL&&!(AT&&AR.series==AT.series&&AR.point==AT.datapoint)){x(AR.series,AR.point)}}if(AT){AE(AT.series,AT.datapoint,AL)}}l.trigger(AL,[AS,AT])}function q(){if(!J){J=setTimeout(v,30)}}function v(){J=null;AJ.save();AJ.clearRect(0,0,y,Q);AJ.translate(e.left,e.top);var AL,AK;for(AL=0;AL<w.length;++AL){AK=w[AL];if(AK.series.bars.show){z(AK.series,AK.point)}else{u(AK.series,AK.point)}}AJ.restore();Z(L.drawOverlay,[AJ])}function AE(AM,AK,AN){if(typeof AM=="number"){AM=O[AM]}if(typeof AK=="number"){AK=AM.data[AK]}var AL=j(AM,AK);if(AL==-1){w.push({series:AM,point:AK,auto:AN});q()}else{if(!AN){w[AL].auto=false}}}function x(AM,AK){if(AM==null&&AK==null){w=[];q()}if(typeof AM=="number"){AM=O[AM]}if(typeof AK=="number"){AK=AM.data[AK]}var AL=j(AM,AK);if(AL!=-1){w.splice(AL,1);q()}}function j(AM,AN){for(var AK=0;AK<w.length;++AK){var AL=w[AK];if(AL.series==AM&&AL.point[0]==AN[0]&&AL.point[1]==AN[1]){return AK}}return -1}function u(AN,AM){var AL=AM[0],AR=AM[1],AQ=AN.xaxis,AP=AN.yaxis;if(AL<AQ.min||AL>AQ.max||AR<AP.min||AR>AP.max){return }var AO=AN.points.radius+AN.points.lineWidth/2;AJ.lineWidth=AO;AJ.strokeStyle=C.color.parse(AN.color).scale("a",0.5).toString();var AK=1.5*AO;AJ.beginPath();AJ.arc(AQ.p2c(AL),AP.p2c(AR),AK,0,2*Math.PI,false);AJ.stroke()}function z(AN,AK){AJ.lineWidth=AN.bars.lineWidth;AJ.strokeStyle=C.color.parse(AN.color).scale("a",0.5).toString();var AM=C.color.parse(AN.color).scale("a",0.5).toString();var AL=AN.bars.align=="left"?0:-AN.bars.barWidth/2;AB(AK[0],AK[1],AK[2]||0,AL,AL+AN.bars.barWidth,0,function(){return AM},AN.xaxis,AN.yaxis,AJ,AN.bars.horizontal)}function R(AM,AL,AQ,AO){if(typeof AM=="string"){return AM}else{var AP=Y.createLinearGradient(0,AQ,0,AL);for(var AN=0,AK=AM.colors.length;AN<AK;++AN){var AR=AM.colors[AN];if(typeof AR!="string"){AR=C.color.parse(AO).scale("rgb",AR.brightness);AR.a*=AR.opacity;AR=AR.toString()}AP.addColorStop(AN/(AK-1),AR)}return AP}}}C.plot=function(G,E,D){var F=new B(C(G),E,D,C.plot.plugins);return F};C.plot.plugins=[];C.plot.formatDate=function(H,E,G){var L=function(N){N=""+N;return N.length==1?"0"+N:N};var D=[];var M=false;var K=H.getUTCHours();var I=K<12;if(G==null){G=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}if(E.search(/%p|%P/)!=-1){if(K>12){K=K-12}else{if(K==0){K=12}}}for(var F=0;F<E.length;++F){var J=E.charAt(F);if(M){switch(J){case"h":J=""+K;break;case"H":J=L(K);break;case"M":J=L(H.getUTCMinutes());break;case"S":J=L(H.getUTCSeconds());break;case"d":J=""+H.getUTCDate();break;case"m":J=""+(H.getUTCMonth()+1);break;case"y":J=""+H.getUTCFullYear();break;case"b":J=""+G[H.getUTCMonth()];break;case"p":J=(I)?("am"):("pm");break;case"P":J=(I)?("AM"):("PM");break}D.push(J);M=false}else{if(J=="%"){M=true}else{D.push(J)}}}return D.join("")};function A(E,D){return D*Math.floor(E/D)}})(jQuery);
1
+ (function(B){B.color={};B.color.make=function(F,E,C,D){var G={};G.r=F||0;G.g=E||0;G.b=C||0;G.a=D!=null?D:1;G.add=function(J,I){for(var H=0;H<J.length;++H){G[J.charAt(H)]+=I}return G.normalize()};G.scale=function(J,I){for(var H=0;H<J.length;++H){G[J.charAt(H)]*=I}return G.normalize()};G.toString=function(){if(G.a>=1){return"rgb("+[G.r,G.g,G.b].join(",")+")"}else{return"rgba("+[G.r,G.g,G.b,G.a].join(",")+")"}};G.normalize=function(){function H(J,K,I){return K<J?J:(K>I?I:K)}G.r=H(0,parseInt(G.r),255);G.g=H(0,parseInt(G.g),255);G.b=H(0,parseInt(G.b),255);G.a=H(0,G.a,1);return G};G.clone=function(){return B.color.make(G.r,G.b,G.g,G.a)};return G.normalize()};B.color.extract=function(D,C){var E;do{E=D.css(C).toLowerCase();if(E!=""&&E!="transparent"){break}D=D.parent()}while(!B.nodeName(D.get(0),"body"));if(E=="rgba(0, 0, 0, 0)"){E="transparent"}return B.color.parse(E)};B.color.parse=function(F){var E,C=B.color.make;if(E=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10))}if(E=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10),parseFloat(E[4]))}if(E=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55)}if(E=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55,parseFloat(E[4]))}if(E=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(F)){return C(parseInt(E[1],16),parseInt(E[2],16),parseInt(E[3],16))}if(E=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(F)){return C(parseInt(E[1]+E[1],16),parseInt(E[2]+E[2],16),parseInt(E[3]+E[3],16))}var D=B.trim(F).toLowerCase();if(D=="transparent"){return C(255,255,255,0)}else{E=A[D]||[0,0,0];return C(E[0],E[1],E[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],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],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);
2
+ (function($) {
3
+ function Plot(placeholder, data_, options_, plugins) {
4
+ var series = [],
5
+ options = {
6
+ colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"],
7
+ legend: {
8
+ show: true,
9
+ noColumns: 1,
10
+ labelFormatter: null,
11
+ labelBoxBorderColor: "#ccc",
12
+ container: null,
13
+ position: "ne",
14
+ margin: 5,
15
+ backgroundColor: null,
16
+ backgroundOpacity: 0.85
17
+ },
18
+ xaxis: {
19
+ show: null,
20
+ position: "bottom",
21
+ mode: null,
22
+ font: null,
23
+ color: null,
24
+ tickColor: null,
25
+ transform: null,
26
+ inverseTransform: null,
27
+ min: null,
28
+ max: null,
29
+ autoscaleMargin: null,
30
+ ticks: null,
31
+ tickFormatter: null,
32
+ labelWidth: null,
33
+ labelHeight: null,
34
+ reserveSpace: null,
35
+ tickLength: null,
36
+ alignTicksWithAxis: null,
37
+ tickDecimals: null,
38
+ tickSize: null,
39
+ minTickSize: null,
40
+ monthNames: null,
41
+ timeformat: null,
42
+ twelveHourClock: false
43
+ },
44
+ yaxis: {
45
+ autoscaleMargin: 0.02,
46
+ position: "left"
47
+ },
48
+ xaxes: [],
49
+ yaxes: [],
50
+ series: {
51
+ points: {
52
+ show: false,
53
+ radius: 3,
54
+ lineWidth: 2,
55
+ fill: true,
56
+ fillColor: "#ffffff",
57
+ symbol: "circle"
58
+ },
59
+ lines: {
60
+ lineWidth: 2,
61
+ fill: false,
62
+ fillColor: null,
63
+ steps: false
64
+ },
65
+ bars: {
66
+ show: false,
67
+ lineWidth: 2,
68
+ barWidth: 1,
69
+ fill: true,
70
+ fillColor: null,
71
+ align: "left",
72
+ horizontal: false
73
+ },
74
+ shadowSize: 3
75
+ },
76
+ grid: {
77
+ show: true,
78
+ aboveData: false,
79
+ color: "#545454",
80
+ backgroundColor: null,
81
+ borderColor: null,
82
+ tickColor: null,
83
+ labelMargin: 5,
84
+ axisMargin: 8,
85
+ borderWidth: 2,
86
+ minBorderMargin: null,
87
+ markings: null,
88
+ markingsColor: "#f4f4f4",
89
+ markingsLineWidth: 2,
90
+ clickable: false,
91
+ hoverable: false,
92
+ autoHighlight: true,
93
+ mouseActiveRadius: 10
94
+ },
95
+ interaction: {
96
+ redrawOverlayInterval: 1000/60
97
+ },
98
+ hooks: {}
99
+ },
100
+ canvas = null,
101
+ overlay = null,
102
+ eventHolder = null,
103
+ ctx = null, octx = null,
104
+ xaxes = [], yaxes = [],
105
+ plotOffset = { left: 0, right: 0, top: 0, bottom: 0},
106
+ canvasWidth = 0, canvasHeight = 0,
107
+ plotWidth = 0, plotHeight = 0,
108
+ hooks = {
109
+ processOptions: [],
110
+ processRawData: [],
111
+ processDatapoints: [],
112
+ drawSeries: [],
113
+ draw: [],
114
+ bindEvents: [],
115
+ drawOverlay: [],
116
+ shutdown: []
117
+ },
118
+ plot = this;
119
+ plot.setData = setData;
120
+ plot.setupGrid = setupGrid;
121
+ plot.draw = draw;
122
+ plot.getPlaceholder = function() { return placeholder; };
123
+ plot.getCanvas = function() { return canvas; };
124
+ plot.getPlotOffset = function() { return plotOffset; };
125
+ plot.width = function () { return plotWidth; };
126
+ plot.height = function () { return plotHeight; };
127
+ plot.offset = function () {
128
+ var o = eventHolder.offset();
129
+ o.left += plotOffset.left;
130
+ o.top += plotOffset.top;
131
+ return o;
132
+ };
133
+ plot.getData = function () { return series; };
134
+ plot.getAxes = function () {
135
+ var res = {}, i;
136
+ $.each(xaxes.concat(yaxes), function (_, axis) {
137
+ if (axis)
138
+ res[axis.direction + (axis.n != 1 ? axis.n : "") + "axis"] = axis;
139
+ });
140
+ return res;
141
+ };
142
+ plot.getXAxes = function () { return xaxes; };
143
+ plot.getYAxes = function () { return yaxes; };
144
+ plot.c2p = canvasToAxisCoords;
145
+ plot.p2c = axisToCanvasCoords;
146
+ plot.getOptions = function () { return options; };
147
+ plot.highlight = highlight;
148
+ plot.unhighlight = unhighlight;
149
+ plot.triggerRedrawOverlay = triggerRedrawOverlay;
150
+ plot.pointOffset = function(point) {
151
+ return {
152
+ left: parseInt(xaxes[axisNumber(point, "x") - 1].p2c(+point.x) + plotOffset.left),
153
+ top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top)
154
+ };
155
+ };
156
+ plot.shutdown = shutdown;
157
+ plot.resize = function () {
158
+ getCanvasDimensions();
159
+ resizeCanvas(canvas);
160
+ resizeCanvas(overlay);
161
+ };
162
+ plot.hooks = hooks;
163
+ initPlugins(plot);
164
+ parseOptions(options_);
165
+ setupCanvases();
166
+ setData(data_);
167
+ setupGrid();
168
+ draw();
169
+ bindEvents();
170
+ function executeHooks(hook, args) {
171
+ args = [plot].concat(args);
172
+ for (var i = 0; i < hook.length; ++i)
173
+ hook[i].apply(this, args);
174
+ }
175
+ function initPlugins() {
176
+ for (var i = 0; i < plugins.length; ++i) {
177
+ var p = plugins[i];
178
+ p.init(plot);
179
+ if (p.options)
180
+ $.extend(true, options, p.options);
181
+ }
182
+ }
183
+ function parseOptions(opts) {
184
+ var i;
185
+ $.extend(true, options, opts);
186
+ if (options.xaxis.color == null)
187
+ options.xaxis.color = options.grid.color;
188
+ if (options.yaxis.color == null)
189
+ options.yaxis.color = options.grid.color;
190
+ if (options.xaxis.tickColor == null)
191
+ options.xaxis.tickColor = options.grid.tickColor;
192
+ if (options.yaxis.tickColor == null)
193
+ options.yaxis.tickColor = options.grid.tickColor;
194
+ if (options.grid.borderColor == null)
195
+ options.grid.borderColor = options.grid.color;
196
+ if (options.grid.tickColor == null)
197
+ options.grid.tickColor = $.color.parse(options.grid.color).scale('a', 0.22).toString();
198
+ for (i = 0; i < Math.max(1, options.xaxes.length); ++i)
199
+ options.xaxes[i] = $.extend(true, {}, options.xaxis, options.xaxes[i]);
200
+ for (i = 0; i < Math.max(1, options.yaxes.length); ++i)
201
+ options.yaxes[i] = $.extend(true, {}, options.yaxis, options.yaxes[i]);
202
+ if (options.xaxis.noTicks && options.xaxis.ticks == null)
203
+ options.xaxis.ticks = options.xaxis.noTicks;
204
+ if (options.yaxis.noTicks && options.yaxis.ticks == null)
205
+ options.yaxis.ticks = options.yaxis.noTicks;
206
+ if (options.x2axis) {
207
+ options.xaxes[1] = $.extend(true, {}, options.xaxis, options.x2axis);
208
+ options.xaxes[1].position = "top";
209
+ }
210
+ if (options.y2axis) {
211
+ options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis);
212
+ options.yaxes[1].position = "right";
213
+ }
214
+ if (options.grid.coloredAreas)
215
+ options.grid.markings = options.grid.coloredAreas;
216
+ if (options.grid.coloredAreasColor)
217
+ options.grid.markingsColor = options.grid.coloredAreasColor;
218
+ if (options.lines)
219
+ $.extend(true, options.series.lines, options.lines);
220
+ if (options.points)
221
+ $.extend(true, options.series.points, options.points);
222
+ if (options.bars)
223
+ $.extend(true, options.series.bars, options.bars);
224
+ if (options.shadowSize != null)
225
+ options.series.shadowSize = options.shadowSize;
226
+ for (i = 0; i < options.xaxes.length; ++i)
227
+ getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i];
228
+ for (i = 0; i < options.yaxes.length; ++i)
229
+ getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i];
230
+ for (var n in hooks)
231
+ if (options.hooks[n] && options.hooks[n].length)
232
+ hooks[n] = hooks[n].concat(options.hooks[n]);
233
+ executeHooks(hooks.processOptions, [options]);
234
+ }
235
+ function setData(d) {
236
+ series = parseData(d);
237
+ fillInSeriesOptions();
238
+ processData();
239
+ }
240
+ function parseData(d) {
241
+ var res = [];
242
+ for (var i = 0; i < d.length; ++i) {
243
+ var s = $.extend(true, {}, options.series);
244
+ if (d[i].data != null) {
245
+ s.data = d[i].data;
246
+ delete d[i].data;
247
+ $.extend(true, s, d[i]);
248
+ d[i].data = s.data;
249
+ }
250
+ else
251
+ s.data = d[i];
252
+ res.push(s);
253
+ }
254
+ return res;
255
+ }
256
+ function axisNumber(obj, coord) {
257
+ var a = obj[coord + "axis"];
258
+ if (typeof a == "object")
259
+ a = a.n;
260
+ if (typeof a != "number")
261
+ a = 1;
262
+ return a;
263
+ }
264
+ function allAxes() {
265
+ return $.grep(xaxes.concat(yaxes), function (a) { return a; });
266
+ }
267
+ function canvasToAxisCoords(pos) {
268
+ var res = {}, i, axis;
269
+ for (i = 0; i < xaxes.length; ++i) {
270
+ axis = xaxes[i];
271
+ if (axis && axis.used)
272
+ res["x" + axis.n] = axis.c2p(pos.left);
273
+ }
274
+ for (i = 0; i < yaxes.length; ++i) {
275
+ axis = yaxes[i];
276
+ if (axis && axis.used)
277
+ res["y" + axis.n] = axis.c2p(pos.top);
278
+ }
279
+ if (res.x1 !== undefined)
280
+ res.x = res.x1;
281
+ if (res.y1 !== undefined)
282
+ res.y = res.y1;
283
+ return res;
284
+ }
285
+ function axisToCanvasCoords(pos) {
286
+ var res = {}, i, axis, key;
287
+ for (i = 0; i < xaxes.length; ++i) {
288
+ axis = xaxes[i];
289
+ if (axis && axis.used) {
290
+ key = "x" + axis.n;
291
+ if (pos[key] == null && axis.n == 1)
292
+ key = "x";
293
+ if (pos[key] != null) {
294
+ res.left = axis.p2c(pos[key]);
295
+ break;
296
+ }
297
+ }
298
+ }
299
+ for (i = 0; i < yaxes.length; ++i) {
300
+ axis = yaxes[i];
301
+ if (axis && axis.used) {
302
+ key = "y" + axis.n;
303
+ if (pos[key] == null && axis.n == 1)
304
+ key = "y";
305
+ if (pos[key] != null) {
306
+ res.top = axis.p2c(pos[key]);
307
+ break;
308
+ }
309
+ }
310
+ }
311
+ return res;
312
+ }
313
+ function getOrCreateAxis(axes, number) {
314
+ if (!axes[number - 1])
315
+ axes[number - 1] = {
316
+ n: number,
317
+ direction: axes == xaxes ? "x" : "y",
318
+ options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis)
319
+ };
320
+ return axes[number - 1];
321
+ }
322
+ function fillInSeriesOptions() {
323
+ var i;
324
+ var neededColors = series.length,
325
+ usedColors = [],
326
+ assignedColors = [];
327
+ for (i = 0; i < series.length; ++i) {
328
+ var sc = series[i].color;
329
+ if (sc != null) {
330
+ --neededColors;
331
+ if (typeof sc == "number")
332
+ assignedColors.push(sc);
333
+ else
334
+ usedColors.push($.color.parse(series[i].color));
335
+ }
336
+ }
337
+ for (i = 0; i < assignedColors.length; ++i) {
338
+ neededColors = Math.max(neededColors, assignedColors[i] + 1);
339
+ }
340
+ var colors = [], variation = 0;
341
+ i = 0;
342
+ while (colors.length < neededColors) {
343
+ var c;
344
+ if (options.colors.length == i)
345
+ c = $.color.make(100, 100, 100);
346
+ else
347
+ c = $.color.parse(options.colors[i]);
348
+ var sign = variation % 2 == 1 ? -1 : 1;
349
+ c.scale('rgb', 1 + sign * Math.ceil(variation / 2) * 0.2)
350
+ colors.push(c);
351
+ ++i;
352
+ if (i >= options.colors.length) {
353
+ i = 0;
354
+ ++variation;
355
+ }
356
+ }
357
+ var colori = 0, s;
358
+ for (i = 0; i < series.length; ++i) {
359
+ s = series[i];
360
+ if (s.color == null) {
361
+ s.color = colors[colori].toString();
362
+ ++colori;
363
+ }
364
+ else if (typeof s.color == "number")
365
+ s.color = colors[s.color].toString();
366
+ if (s.lines.show == null) {
367
+ var v, show = true;
368
+ for (v in s)
369
+ if (s[v] && s[v].show) {
370
+ show = false;
371
+ break;
372
+ }
373
+ if (show)
374
+ s.lines.show = true;
375
+ }
376
+ s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x"));
377
+ s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y"));
378
+ }
379
+ }
380
+ function processData() {
381
+ var topSentry = Number.POSITIVE_INFINITY,
382
+ bottomSentry = Number.NEGATIVE_INFINITY,
383
+ fakeInfinity = Number.MAX_VALUE,
384
+ i, j, k, m, length,
385
+ s, points, ps, x, y, axis, val, f, p;
386
+ function updateAxis(axis, min, max) {
387
+ if (min < axis.datamin && min != -fakeInfinity)
388
+ axis.datamin = min;
389
+ if (max > axis.datamax && max != fakeInfinity)
390
+ axis.datamax = max;
391
+ }
392
+ $.each(allAxes(), function (_, axis) {
393
+ axis.datamin = topSentry;
394
+ axis.datamax = bottomSentry;
395
+ axis.used = false;
396
+ });
397
+ for (i = 0; i < series.length; ++i) {
398
+ s = series[i];
399
+ s.datapoints = { points: [] };
400
+ executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]);
401
+ }
402
+ for (i = 0; i < series.length; ++i) {
403
+ s = series[i];
404
+ var data = s.data, format = s.datapoints.format;
405
+ if (!format) {
406
+ format = [];
407
+ format.push({ x: true, number: true, required: true });
408
+ format.push({ y: true, number: true, required: true });
409
+ if (s.bars.show || (s.lines.show && s.lines.fill)) {
410
+ format.push({ y: true, number: true, required: false, defaultValue: 0 });
411
+ if (s.bars.horizontal) {
412
+ delete format[format.length - 1].y;
413
+ format[format.length - 1].x = true;
414
+ }
415
+ }
416
+ s.datapoints.format = format;
417
+ }
418
+ if (s.datapoints.pointsize != null)
419
+ continue;
420
+ s.datapoints.pointsize = format.length;
421
+ ps = s.datapoints.pointsize;
422
+ points = s.datapoints.points;
423
+ insertSteps = s.lines.show && s.lines.steps;
424
+ s.xaxis.used = s.yaxis.used = true;
425
+ for (j = k = 0; j < data.length; ++j, k += ps) {
426
+ p = data[j];
427
+ var nullify = p == null;
428
+ if (!nullify) {
429
+ for (m = 0; m < ps; ++m) {
430
+ val = p[m];
431
+ f = format[m];
432
+ if (f) {
433
+ if (f.number && val != null) {
434
+ val = +val;
435
+ if (isNaN(val))
436
+ val = null;
437
+ else if (val == Infinity)
438
+ val = fakeInfinity;
439
+ else if (val == -Infinity)
440
+ val = -fakeInfinity;
441
+ }
442
+ if (val == null) {
443
+ if (f.required)
444
+ nullify = true;
445
+ if (f.defaultValue != null)
446
+ val = f.defaultValue;
447
+ }
448
+ }
449
+ points[k + m] = val;
450
+ }
451
+ }
452
+ if (nullify) {
453
+ for (m = 0; m < ps; ++m) {
454
+ val = points[k + m];
455
+ if (val != null) {
456
+ f = format[m];
457
+ if (f.x)
458
+ updateAxis(s.xaxis, val, val);
459
+ if (f.y)
460
+ updateAxis(s.yaxis, val, val);
461
+ }
462
+ points[k + m] = null;
463
+ }
464
+ }
465
+ else {
466
+ if (insertSteps && k > 0
467
+ && points[k - ps] != null
468
+ && points[k - ps] != points[k]
469
+ && points[k - ps + 1] != points[k + 1]) {
470
+ for (m = 0; m < ps; ++m)
471
+ points[k + ps + m] = points[k + m];
472
+ points[k + 1] = points[k - ps + 1];
473
+ k += ps;
474
+ }
475
+ }
476
+ }
477
+ }
478
+ for (i = 0; i < series.length; ++i) {
479
+ s = series[i];
480
+ executeHooks(hooks.processDatapoints, [ s, s.datapoints]);
481
+ }
482
+ for (i = 0; i < series.length; ++i) {
483
+ s = series[i];
484
+ points = s.datapoints.points,
485
+ ps = s.datapoints.pointsize;
486
+ var xmin = topSentry, ymin = topSentry,
487
+ xmax = bottomSentry, ymax = bottomSentry;
488
+ for (j = 0; j < points.length; j += ps) {
489
+ if (points[j] == null)
490
+ continue;
491
+ for (m = 0; m < ps; ++m) {
492
+ val = points[j + m];
493
+ f = format[m];
494
+ if (!f || val == fakeInfinity || val == -fakeInfinity)
495
+ continue;
496
+ if (f.x) {
497
+ if (val < xmin)
498
+ xmin = val;
499
+ if (val > xmax)
500
+ xmax = val;
501
+ }
502
+ if (f.y) {
503
+ if (val < ymin)
504
+ ymin = val;
505
+ if (val > ymax)
506
+ ymax = val;
507
+ }
508
+ }
509
+ }
510
+ if (s.bars.show) {
511
+ var delta = s.bars.align == "left" ? 0 : -s.bars.barWidth/2;
512
+ if (s.bars.horizontal) {
513
+ ymin += delta;
514
+ ymax += delta + s.bars.barWidth;
515
+ }
516
+ else {
517
+ xmin += delta;
518
+ xmax += delta + s.bars.barWidth;
519
+ }
520
+ }
521
+ updateAxis(s.xaxis, xmin, xmax);
522
+ updateAxis(s.yaxis, ymin, ymax);
523
+ }
524
+ $.each(allAxes(), function (_, axis) {
525
+ if (axis.datamin == topSentry)
526
+ axis.datamin = null;
527
+ if (axis.datamax == bottomSentry)
528
+ axis.datamax = null;
529
+ });
530
+ }
531
+ function makeCanvas(skipPositioning, cls) {
532
+ var c = document.createElement('canvas');
533
+ c.className = cls;
534
+ c.width = canvasWidth;
535
+ c.height = canvasHeight;
536
+ if (!skipPositioning)
537
+ $(c).css({ position: 'absolute', left: 0, top: 0 });
538
+ $(c).appendTo(placeholder);
539
+ if (!c.getContext)
540
+ c = window.G_vmlCanvasManager.initElement(c);
541
+ c.getContext("2d").save();
542
+ return c;
543
+ }
544
+ function getCanvasDimensions() {
545
+ canvasWidth = placeholder.width();
546
+ canvasHeight = placeholder.height();
547
+ if (canvasWidth <= 0 || canvasHeight <= 0)
548
+ throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight;
549
+ }
550
+ function resizeCanvas(c) {
551
+ if (c.width != canvasWidth)
552
+ c.width = canvasWidth;
553
+ if (c.height != canvasHeight)
554
+ c.height = canvasHeight;
555
+ var cctx = c.getContext("2d");
556
+ cctx.restore();
557
+ cctx.save();
558
+ }
559
+ function setupCanvases() {
560
+ var reused,
561
+ existingCanvas = placeholder.children("canvas.base"),
562
+ existingOverlay = placeholder.children("canvas.overlay");
563
+ if (existingCanvas.length == 0 || existingOverlay == 0) {
564
+ placeholder.html("");
565
+ placeholder.css({ padding: 0 });
566
+ if (placeholder.css("position") == 'static')
567
+ placeholder.css("position", "relative");
568
+ getCanvasDimensions();
569
+ canvas = makeCanvas(true, "base");
570
+ overlay = makeCanvas(false, "overlay");
571
+ reused = false;
572
+ }
573
+ else {
574
+ canvas = existingCanvas.get(0);
575
+ overlay = existingOverlay.get(0);
576
+ reused = true;
577
+ }
578
+ ctx = canvas.getContext("2d");
579
+ octx = overlay.getContext("2d");
580
+ eventHolder = $(overlay);
581
+ if (reused) {
582
+ placeholder.data("plot").shutdown();
583
+ plot.resize();
584
+ octx.clearRect(0, 0, canvasWidth, canvasHeight);
585
+ eventHolder.unbind();
586
+ placeholder.children().not([canvas, overlay]).remove();
587
+ }
588
+ placeholder.data("plot", plot);
589
+ }
590
+ function bindEvents() {
591
+ if (options.grid.hoverable) {
592
+ eventHolder.mousemove(onMouseMove);
593
+ eventHolder.mouseleave(onMouseLeave);
594
+ }
595
+ if (options.grid.clickable)
596
+ eventHolder.click(onClick);
597
+ executeHooks(hooks.bindEvents, [eventHolder]);
598
+ }
599
+ function shutdown() {
600
+ if (redrawTimeout)
601
+ clearTimeout(redrawTimeout);
602
+ eventHolder.unbind("mousemove", onMouseMove);
603
+ eventHolder.unbind("mouseleave", onMouseLeave);
604
+ eventHolder.unbind("click", onClick);
605
+ executeHooks(hooks.shutdown, [eventHolder]);
606
+ }
607
+ function setTransformationHelpers(axis) {
608
+ function identity(x) { return x; }
609
+ var s, m, t = axis.options.transform || identity,
610
+ it = axis.options.inverseTransform;
611
+ if (axis.direction == "x") {
612
+ s = axis.scale = plotWidth / Math.abs(t(axis.max) - t(axis.min));
613
+ m = Math.min(t(axis.max), t(axis.min));
614
+ }
615
+ else {
616
+ s = axis.scale = plotHeight / Math.abs(t(axis.max) - t(axis.min));
617
+ s = -s;
618
+ m = Math.max(t(axis.max), t(axis.min));
619
+ }
620
+ if (t == identity)
621
+ axis.p2c = function (p) { return (p - m) * s; };
622
+ else
623
+ axis.p2c = function (p) { return (t(p) - m) * s; };
624
+ if (!it)
625
+ axis.c2p = function (c) { return m + c / s; };
626
+ else
627
+ axis.c2p = function (c) { return it(m + c / s); };
628
+ }
629
+ function measureTickLabels(axis) {
630
+ var opts = axis.options, ticks = axis.ticks || [],
631
+ axisw = opts.labelWidth || 0, axish = opts.labelHeight || 0,
632
+ f = axis.font;
633
+ if (opts.labelWidth == null || opts.labelHeight == null) {
634
+ ctx.save();
635
+ ctx.font = f.style + " " + f.variant + " " + f.weight + " " + f.size + "px '" + f.family + "'";
636
+ for (var i = 0; i < ticks.length; ++i) {
637
+ var t = ticks[i];
638
+ t.lines = [];
639
+ t.width = t.height = 0;
640
+ if (!t.label)
641
+ continue;
642
+ var lines = t.label.replace(/<br ?\/?>|\r\n|\r/g, "\n").split("\n");
643
+ for (var j = 0; j < lines.length; ++j) {
644
+ var line = { text: lines[j] },
645
+ m = ctx.measureText(line.text);
646
+ line.width = m.width;
647
+ line.height = m.height != null ? m.height : f.size;
648
+ line.height += Math.round(f.size * 0.15);
649
+ t.width = Math.max(line.width, t.width);
650
+ t.height += line.height;
651
+ t.lines.push(line);
652
+ }
653
+ if (opts.labelWidth == null)
654
+ axisw = Math.max(axisw, t.width);
655
+ if (opts.labelHeight == null)
656
+ axish = Math.max(axish, t.height);
657
+ }
658
+ ctx.restore();
659
+ }
660
+ axis.labelWidth = Math.ceil(axisw);
661
+ axis.labelHeight = Math.ceil(axish);
662
+ }
663
+ function allocateAxisBoxFirstPhase(axis) {
664
+ var lw = axis.labelWidth,
665
+ lh = axis.labelHeight,
666
+ pos = axis.options.position,
667
+ tickLength = axis.options.tickLength,
668
+ axisMargin = options.grid.axisMargin,
669
+ padding = options.grid.labelMargin,
670
+ all = axis.direction == "x" ? xaxes : yaxes,
671
+ index;
672
+ var samePosition = $.grep(all, function (a) {
673
+ return a && a.options.position == pos && a.reserveSpace;
674
+ });
675
+ if ($.inArray(axis, samePosition) == samePosition.length - 1)
676
+ axisMargin = 0;
677
+ if (tickLength == null) {
678
+ var sameDirection = $.grep(all, function (a) {
679
+ return a && a.reserveSpace;
680
+ });
681
+ var innermost = $.inArray(axis, sameDirection) == 0;
682
+ if (innermost)
683
+ tickLength = "full"
684
+ else
685
+ tickLength = 5;
686
+ }
687
+ if (!isNaN(+tickLength))
688
+ padding += +tickLength;
689
+ if (axis.direction == "x") {
690
+ lh += padding;
691
+ if (pos == "bottom") {
692
+ plotOffset.bottom += lh + axisMargin;
693
+ axis.box = { top: canvasHeight - plotOffset.bottom, height: lh };
694
+ }
695
+ else {
696
+ axis.box = { top: plotOffset.top + axisMargin, height: lh };
697
+ plotOffset.top += lh + axisMargin;
698
+ }
699
+ }
700
+ else {
701
+ lw += padding;
702
+ if (pos == "left") {
703
+ axis.box = { left: plotOffset.left + axisMargin, width: lw };
704
+ plotOffset.left += lw + axisMargin;
705
+ }
706
+ else {
707
+ plotOffset.right += lw + axisMargin;
708
+ axis.box = { left: canvasWidth - plotOffset.right, width: lw };
709
+ }
710
+ }
711
+ axis.position = pos;
712
+ axis.tickLength = tickLength;
713
+ axis.box.padding = padding;
714
+ axis.innermost = innermost;
715
+ }
716
+ function allocateAxisBoxSecondPhase(axis) {
717
+ if (axis.direction == "x") {
718
+ axis.box.left = plotOffset.left - axis.labelWidth / 2;
719
+ axis.box.width = canvasWidth - plotOffset.left - plotOffset.right + axis.labelWidth;
720
+ }
721
+ else {
722
+ axis.box.top = plotOffset.top - axis.labelHeight / 2;
723
+ axis.box.height = canvasHeight - plotOffset.bottom - plotOffset.top + axis.labelHeight;
724
+ }
725
+ }
726
+ function adjustLayoutForThingsStickingOut() {
727
+ var minMargin = options.grid.minBorderMargin,
728
+ margins = { x: 0, y: 0 }, i, axis;
729
+ if (minMargin == null) {
730
+ minMargin = 0;
731
+ for (i = 0; i < series.length; ++i)
732
+ minMargin = Math.max(minMargin, 2 * (series[i].points.radius + series[i].points.lineWidth/2));
733
+ }
734
+ margins.x = margins.y = minMargin;
735
+ $.each(allAxes(), function (_, axis) {
736
+ var dir = axis.direction;
737
+ if (axis.reserveSpace)
738
+ margins[dir] = Math.max(margins[dir], (dir == "x" ? axis.labelWidth : axis.labelHeight) / 2);
739
+ });
740
+ plotOffset.left = Math.max(margins.x, plotOffset.left);
741
+ plotOffset.right = Math.max(margins.x, plotOffset.right);
742
+ plotOffset.top = Math.max(margins.y, plotOffset.top);
743
+ plotOffset.bottom = Math.max(margins.y, plotOffset.bottom);
744
+ }
745
+ function setupGrid() {
746
+ var i, axes = allAxes(), showGrid = options.grid.show;
747
+ for (var a in plotOffset)
748
+ plotOffset[a] = showGrid ? options.grid.borderWidth : 0;
749
+ $.each(axes, function (_, axis) {
750
+ axis.show = axis.options.show;
751
+ if (axis.show == null)
752
+ axis.show = axis.used;
753
+ axis.reserveSpace = axis.show || axis.options.reserveSpace;
754
+ setRange(axis);
755
+ });
756
+ if (showGrid) {
757
+ var fontDefaults = {
758
+ style: placeholder.css("font-style"),
759
+ size: Math.round(0.8 * (+placeholder.css("font-size").replace("px", "") || 13)),
760
+ variant: placeholder.css("font-variant"),
761
+ weight: placeholder.css("font-weight"),
762
+ family: placeholder.css("font-family")
763
+ };
764
+ var allocatedAxes = $.grep(axes, function (axis) { return axis.reserveSpace; });
765
+ $.each(allocatedAxes, function (_, axis) {
766
+ setupTickGeneration(axis);
767
+ setTicks(axis);
768
+ snapRangeToTicks(axis, axis.ticks);
769
+ axis.font = $.extend({}, fontDefaults, axis.options.font);
770
+ measureTickLabels(axis);
771
+ });
772
+ for (i = allocatedAxes.length - 1; i >= 0; --i)
773
+ allocateAxisBoxFirstPhase(allocatedAxes[i]);
774
+ adjustLayoutForThingsStickingOut();
775
+ $.each(allocatedAxes, function (_, axis) {
776
+ allocateAxisBoxSecondPhase(axis);
777
+ });
778
+ }
779
+ plotWidth = canvasWidth - plotOffset.left - plotOffset.right;
780
+ plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top;
781
+ $.each(axes, function (_, axis) {
782
+ setTransformationHelpers(axis);
783
+ });
784
+ insertLegend();
785
+ }
786
+ function setRange(axis) {
787
+ var opts = axis.options,
788
+ min = +(opts.min != null ? opts.min : axis.datamin),
789
+ max = +(opts.max != null ? opts.max : axis.datamax),
790
+ delta = max - min;
791
+ if (delta == 0.0) {
792
+ var widen = max == 0 ? 1 : 0.01;
793
+ if (opts.min == null)
794
+ min -= widen;
795
+ if (opts.max == null || opts.min != null)
796
+ max += widen;
797
+ }
798
+ else {
799
+ var margin = opts.autoscaleMargin;
800
+ if (margin != null) {
801
+ if (opts.min == null) {
802
+ min -= delta * margin;
803
+ if (min < 0 && axis.datamin != null && axis.datamin >= 0)
804
+ min = 0;
805
+ }
806
+ if (opts.max == null) {
807
+ max += delta * margin;
808
+ if (max > 0 && axis.datamax != null && axis.datamax <= 0)
809
+ max = 0;
810
+ }
811
+ }
812
+ }
813
+ axis.min = min;
814
+ axis.max = max;
815
+ }
816
+ function setupTickGeneration(axis) {
817
+ var opts = axis.options;
818
+ var noTicks;
819
+ if (typeof opts.ticks == "number" && opts.ticks > 0)
820
+ noTicks = opts.ticks;
821
+ else
822
+ noTicks = 0.3 * Math.sqrt(axis.direction == "x" ? canvasWidth : canvasHeight);
823
+ var delta = (axis.max - axis.min) / noTicks,
824
+ size, generator, unit, formatter, i, magn, norm;
825
+ if (opts.mode == "time") {
826
+ var timeUnitSize = {
827
+ "second": 1000,
828
+ "minute": 60 * 1000,
829
+ "hour": 60 * 60 * 1000,
830
+ "day": 24 * 60 * 60 * 1000,
831
+ "month": 30 * 24 * 60 * 60 * 1000,
832
+ "year": 365.2425 * 24 * 60 * 60 * 1000
833
+ };
834
+ var spec = [
835
+ [1, "second"], [2, "second"], [5, "second"], [10, "second"],
836
+ [30, "second"],
837
+ [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"],
838
+ [30, "minute"],
839
+ [1, "hour"], [2, "hour"], [4, "hour"],
840
+ [8, "hour"], [12, "hour"],
841
+ [1, "day"], [2, "day"], [3, "day"],
842
+ [0.25, "month"], [0.5, "month"], [1, "month"],
843
+ [2, "month"], [3, "month"], [6, "month"],
844
+ [1, "year"]
845
+ ];
846
+ var minSize = 0;
847
+ if (opts.minTickSize != null) {
848
+ if (typeof opts.tickSize == "number")
849
+ minSize = opts.tickSize;
850
+ else
851
+ minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]];
852
+ }
853
+ for (var i = 0; i < spec.length - 1; ++i)
854
+ if (delta < (spec[i][0] * timeUnitSize[spec[i][1]]
855
+ + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2
856
+ && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize)
857
+ break;
858
+ size = spec[i][0];
859
+ unit = spec[i][1];
860
+ if (unit == "year") {
861
+ magn = Math.pow(10, Math.floor(Math.log(delta / timeUnitSize.year) / Math.LN10));
862
+ norm = (delta / timeUnitSize.year) / magn;
863
+ if (norm < 1.5)
864
+ size = 1;
865
+ else if (norm < 3)
866
+ size = 2;
867
+ else if (norm < 7.5)
868
+ size = 5;
869
+ else
870
+ size = 10;
871
+ size *= magn;
872
+ }
873
+ axis.tickSize = opts.tickSize || [size, unit];
874
+ generator = function(axis) {
875
+ var ticks = [],
876
+ tickSize = axis.tickSize[0], unit = axis.tickSize[1],
877
+ d = new Date(axis.min);
878
+ var step = tickSize * timeUnitSize[unit];
879
+ if (unit == "second")
880
+ d.setUTCSeconds(floorInBase(d.getUTCSeconds(), tickSize));
881
+ if (unit == "minute")
882
+ d.setUTCMinutes(floorInBase(d.getUTCMinutes(), tickSize));
883
+ if (unit == "hour")
884
+ d.setUTCHours(floorInBase(d.getUTCHours(), tickSize));
885
+ if (unit == "month")
886
+ d.setUTCMonth(floorInBase(d.getUTCMonth(), tickSize));
887
+ if (unit == "year")
888
+ d.setUTCFullYear(floorInBase(d.getUTCFullYear(), tickSize));
889
+ d.setUTCMilliseconds(0);
890
+ if (step >= timeUnitSize.minute)
891
+ d.setUTCSeconds(0);
892
+ if (step >= timeUnitSize.hour)
893
+ d.setUTCMinutes(0);
894
+ if (step >= timeUnitSize.day)
895
+ d.setUTCHours(0);
896
+ if (step >= timeUnitSize.day * 4)
897
+ d.setUTCDate(1);
898
+ if (step >= timeUnitSize.year)
899
+ d.setUTCMonth(0);
900
+ var carry = 0, v = Number.NaN, prev;
901
+ do {
902
+ prev = v;
903
+ v = d.getTime();
904
+ ticks.push(v);
905
+ if (unit == "month") {
906
+ if (tickSize < 1) {
907
+ d.setUTCDate(1);
908
+ var start = d.getTime();
909
+ d.setUTCMonth(d.getUTCMonth() + 1);
910
+ var end = d.getTime();
911
+ d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
912
+ carry = d.getUTCHours();
913
+ d.setUTCHours(0);
914
+ }
915
+ else
916
+ d.setUTCMonth(d.getUTCMonth() + tickSize);
917
+ }
918
+ else if (unit == "year") {
919
+ d.setUTCFullYear(d.getUTCFullYear() + tickSize);
920
+ }
921
+ else
922
+ d.setTime(v + step);
923
+ } while (v < axis.max && v != prev);
924
+ return ticks;
925
+ };
926
+ formatter = function (v, axis) {
927
+ var d = new Date(v);
928
+ if (opts.timeformat != null)
929
+ return $.plot.formatDate(d, opts.timeformat, opts.monthNames);
930
+ var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
931
+ var span = axis.max - axis.min;
932
+ var suffix = (opts.twelveHourClock) ? " %p" : "";
933
+ if (t < timeUnitSize.minute)
934
+ fmt = "%h:%M:%S" + suffix;
935
+ else if (t < timeUnitSize.day) {
936
+ if (span < 2 * timeUnitSize.day)
937
+ fmt = "%h:%M" + suffix;
938
+ else
939
+ fmt = "%b %d %h:%M" + suffix;
940
+ }
941
+ else if (t < timeUnitSize.month)
942
+ fmt = "%b %d";
943
+ else if (t < timeUnitSize.year) {
944
+ if (span < timeUnitSize.year)
945
+ fmt = "%b";
946
+ else
947
+ fmt = "%b %y";
948
+ }
949
+ else
950
+ fmt = "%y";
951
+ return $.plot.formatDate(d, fmt, opts.monthNames);
952
+ };
953
+ }
954
+ else {
955
+ var maxDec = opts.tickDecimals;
956
+ var dec = -Math.floor(Math.log(delta) / Math.LN10);
957
+ if (maxDec != null && dec > maxDec)
958
+ dec = maxDec;
959
+ magn = Math.pow(10, -dec);
960
+ norm = delta / magn;
961
+ if (norm < 1.5)
962
+ size = 1;
963
+ else if (norm < 3) {
964
+ size = 2;
965
+ if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {
966
+ size = 2.5;
967
+ ++dec;
968
+ }
969
+ }
970
+ else if (norm < 7.5)
971
+ size = 5;
972
+ else
973
+ size = 10;
974
+ size *= magn;
975
+ if (opts.minTickSize != null && size < opts.minTickSize)
976
+ size = opts.minTickSize;
977
+ axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
978
+ axis.tickSize = opts.tickSize || size;
979
+ generator = function (axis) {
980
+ var ticks = [];
981
+ var start = floorInBase(axis.min, axis.tickSize),
982
+ i = 0, v = Number.NaN, prev;
983
+ do {
984
+ prev = v;
985
+ v = start + i * axis.tickSize;
986
+ ticks.push(v);
987
+ ++i;
988
+ } while (v < axis.max && v != prev);
989
+ return ticks;
990
+ };
991
+ formatter = function (v, axis) {
992
+ return v.toFixed(axis.tickDecimals);
993
+ };
994
+ }
995
+ if (opts.alignTicksWithAxis != null) {
996
+ var otherAxis = (axis.direction == "x" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1];
997
+ if (otherAxis && otherAxis.used && otherAxis != axis) {
998
+ var niceTicks = generator(axis);
999
+ if (niceTicks.length > 0) {
1000
+ if (opts.min == null)
1001
+ axis.min = Math.min(axis.min, niceTicks[0]);
1002
+ if (opts.max == null && niceTicks.length > 1)
1003
+ axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]);
1004
+ }
1005
+ generator = function (axis) {
1006
+ var ticks = [], v, i;
1007
+ for (i = 0; i < otherAxis.ticks.length; ++i) {
1008
+ v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min);
1009
+ v = axis.min + v * (axis.max - axis.min);
1010
+ ticks.push(v);
1011
+ }
1012
+ return ticks;
1013
+ };
1014
+ if (axis.mode != "time" && opts.tickDecimals == null) {
1015
+ var extraDec = Math.max(0, -Math.floor(Math.log(delta) / Math.LN10) + 1),
1016
+ ts = generator(axis);
1017
+ if (!(ts.length > 1 && /\..*0#x2F;.test((ts[1] - ts[0]).toFixed(extraDec))))
1018
+ axis.tickDecimals = extraDec;
1019
+ }
1020
+ }
1021
+ }
1022
+ axis.tickGenerator = generator;
1023
+ if ($.isFunction(opts.tickFormatter))
1024
+ axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); };
1025
+ else
1026
+ axis.tickFormatter = formatter;
1027
+ }
1028
+ function setTicks(axis) {
1029
+ var oticks = axis.options.ticks, ticks = [];
1030
+ if (oticks == null || (typeof oticks == "number" && oticks > 0))
1031
+ ticks = axis.tickGenerator(axis);
1032
+ else if (oticks) {
1033
+ if ($.isFunction(oticks))
1034
+ ticks = oticks({ min: axis.min, max: axis.max });
1035
+ else
1036
+ ticks = oticks;
1037
+ }
1038
+ var i, v;
1039
+ axis.ticks = [];
1040
+ for (i = 0; i < ticks.length; ++i) {
1041
+ var label = null;
1042
+ var t = ticks[i];
1043
+ if (typeof t == "object") {
1044
+ v = +t[0];
1045
+ if (t.length > 1)
1046
+ label = t[1];
1047
+ }
1048
+ else
1049
+ v = +t;
1050
+ if (label == null)
1051
+ label = axis.tickFormatter(v, axis);
1052
+ if (!isNaN(v))
1053
+ axis.ticks.push({ v: v, label: label });
1054
+ }
1055
+ }
1056
+ function snapRangeToTicks(axis, ticks) {
1057
+ if (axis.options.autoscaleMargin && ticks.length > 0) {
1058
+ if (axis.options.min == null)
1059
+ axis.min = Math.min(axis.min, ticks[0].v);
1060
+ if (axis.options.max == null && ticks.length > 1)
1061
+ axis.max = Math.max(axis.max, ticks[ticks.length - 1].v);
1062
+ }
1063
+ }
1064
+ function draw() {
1065
+ ctx.clearRect(0, 0, canvasWidth, canvasHeight);
1066
+ var grid = options.grid;
1067
+ if (grid.show && grid.backgroundColor)
1068
+ drawBackground();
1069
+ if (grid.show && !grid.aboveData) {
1070
+ drawGrid();
1071
+ drawAxisLabels();
1072
+ }
1073
+ for (var i = 0; i < series.length; ++i) {
1074
+ executeHooks(hooks.drawSeries, [ctx, series[i]]);
1075
+ drawSeries(series[i]);
1076
+ }
1077
+ executeHooks(hooks.draw, [ctx]);
1078
+ if (grid.show && grid.aboveData) {
1079
+ drawGrid();
1080
+ drawAxisLabels();
1081
+ }
1082
+ }
1083
+ function extractRange(ranges, coord) {
1084
+ var axis, from, to, key, axes = allAxes();
1085
+ for (i = 0; i < axes.length; ++i) {
1086
+ axis = axes[i];
1087
+ if (axis.direction == coord) {
1088
+ key = coord + axis.n + "axis";
1089
+ if (!ranges[key] && axis.n == 1)
1090
+ key = coord + "axis";
1091
+ if (ranges[key]) {
1092
+ from = ranges[key].from;
1093
+ to = ranges[key].to;
1094
+ break;
1095
+ }
1096
+ }
1097
+ }
1098
+ if (!ranges[key]) {
1099
+ axis = coord == "x" ? xaxes[0] : yaxes[0];
1100
+ from = ranges[coord + "1"];
1101
+ to = ranges[coord + "2"];
1102
+ }
1103
+ if (from != null && to != null && from > to) {
1104
+ var tmp = from;
1105
+ from = to;
1106
+ to = tmp;
1107
+ }
1108
+ return { from: from, to: to, axis: axis };
1109
+ }
1110
+ function drawBackground() {
1111
+ ctx.save();
1112
+ ctx.translate(plotOffset.left, plotOffset.top);
1113
+ ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)");
1114
+ ctx.fillRect(0, 0, plotWidth, plotHeight);
1115
+ ctx.restore();
1116
+ }
1117
+ function drawGrid() {
1118
+ var i;
1119
+ ctx.save();
1120
+ ctx.translate(plotOffset.left, plotOffset.top);
1121
+ var markings = options.grid.markings;
1122
+ if (markings) {
1123
+ if ($.isFunction(markings)) {
1124
+ var axes = plot.getAxes();
1125
+ axes.xmin = axes.xaxis.min;
1126
+ axes.xmax = axes.xaxis.max;
1127
+ axes.ymin = axes.yaxis.min;
1128
+ axes.ymax = axes.yaxis.max;
1129
+ markings = markings(axes);
1130
+ }
1131
+ for (i = 0; i < markings.length; ++i) {
1132
+ var m = markings[i],
1133
+ xrange = extractRange(m, "x"),
1134
+ yrange = extractRange(m, "y");
1135
+ if (xrange.from == null)
1136
+ xrange.from = xrange.axis.min;
1137
+ if (xrange.to == null)
1138
+ xrange.to = xrange.axis.max;
1139
+ if (yrange.from == null)
1140
+ yrange.from = yrange.axis.min;
1141
+ if (yrange.to == null)
1142
+ yrange.to = yrange.axis.max;
1143
+ if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max ||
1144
+ yrange.to < yrange.axis.min || yrange.from > yrange.axis.max)
1145
+ continue;
1146
+ xrange.from = Math.max(xrange.from, xrange.axis.min);
1147
+ xrange.to = Math.min(xrange.to, xrange.axis.max);
1148
+ yrange.from = Math.max(yrange.from, yrange.axis.min);
1149
+ yrange.to = Math.min(yrange.to, yrange.axis.max);
1150
+ if (xrange.from == xrange.to && yrange.from == yrange.to)
1151
+ continue;
1152
+ xrange.from = xrange.axis.p2c(xrange.from);
1153
+ xrange.to = xrange.axis.p2c(xrange.to);
1154
+ yrange.from = yrange.axis.p2c(yrange.from);
1155
+ yrange.to = yrange.axis.p2c(yrange.to);
1156
+ if (xrange.from == xrange.to || yrange.from == yrange.to) {
1157
+ ctx.beginPath();
1158
+ ctx.strokeStyle = m.color || options.grid.markingsColor;
1159
+ ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth;
1160
+ ctx.moveTo(xrange.from, yrange.from);
1161
+ ctx.lineTo(xrange.to, yrange.to);
1162
+ ctx.stroke();
1163
+ }
1164
+ else {
1165
+ ctx.fillStyle = m.color || options.grid.markingsColor;
1166
+ ctx.fillRect(xrange.from, yrange.to,
1167
+ xrange.to - xrange.from,
1168
+ yrange.from - yrange.to);
1169
+ }
1170
+ }
1171
+ }
1172
+ var axes = allAxes(), bw = options.grid.borderWidth;
1173
+ for (var j = 0; j < axes.length; ++j) {
1174
+ var axis = axes[j], box = axis.box,
1175
+ t = axis.tickLength, x, y, xoff, yoff;
1176
+ if (!axis.show || axis.ticks.length == 0)
1177
+ continue;
1178
+ ctx.strokeStyle = axis.options.tickColor || $.color.parse(axis.options.color).scale('a', 0.22).toString();
1179
+ ctx.lineWidth = 1;
1180
+ if (axis.direction == "x") {
1181
+ x = 0;
1182
+ if (t == "full")
1183
+ y = (axis.position == "top" ? 0 : plotHeight);
1184
+ else
1185
+ y = box.top - plotOffset.top + (axis.position == "top" ? box.height : 0);
1186
+ }
1187
+ else {
1188
+ y = 0;
1189
+ if (t == "full")
1190
+ x = (axis.position == "left" ? 0 : plotWidth);
1191
+ else
1192
+ x = box.left - plotOffset.left + (axis.position == "left" ? box.width : 0);
1193
+ }
1194
+ if (!axis.innermost) {
1195
+ ctx.beginPath();
1196
+ xoff = yoff = 0;
1197
+ if (axis.direction == "x")
1198
+ xoff = plotWidth;
1199
+ else
1200
+ yoff = plotHeight;
1201
+ if (ctx.lineWidth == 1) {
1202
+ x = Math.floor(x) + 0.5;
1203
+ y = Math.floor(y) + 0.5;
1204
+ }
1205
+ ctx.moveTo(x, y);
1206
+ ctx.lineTo(x + xoff, y + yoff);
1207
+ ctx.stroke();
1208
+ }
1209
+ ctx.beginPath();
1210
+ for (i = 0; i < axis.ticks.length; ++i) {
1211
+ var v = axis.ticks[i].v;
1212
+ xoff = yoff = 0;
1213
+ if (v < axis.min || v > axis.max
1214
+ || (t == "full" && bw > 0
1215
+ && (v == axis.min || v == axis.max)))
1216
+ continue;
1217
+ if (axis.direction == "x") {
1218
+ x = axis.p2c(v);
1219
+ yoff = t == "full" ? -plotHeight : t;
1220
+ if (axis.position == "top")
1221
+ yoff = -yoff;
1222
+ }
1223
+ else {
1224
+ y = axis.p2c(v);
1225
+ xoff = t == "full" ? -plotWidth : t;
1226
+ if (axis.position == "left")
1227
+ xoff = -xoff;
1228
+ }
1229
+ if (ctx.lineWidth == 1) {
1230
+ if (axis.direction == "x")
1231
+ x = Math.floor(x) + 0.5;
1232
+ else
1233
+ y = Math.floor(y) + 0.5;
1234
+ }
1235
+ ctx.moveTo(x, y);
1236
+ ctx.lineTo(x + xoff, y + yoff);
1237
+ }
1238
+ ctx.stroke();
1239
+ }
1240
+ if (bw) {
1241
+ ctx.lineWidth = bw;
1242
+ ctx.strokeStyle = options.grid.borderColor;
1243
+ ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw);
1244
+ }
1245
+ ctx.restore();
1246
+ }
1247
+ function drawAxisLabels() {
1248
+ ctx.save();
1249
+ $.each(allAxes(), function (_, axis) {
1250
+ if (!axis.show || axis.ticks.length == 0)
1251
+ return;
1252
+ var box = axis.box, f = axis.font;
1253
+ ctx.fillStyle = axis.options.color;
1254
+ ctx.font = f.style + " " + f.variant + " " + f.weight + " " + f.size + "px '" + f.family + "'";
1255
+ ctx.textAlign = "start";
1256
+ ctx.textBaseline = "middle";
1257
+ for (var i = 0; i < axis.ticks.length; ++i) {
1258
+ var tick = axis.ticks[i];
1259
+ if (!tick.label || tick.v < axis.min || tick.v > axis.max)
1260
+ continue;
1261
+ var x, y, offset = 0, line;
1262
+ for (var k = 0; k < tick.lines.length; ++k) {
1263
+ line = tick.lines[k];
1264
+ if (axis.direction == "x") {
1265
+ x = plotOffset.left + axis.p2c(tick.v) - line.width/2;
1266
+ if (axis.position == "bottom")
1267
+ y = box.top + box.padding;
1268
+ else
1269
+ y = box.top + box.height - box.padding - tick.height;
1270
+ }
1271
+ else {
1272
+ y = plotOffset.top + axis.p2c(tick.v) - tick.height/2;
1273
+ if (axis.position == "left")
1274
+ x = box.left + box.width - box.padding - line.width;
1275
+ else
1276
+ x = box.left + box.padding;
1277
+ }
1278
+ y += line.height/2 + offset;
1279
+ offset += line.height;
1280
+ if ($.browser.opera) {
1281
+ x = Math.floor(x);
1282
+ y = Math.ceil(y - 2);
1283
+ }
1284
+ ctx.fillText(line.text, x, y);
1285
+ }
1286
+ }
1287
+ });
1288
+ ctx.restore();
1289
+ }
1290
+ function drawSeries(series) {
1291
+ if (series.lines.show)
1292
+ drawSeriesLines(series);
1293
+ if (series.bars.show)
1294
+ drawSeriesBars(series);
1295
+ if (series.points.show)
1296
+ drawSeriesPoints(series);
1297
+ }
1298
+ function drawSeriesLines(series) {
1299
+ function plotLine(datapoints, xoffset, yoffset, axisx, axisy) {
1300
+ var points = datapoints.points,
1301
+ ps = datapoints.pointsize,
1302
+ prevx = null, prevy = null;
1303
+ ctx.beginPath();
1304
+ for (var i = ps; i < points.length; i += ps) {
1305
+ var x1 = points[i - ps], y1 = points[i - ps + 1],
1306
+ x2 = points[i], y2 = points[i + 1];
1307
+ if (x1 == null || x2 == null)
1308
+ continue;
1309
+ if (y1 <= y2 && y1 < axisy.min) {
1310
+ if (y2 < axisy.min)
1311
+ continue;
1312
+ x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
1313
+ y1 = axisy.min;
1314
+ }
1315
+ else if (y2 <= y1 && y2 < axisy.min) {
1316
+ if (y1 < axisy.min)
1317
+ continue;
1318
+ x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
1319
+ y2 = axisy.min;
1320
+ }
1321
+ if (y1 >= y2 && y1 > axisy.max) {
1322
+ if (y2 > axisy.max)
1323
+ continue;
1324
+ x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
1325
+ y1 = axisy.max;
1326
+ }
1327
+ else if (y2 >= y1 && y2 > axisy.max) {
1328
+ if (y1 > axisy.max)
1329
+ continue;
1330
+ x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
1331
+ y2 = axisy.max;
1332
+ }
1333
+ if (x1 <= x2 && x1 < axisx.min) {
1334
+ if (x2 < axisx.min)
1335
+ continue;
1336
+ y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
1337
+ x1 = axisx.min;
1338
+ }
1339
+ else if (x2 <= x1 && x2 < axisx.min) {
1340
+ if (x1 < axisx.min)
1341
+ continue;
1342
+ y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
1343
+ x2 = axisx.min;
1344
+ }
1345
+ if (x1 >= x2 && x1 > axisx.max) {
1346
+ if (x2 > axisx.max)
1347
+ continue;
1348
+ y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
1349
+ x1 = axisx.max;
1350
+ }
1351
+ else if (x2 >= x1 && x2 > axisx.max) {
1352
+ if (x1 > axisx.max)
1353
+ continue;
1354
+ y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
1355
+ x2 = axisx.max;
1356
+ }
1357
+ if (x1 != prevx || y1 != prevy)
1358
+ ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);
1359
+ prevx = x2;
1360
+ prevy = y2;
1361
+ ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset);
1362
+ }
1363
+ ctx.stroke();
1364
+ }
1365
+ function plotLineArea(datapoints, axisx, axisy) {
1366
+ var points = datapoints.points,
1367
+ ps = datapoints.pointsize,
1368
+ bottom = Math.min(Math.max(0, axisy.min), axisy.max),
1369
+ i = 0, top, areaOpen = false,
1370
+ ypos = 1, segmentStart = 0, segmentEnd = 0;
1371
+ while (true) {
1372
+ if (ps > 0 && i > points.length + ps)
1373
+ break;
1374
+ i += ps;
1375
+ var x1 = points[i - ps],
1376
+ y1 = points[i - ps + ypos],
1377
+ x2 = points[i], y2 = points[i + ypos];
1378
+ if (areaOpen) {
1379
+ if (ps > 0 && x1 != null && x2 == null) {
1380
+ segmentEnd = i;
1381
+ ps = -ps;
1382
+ ypos = 2;
1383
+ continue;
1384
+ }
1385
+ if (ps < 0 && i == segmentStart + ps) {
1386
+ ctx.fill();
1387
+ areaOpen = false;
1388
+ ps = -ps;
1389
+ ypos = 1;
1390
+ i = segmentStart = segmentEnd + ps;
1391
+ continue;
1392
+ }
1393
+ }
1394
+ if (x1 == null || x2 == null)
1395
+ continue;
1396
+ if (x1 <= x2 && x1 < axisx.min) {
1397
+ if (x2 < axisx.min)
1398
+ continue;
1399
+ y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
1400
+ x1 = axisx.min;
1401
+ }
1402
+ else if (x2 <= x1 && x2 < axisx.min) {
1403
+ if (x1 < axisx.min)
1404
+ continue;
1405
+ y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
1406
+ x2 = axisx.min;
1407
+ }
1408
+ if (x1 >= x2 && x1 > axisx.max) {
1409
+ if (x2 > axisx.max)
1410
+ continue;
1411
+ y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
1412
+ x1 = axisx.max;
1413
+ }
1414
+ else if (x2 >= x1 && x2 > axisx.max) {
1415
+ if (x1 > axisx.max)
1416
+ continue;
1417
+ y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
1418
+ x2 = axisx.max;
1419
+ }
1420
+ if (!areaOpen) {
1421
+ ctx.beginPath();
1422
+ ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));
1423
+ areaOpen = true;
1424
+ }
1425
+ if (y1 >= axisy.max && y2 >= axisy.max) {
1426
+ ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));
1427
+ ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));
1428
+ continue;
1429
+ }
1430
+ else if (y1 <= axisy.min && y2 <= axisy.min) {
1431
+ ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));
1432
+ ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));
1433
+ continue;
1434
+ }
1435
+ var x1old = x1, x2old = x2;
1436
+ if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {
1437
+ x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
1438
+ y1 = axisy.min;
1439
+ }