|
10 | 10 | * |
11 | 11 | * About: Copyright & License |
12 | 12 | * |
13 | | - * Copyright (c) 2009-2013 Chris Leonello |
| 13 | + * Copyright (c) 2009-2016 Chris Leonello |
14 | 14 | * jqPlot is currently available for use in all personal or commercial projects |
15 | 15 | * under both the MIT and GPL version 2.0 licenses. This means that you can |
16 | 16 | * choose the license that best suits your project and use it accordingly. |
|
184 | 184 | * enabled in the individual plot options. Default: false. |
185 | 185 | * This property sets the "show" property of certain plugins to true or false. |
186 | 186 | * Only plugins that can be immediately active upon loading are affected. This includes |
187 | | - * non-renderer plugins like cursor, dragable, highlighter, and trendline. |
| 187 | + * non-renderer plugins like cursor, draggable, highlighter, and trendline. |
188 | 188 | * defaultHeight - Default height for plots where no css height specification exists. This |
189 | 189 | * is a jqplot wide default. |
190 | 190 | * defaultWidth - Default height for plots where no css height specification exists. This |
|
295 | 295 | if ($.jqplot.use_excanvas) { |
296 | 296 | return window.G_vmlCanvasManager.initElement(canvas); |
297 | 297 | } |
| 298 | + |
298 | 299 | var cctx = canvas.getContext('2d'); |
299 | 300 |
|
300 | 301 | var canvasBackingScale = 1; |
|
892 | 893 | // prop: placement |
893 | 894 | // "insideGrid" places legend inside the grid area of the plot. |
894 | 895 | // "outsideGrid" places the legend outside the grid but inside the plot container, |
895 | | - // shrinking the grid to accomodate the legend. |
| 896 | + // shrinking the grid to accommodate the legend. |
896 | 897 | // "inside" synonym for "insideGrid", |
897 | 898 | // "outside" places the legend ouside the grid area, but does not shrink the grid which |
898 | 899 | // can cause the legend to overflow the plot container. |
|
1325 | 1326 | this._sumy = 0; |
1326 | 1327 | this._sumx = 0; |
1327 | 1328 | this._type = ''; |
| 1329 | + this.step = false; |
1328 | 1330 | } |
1329 | 1331 |
|
1330 | 1332 | Series.prototype = new $.jqplot.ElemContainer(); |
|
1804 | 1806 | // prop: drawIfHidden |
1805 | 1807 | // True to execute the draw method even if the plot target is hidden. |
1806 | 1808 | // Generally, this should be false. Most plot elements will not be sized/ |
1807 | | - // positioned correctly if renderered into a hidden container. To render into |
| 1809 | + // positioned correclty if renderered into a hidden container. To render into |
1808 | 1810 | // a hidden container, call the replot method when the container is shown. |
1809 | 1811 | this.drawIfHidden = false; |
1810 | 1812 | this.eventCanvas = new $.jqplot.GenericCanvas(); |
|
2058 | 2060 | $.extend(true, this.noDataIndicator, options.noDataIndicator); |
2059 | 2061 | } |
2060 | 2062 |
|
2061 | | - if (data == null || $.isArray(data) == false || data.length == 0 || $.isArray(data[0]) == false || data[0].length == 0) { |
| 2063 | + // check for any data |
| 2064 | + var hasData = false; |
| 2065 | + if (data != null && $.isArray(data) === true) { |
| 2066 | + for (var i = 0; i < data.length; i++) { |
| 2067 | + if ($.isArray(data[i]) === true && data[i].length > 0) { |
| 2068 | + hasData = true; |
| 2069 | + break; |
| 2070 | + }; |
| 2071 | + } |
| 2072 | + }; |
| 2073 | + |
| 2074 | + if (!hasData) { |
2062 | 2075 |
|
2063 | 2076 | if (this.noDataIndicator.show == false) { |
2064 | 2077 | throw new Error("No data specified"); |
|
2100 | 2113 |
|
2101 | 2114 | // make a copy of the data |
2102 | 2115 | this.data = $.extend(true, [], data); |
2103 | | - |
| 2116 | + // fix missing data entries |
| 2117 | + for (var i = 0; i < this.data.length; i++) { |
| 2118 | + if ($.isArray(data[i]) == false) { |
| 2119 | + this.data[i] = []; |
| 2120 | + }; |
| 2121 | + }; |
| 2122 | + |
2104 | 2123 | this.parseOptions(options); |
2105 | 2124 |
|
2106 | 2125 | if (this.textColor) { |
|
3049 | 3068 |
|
3050 | 3069 | if (this.legend.placement === 'outsideGrid') { |
3051 | 3070 | legendPadding = {top:this.title.getHeight(), left: 0, right: 0, bottom: 0}; |
3052 | | - if (this.legend.location === 's') { |
3053 | | - legendPadding.left = this._gridPadding.left; |
3054 | | - legendPadding.right = this._gridPadding.right; |
3055 | | - } |
3056 | 3071 | } |
3057 | 3072 |
|
3058 | 3073 | ax.xaxis.pack({position:'absolute', bottom:this._gridPadding.bottom - ax.xaxis.getHeight(), left:0, width:this._width}, {min:this._gridPadding.left, max:this._width - this._gridPadding.right}); |
|
3131 | 3146 | } |
3132 | 3147 |
|
3133 | 3148 | var fb = this.fillBetween; |
3134 | | - if (fb.fill && fb.series1 !== fb.series2 && fb.series1 < seriesLength && fb.series2 < seriesLength && series[fb.series1]._type === 'line' && series[fb.series2]._type === 'line') { |
| 3149 | + if(typeof fb.series1 == 'number'){ |
| 3150 | + if(fb.fill&&fb.series1!==fb.series2&&fb.series1<seriesLength&&fb.series2<seriesLength&&series[fb.series1]._type==="line"&&series[fb.series2]._type==="line") |
3135 | 3151 | this.doFillBetweenLines(); |
3136 | 3152 | } |
| 3153 | + else{ |
| 3154 | + if(fb.series1 != null && fb.series2 != null){ |
| 3155 | + var doFb = false; |
| 3156 | + if(fb.series1.length === fb.series2.length){ |
| 3157 | + var tempSeries1 = 0; |
| 3158 | + var tempSeries2 = 0; |
| 3159 | + |
| 3160 | + for(var cnt = 0; cnt < fb.series1.length; cnt++){ |
| 3161 | + tempSeries1 = fb.series1[cnt]; |
| 3162 | + tempSeries2 = fb.series2[cnt]; |
| 3163 | + if(tempSeries1!==tempSeries2&&tempSeries1<seriesLength&&tempSeries2<seriesLength&&series[tempSeries1]._type==="line"&&series[tempSeries2]._type==="line"){ |
| 3164 | + doFb = true; |
| 3165 | + } |
| 3166 | + else{ |
| 3167 | + doFb = false; |
| 3168 | + break; |
| 3169 | + } |
| 3170 | + } |
| 3171 | + } |
| 3172 | + if(fb.fill && doFb){ |
| 3173 | + this.doFillBetweenLines(); |
| 3174 | + } |
| 3175 | + } |
| 3176 | + } |
3137 | 3177 |
|
3138 | 3178 | for (var i=0, l=$.jqplot.postDrawHooks.length; i<l; i++) { |
3139 | 3179 | $.jqplot.postDrawHooks[i].call(this); |
|
3174 | 3214 |
|
3175 | 3215 | jqPlot.prototype.doFillBetweenLines = function () { |
3176 | 3216 | var fb = this.fillBetween; |
| 3217 | + var series = this.series; |
3177 | 3218 | var sid1 = fb.series1; |
3178 | 3219 | var sid2 = fb.series2; |
3179 | | - // first series should always be lowest index |
3180 | | - var id1 = (sid1 < sid2) ? sid1 : sid2; |
3181 | | - var id2 = (sid2 > sid1) ? sid2 : sid1; |
3182 | | - |
3183 | | - var series1 = this.series[id1]; |
3184 | | - var series2 = this.series[id2]; |
3185 | | - |
3186 | | - if (series2.renderer.smooth) { |
3187 | | - var tempgd = series2.renderer._smoothedData.slice(0).reverse(); |
3188 | | - } |
3189 | | - else { |
3190 | | - var tempgd = series2.gridData.slice(0).reverse(); |
| 3220 | + var id1 = 0, id2 = 0; |
| 3221 | + |
| 3222 | + function fill(id1, id2){ |
| 3223 | + var series1 = series[id1]; |
| 3224 | + var series2 = series[id2]; |
| 3225 | + if (series2.renderer.smooth) |
| 3226 | + var tempgd = series2.renderer._smoothedData.slice(0).reverse(); |
| 3227 | + else |
| 3228 | + var tempgd = series2.gridData.slice(0).reverse(); |
| 3229 | + if (series1.renderer.smooth) |
| 3230 | + var gd = series1.renderer._smoothedData.concat(tempgd); |
| 3231 | + else |
| 3232 | + var gd = series1.gridData.concat(tempgd); |
| 3233 | + var color = fb.color !== null ? fb.color : series[id1].fillColor; |
| 3234 | + var baseSeries = fb.baseSeries !== null ? fb.baseSeries : id1; |
| 3235 | + var sr = |
| 3236 | + series[baseSeries].renderer.shapeRenderer; |
| 3237 | + var opts = |
| 3238 | + { |
| 3239 | + fillStyle : color, |
| 3240 | + fill : true, |
| 3241 | + closePath : true |
| 3242 | + }; |
| 3243 | + sr.draw(series1.shadowCanvas._ctx, gd, opts) |
3191 | 3244 | } |
3192 | 3245 |
|
3193 | | - if (series1.renderer.smooth) { |
3194 | | - var gd = series1.renderer._smoothedData.concat(tempgd); |
| 3246 | + if(typeof sid1 == 'number' && typeof sid2 == 'number'){ |
| 3247 | + id1 = sid1 < sid2 ? sid1 : sid2; |
| 3248 | + id2 = sid2 > sid1 ? sid2 : sid1; |
| 3249 | + fill(id1, id2); |
3195 | 3250 | } |
3196 | | - else { |
3197 | | - var gd = series1.gridData.concat(tempgd); |
| 3251 | + else{ |
| 3252 | + for(var cnt = 0; cnt < sid1.length ; cnt++){ |
| 3253 | + id1 = sid1[cnt] < sid2[cnt] ? sid1[cnt] : sid2[cnt]; |
| 3254 | + id2 = sid2[cnt] > sid1[cnt] ? sid2[cnt] : sid1[cnt]; |
| 3255 | + fill(id1, id2); |
| 3256 | + } |
3198 | 3257 | } |
3199 | | - |
3200 | | - var color = (fb.color !== null) ? fb.color : this.series[sid1].fillColor; |
3201 | | - var baseSeries = (fb.baseSeries !== null) ? fb.baseSeries : id1; |
3202 | | - |
3203 | | - // now apply a fill to the shape on the lower series shadow canvas, |
3204 | | - // so it is behind both series. |
3205 | | - var sr = this.series[baseSeries].renderer.shapeRenderer; |
3206 | | - var opts = {fillStyle: color, fill: true, closePath: true}; |
3207 | | - sr.draw(series1.shadowCanvas._ctx, gd, opts); |
3208 | 3258 | }; |
3209 | 3259 |
|
3210 | 3260 | this.bindCustomEvents = function() { |
|
3261 | 3311 | for (j=0; j<s._barPoints.length; j++) { |
3262 | 3312 | points = s._barPoints[j]; |
3263 | 3313 | p = s.gridData[j]; |
3264 | | - if (x>points[0][0] && x<points[2][0] && y>points[2][1] && y<points[0][1]) { |
| 3314 | + if (x>points[0][0] && x<points[2][0] && (y>points[2][1] && y<points[0][1] || y<points[2][1] && y>points[0][1])) { |
3265 | 3315 | return {seriesIndex:s.index, pointIndex:j, gridData:p, data:s.data[j], points:s._barPoints[j]}; |
3266 | 3316 | } |
3267 | 3317 | } |
|
3414 | 3464 | for (j=0; j<v.length; j++) { |
3415 | 3465 | cv = v[j]; |
3416 | 3466 | if (y >= cv[0][1] && y <= cv[3][1] && x >= lex[0] && x <= rex[0]) { |
3417 | | - return {seriesIndex:s.index, pointIndex:j, gridData:null, data:s.data[j]}; |
| 3467 | + return {seriesIndex:s.index, pointIndex:j, gridData:[gridpos.x,gridpos.y], data:s.data[j]}; |
3418 | 3468 | } |
3419 | 3469 | } |
3420 | 3470 | break; |
|
0 commit comments