(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, 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: '#F0F0F0', // => Legend background color. backgroundOpacity: 0.85// => set to 0 to avoid background, set to 1 for a solid background }, callbacks: { 'flotr:afterinit': function() { this.legend.insertLegend(); }, 'flotr:destroy': function() { var markup = this.legend.markup; if (markup) { this.legend.markup = null; D.remove(markup); } } }, /** * 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, opacity = legend.backgroundOpacity, i, label, color; if (itemCount) { var lbw = legend.labelBoxWidth, lbh = legend.labelBoxHeight, lbm = legend.labelBoxMargin, offsetX = plotOffset.left + m, offsetY = plotOffset.top + m, labelMaxWidth = 0, style = { size: options.fontSize*1.1, color: options.grid.color }; // We calculate the labels' max width 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); // Default Opacity if (!opacity && opacity !== 0) { opacity = 0.1; } if (!options.HtmlText && this.textEnabled && !legend.container) { if(p.charAt(0) == 's') offsetY = plotOffset.top + this.plotHeight - (m + legendHeight); if(p.charAt(0) == 'c') offsetY = plotOffset.top + (this.plotHeight/2) - (m + (legendHeight/2)); if(p.charAt(1) == 'e') offsetX = plotOffset.left + this.plotWidth - (m + legendWidth); // Legend box color = this.processColor(legend.backgroundColor, { opacity : opacity }); 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 ? '' : ''); rowStarted = true; } var s = series[i], boxWidth = legend.labelBoxWidth, boxHeight = legend.labelBoxHeight; 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( '', '
', '
', // Border '
', // Background '
', '
', '', '', label, '' ); } if(rowStarted) fragments.push(''); if(fragments.length > 0){ var table = '' + fragments.join('') + '
'; if(legend.container){ table = D.node(table); this.legend.markup = table; D.insert(legend.container, table); } else { var styles = {position: 'absolute', 'zIndex': '2', 'border' : '1px solid ' + legend.labelBoxBorderColor}; if(p.charAt(0) == 'n') { styles.top = (m + plotOffset.top) + 'px'; styles.bottom = 'auto'; } else if(p.charAt(0) == 'c') { styles.top = (m + (this.plotHeight - legendHeight) / 2) + '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 (!opacity) return; var c = legend.backgroundColor || options.grid.backgroundColor || '#ffffff'; _.extend(styles, D.size(div), { 'backgroundColor': c, 'zIndex' : '', 'border' : '' }); 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, opacity); D.insert(div, ' '); D.insert(this.el, div); } } } } } }); })();