180 lines
7.0 KiB
JavaScript
180 lines
7.0 KiB
JavaScript
(function () {
|
|
|
|
var
|
|
D = Flotr.DOM,
|
|
_ = Flotr._;
|
|
|
|
Flotr.addPlugin('legend', {
|
|
options: {
|
|
show: true, // => setting to true will show the legend, hide otherwise
|
|
noColumns: 1, // => number of colums in legend table // @todo: doesn't work for HtmlText = false
|
|
labelFormatter: function(v){return v;}, // => fn: string -> string
|
|
labelBoxBorderColor: '#CCCCCC', // => border color for the little label boxes
|
|
labelBoxWidth: 14,
|
|
labelBoxHeight: 10,
|
|
labelBoxMargin: 5,
|
|
labelBoxOpacity: 0.4,
|
|
container: null, // => container (as jQuery object) to put legend in, null means default on top of graph
|
|
position: 'nw', // => position of default legend container within plot
|
|
margin: 5, // => distance from grid edge to default legend container within plot
|
|
backgroundColor: null, // => null means auto-detect
|
|
backgroundOpacity: 0.85// => set to 0 to avoid background, set to 1 for a solid background
|
|
},
|
|
callbacks: {
|
|
'flotr:afterinit': function() {
|
|
this.legend.insertLegend();
|
|
}
|
|
},
|
|
/**
|
|
* Adds a legend div to the canvas container or draws it on the canvas.
|
|
*/
|
|
insertLegend: function(){
|
|
|
|
if(!this.options.legend.show)
|
|
return;
|
|
|
|
var series = this.series,
|
|
plotOffset = this.plotOffset,
|
|
options = this.options,
|
|
legend = options.legend,
|
|
fragments = [],
|
|
rowStarted = false,
|
|
ctx = this.ctx,
|
|
itemCount = _.filter(series, function(s) {return (s.label && !s.hide);}).length,
|
|
p = legend.position,
|
|
m = legend.margin,
|
|
i, label, color;
|
|
|
|
if (itemCount) {
|
|
if (!options.HtmlText && this.textEnabled && !legend.container) {
|
|
var style = {
|
|
size: options.fontSize*1.1,
|
|
color: options.grid.color
|
|
};
|
|
|
|
var lbw = legend.labelBoxWidth,
|
|
lbh = legend.labelBoxHeight,
|
|
lbm = legend.labelBoxMargin,
|
|
offsetX = plotOffset.left + m,
|
|
offsetY = plotOffset.top + m;
|
|
|
|
// We calculate the labels' max width
|
|
var labelMaxWidth = 0;
|
|
for(i = series.length - 1; i > -1; --i){
|
|
if(!series[i].label || series[i].hide) continue;
|
|
label = legend.labelFormatter(series[i].label);
|
|
labelMaxWidth = Math.max(labelMaxWidth, this._text.measureText(label, style).width);
|
|
}
|
|
|
|
var legendWidth = Math.round(lbw + lbm*3 + labelMaxWidth),
|
|
legendHeight = Math.round(itemCount*(lbm+lbh) + lbm);
|
|
|
|
if(p.charAt(0) == 's') offsetY = plotOffset.top + this.plotHeight - (m + legendHeight);
|
|
if(p.charAt(1) == 'e') offsetX = plotOffset.left + this.plotWidth - (m + legendWidth);
|
|
|
|
// Legend box
|
|
color = this.processColor(legend.backgroundColor || 'rgb(240,240,240)', {opacity: legend.backgroundOpacity || 0.1});
|
|
|
|
ctx.fillStyle = color;
|
|
ctx.fillRect(offsetX, offsetY, legendWidth, legendHeight);
|
|
ctx.strokeStyle = legend.labelBoxBorderColor;
|
|
ctx.strokeRect(Flotr.toPixel(offsetX), Flotr.toPixel(offsetY), legendWidth, legendHeight);
|
|
|
|
// Legend labels
|
|
var x = offsetX + lbm;
|
|
var y = offsetY + lbm;
|
|
for(i = 0; i < series.length; i++){
|
|
if(!series[i].label || series[i].hide) continue;
|
|
label = legend.labelFormatter(series[i].label);
|
|
|
|
ctx.fillStyle = series[i].color;
|
|
ctx.fillRect(x, y, lbw-1, lbh-1);
|
|
|
|
ctx.strokeStyle = legend.labelBoxBorderColor;
|
|
ctx.lineWidth = 1;
|
|
ctx.strokeRect(Math.ceil(x)-1.5, Math.ceil(y)-1.5, lbw+2, lbh+2);
|
|
|
|
// Legend text
|
|
Flotr.drawText(ctx, label, x + lbw + lbm, y + lbh, style);
|
|
|
|
y += lbh + lbm;
|
|
}
|
|
}
|
|
else {
|
|
for(i = 0; i < series.length; ++i){
|
|
if(!series[i].label || series[i].hide) continue;
|
|
|
|
if(i % legend.noColumns === 0){
|
|
fragments.push(rowStarted ? '</tr><tr>' : '<tr>');
|
|
rowStarted = true;
|
|
}
|
|
|
|
// @TODO remove requirement on bars
|
|
var s = series[i],
|
|
boxWidth = legend.labelBoxWidth,
|
|
boxHeight = legend.labelBoxHeight,
|
|
opacityValue = (s.bars ? s.bars.fillOpacity : legend.labelBoxOpacity),
|
|
opacity = 'opacity:' + opacityValue + ';filter:alpha(opacity=' + opacityValue*100 + ');';
|
|
|
|
label = legend.labelFormatter(s.label);
|
|
color = 'background-color:' + ((s.bars && s.bars.show && s.bars.fillColor && s.bars.fill) ? s.bars.fillColor : s.color) + ';';
|
|
|
|
fragments.push(
|
|
'<td class="flotr-legend-color-box">',
|
|
'<div style="border:1px solid ', legend.labelBoxBorderColor, ';padding:1px">',
|
|
'<div style="width:', (boxWidth-1), 'px;height:', (boxHeight-1), 'px;border:1px solid ', series[i].color, '">', // Border
|
|
'<div style="width:', boxWidth, 'px;height:', boxHeight, 'px;', 'opacity:.4;', color, '"></div>', // Background
|
|
'</div>',
|
|
'</div>',
|
|
'</td>',
|
|
'<td class="flotr-legend-label">', label, '</td>'
|
|
);
|
|
}
|
|
if(rowStarted) fragments.push('</tr>');
|
|
|
|
if(fragments.length > 0){
|
|
var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join('') + '</table>';
|
|
if(legend.container){
|
|
D.insert(legend.container, table);
|
|
}
|
|
else {
|
|
var styles = {position: 'absolute', 'z-index': 2};
|
|
|
|
if(p.charAt(0) == 'n') { styles.top = (m + plotOffset.top) + 'px'; styles.bottom = 'auto'; }
|
|
else if(p.charAt(0) == 's') { styles.bottom = (m + plotOffset.bottom) + 'px'; styles.top = 'auto'; }
|
|
if(p.charAt(1) == 'e') { styles.right = (m + plotOffset.right) + 'px'; styles.left = 'auto'; }
|
|
else if(p.charAt(1) == 'w') { styles.left = (m + plotOffset.left) + 'px'; styles.right = 'auto'; }
|
|
|
|
var div = D.create('div'), size;
|
|
div.className = 'flotr-legend';
|
|
D.setStyles(div, styles);
|
|
D.insert(div, table);
|
|
D.insert(this.el, div);
|
|
|
|
if(!legend.backgroundOpacity)
|
|
return;
|
|
|
|
var c = legend.backgroundColor || options.grid.backgroundColor || '#ffffff';
|
|
|
|
_.extend(styles, D.size(div), {
|
|
'backgroundColor': c,
|
|
'z-index': 1
|
|
});
|
|
styles.width += 'px';
|
|
styles.height += 'px';
|
|
|
|
// Put in the transparent background separately to avoid blended labels and
|
|
div = D.create('div');
|
|
div.className = 'flotr-legend-bg';
|
|
D.setStyles(div, styles);
|
|
D.opacity(div, legend.backgroundOpacity);
|
|
D.insert(div, ' ');
|
|
D.insert(this.el, div);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
})();
|