Interactive Legends: allow labelFormatter to be a fn:txt->txt or fn:txt->jquery #311

Open
dnschnur opened this Issue Sep 28, 2012 · 7 comments

Comments

Projects
None yet
1 participant
Owner

dnschnur commented Sep 28, 2012

Original author: mathes....@gmail.com (October 07, 2009 17:21:14)

In order to make the legend interactive, I suggest allowing the labelFormatter
function to return either txt or a jquery object.

Example use case: Clicks on a label in the legend to toggle that plot on or off on
the current chart. You can certainly work around this by making your return value of
labelFormatter be something like this:

function labelFormatter (labelName) {
return '<span onclick="hideLabel(labelName);">' + ;
}

But you then have to make the hideLabel() function do some DOM lookups to figure out
which chart to toggle on or off as opposed to using closures to keep things lexically
local, which a full jquery object allows you to do, like this:

Chart.prototype.makeChartLegendLabel = function (tagName) {

var tagToggle = $('&lt;span&gt;' + tagName + '&lt;/span&gt;')
    .addClass('label')
    .addClass( this.inactivePlots[tagName] ? 'inactive' : 'active' )
;

var selfRef = this;
tagToggle.click(function() {selfRef.toggleTag(tagName);});

return tagToggle;

};

Original issue: http://code.google.com/p/flot/issues/detail?id=232

Owner

dnschnur commented Sep 28, 2012

From mathes....@gmail.com on October 07, 2009 17:22:54
Worth noting that I have a local modified version of flot that behaves exactly like
this, but it only works in some use cases. I haven't made it fully functional because
I'm using it for internal stats tracking tools, and we never use the broken cases.

Owner

dnschnur commented Sep 28, 2012

From mathes....@gmail.com on October 07, 2009 17:50:18
If it's helpful, here's the re-written loop that builds the

for the legend, using jquery object
creation:

var table = $('

');
for (i = 0; i < series.length; ++i) {
if (!series[i].label) {
continue;
}

if ( i % options.legend.noColumns == 0 ) {
    var currentRow = $('<tr></tr>');
    table.append(currentRow);
}

// use the raw label text or use the text or jquery object
// returned by the use-defined labelFormatter function
var label = series[i].label;
if (options.legend.labelFormatter != null) {
    label = options.legend.labelFormatter(label);
}

var legendColorBox = $(
    '<td class="legendColorBox">'
        + '<div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px">'
            + '<div style="width:14px;height:10px;background-color:' + series[i].color + 

';overflow:hidden">'
+ ''
+ ''
+ ''
);
var labelBox = $('').append(label);

currentRow.append(legendColorBox).append(labelBox);

}

Owner

dnschnur commented Sep 28, 2012

From olau%iol...@gtempaccount.com on October 21, 2009 19:42:49
Have you considered just doing a '' + value + '' then
$(".foo").click(...)? It seems less complex to me?

Owner

dnschnur commented Sep 28, 2012

From mathes....@gmail.com on October 21, 2009 20:31:01
That wouldn't work for my use case. I'ts less about having a jquery object and more
about having a full variable in javascript and all that gets you with closures and
attributes.

I'm using closures to do some OOP stuff with a Chart object wrapped around flot.
Specifically, clicking on the label needs to call a method on the Chart object to
turn the tag on/off. If I were to use the method you described, every label would all
call the same function. Perhaps on some labels different functions need to be called?
Would the .click() function be in the right closure?

I'd link to an example page, but this is for an internal stats reporting tool that's
behind a VPN. Here's an example screenshot:

http://imgur.com/CrF3Dl.png

Owner

dnschnur commented Sep 28, 2012

From p...@catalinatrading.com.au on May 11, 2010 06:36:32
I had the same problem, but with a little jquery magic, here may be the start of a
solution..
$("#placeholder table tr").click(function(){
alert($(this).children(":eq(1)").html());})
will alert the legend names

regards

Owner

dnschnur commented Sep 28, 2012

From erics...@gmail.com on April 21, 2011 18:47:35
To Toggle legend items (lines specifically) I just used this.
It depends upon the outer-divs of flot to have a class of 'graph',
and that the return object from $.plot(...) be stored with the div object.
Example:
$('.graph').each(function(){
// ... fetch your data and options
var p = plot( this, mydata, myoptions );
$(this).data('plot', p );

$('.legendColorBox').bind('click',function(){
    var i = $(this).parents('table').find('.legendColorBox').index(this);
    var g = $(this).parents('.graph');
    var p = $(g).data('plot');
    var d = p.getData();
    var show = d[i].lines.show;
    $(this).css('opacity', (show)? 0.25 : 1.0 );
    d[i].lines.show = (show) ? false: true;
    p.draw();
}); 

Perhaps someone could grow this into a proper plugin for all graph types?
Also note that, thus far, it seems to work 'most-of-the-time', but after a while the 'click' events no longer seem to fire. Haven't started to debug that one yet.

Owner

dnschnur commented Sep 28, 2012

From dnsch...@gmail.com on June 04, 2012 20:21:59
I don't see this as high priority, but I think it makes sense to keep this for consideration as an enhancement. We might solve this by adding parameters to labelFormatter, or introduce a new hook.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment