Skip to content
This repository

Create thresholds without creating extra plot points? #337

Open
dnschnur opened this Issue · 8 comments

1 participant

David Schnur
David Schnur
Owner

Original author: thelevyb...@gmail.com (November 12, 2009 02:25:10)

The threshold plugin is very useful, but the use of points to separate the
colors on either side of the limit creates problems when you want to
implement tooltips or anything else involving the point indexes.

There's ways to deal with this by manually calculating where these extra
points will be introduced, but I figured I would ask for advice. I haven't
found an easy solution in the code, but perhaps there is a private method
somewhere that I can use to automatically delete the threshold-created points.

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

David Schnur
Owner

From mathes....@gmail.com on November 12, 2009 18:02:28
I'm not sure if this answers your concern, but it seems like you're having trouble
implementing tooltips on something over/under the threshold?

From the opening comments to
http://flot.googlecode.com/svn/trunk/jquery.flot.threshold.js:


Internally, the plugin works by splitting the data into two series,
above and below the threshold. The extra series below the threshold
will have its label cleared and the special "originSeries" attribute
set to the original series. You may need to check for this in hover

events.

You basically get a pointer on the mouseover events to the original series if you
need to access things like the series' label.

David Schnur
Owner

From thelevyb...@gmail.com on November 12, 2009 22:34:28
I noticed the originSeries attribute, but it doesn't seem to be useful in practice.
Instead of data about the whole originSeries, what is needed for a hover event is an
attribute like originDataIndex that would preserve the point's original data index.
AFAIK the originSeries attribute offers no way of figuring out the original data
index of the point you are hovering on.

I tried to patch this in the threshold plugin, but my implementation so far seems to
be buggy. I'll update this thread with a patch once I get one ready.

David Schnur
Owner

From mathes....@gmail.com on November 13, 2009 16:38:10
Well, you get all the information about the series from the originSeries, you get all
the information about the point from the plot item:

Register the tooltip creator:


$.plot(this.chart, this.plotData, this.options);
// register the tooltip creater
var previousPoint = null;
var selfRef = this;
this.chart.bind("plothover", function (event, pos, item) {

    if (item) {
        if (previousPoint != item.datapoint) {
            previousPoint = item.datapoint;

            $("#tooltip").remove();
            selfRef.drawToolTip(item);
        }
    }
    else {
        $("#tooltip").remove();
        previousPoint = null;
    }
});

And then in the drawToolTip function:


Chart.prototype.drawToolTip = function(plotItem) {
// if the plot is a tag/stat below the threshold,
// then we have to handle a leaked abstraction by the
// graphing library:
// "Internally, the plugin works by splitting the data into two series,
// above and below the threshold. The extra series below the threshold
// will have its label cleared and the special "originSeries" attribute
// set to the original series. You may need to check for this in hover
// events. "
var series, belowTripValue;
if (plotItem.series.label) {
series = plotItem.series;
belowTripValue = false;
}
else {
series = plotItem.series.originSeries;
belowTripValue = true;
}

var screenX = plotItem.pageX;
var screenY = plotItem.pageY;
var tag = series.label;
var time = plotItem.datapoint[0];
var value = plotItem.datapoint[1];
David Schnur
Owner

From thelevyb...@gmail.com on November 18, 2009 00:15:29
Thanks! That was helpful. For my solution, I ditched my early kludgey attempt to
calculate the 'originDataIndex' I described above, and simply used the time value of
the item, since it's guaranteed to be unique and doesn't get messed up by the
threshold series splitting.

One last thing I'm wondering about is deleting these items on the threshold points,
since they're not real items and thus would be confusing to end users. You would have
to introspect on an item and check not only if it has the Y value of a threshold
level, but also that it's at the end of its current series...

David Schnur
Owner

From andrewg...@live.co.uk on November 08, 2011 10:33:00
I updated the "drawSeriesPoints" method in jquery.flot.js. This checks to see if each points is valid against the original data and removes the extra threshold points.

function drawSeriesPoints(series) {
function plotPoints(datapoints, radius, fillStyle, offset, shadow, axisx, axisy, symbol) {
var data,
thresholdBelow;

    if (series.originSeries) {
        data = series.originSeries.data,
                thresholdBelow = series.originSeries.threshold.below;
    }
    else {
        data = series.data;
    }

    var points = datapoints.points, ps = datapoints.pointsize;

    for (var i = 0; i < points.length; i += ps) {
        var x = points[i],
                    y = points[i + 1];

        if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
            continue;

        if (i % 2 === 0) {
            var isValid = false;

            if (!thresholdBelow || y < thresholdBelow) {
                for (var j = 0; j < data.length; j++) {
                    var value = data[j];

                    if (x == value[0] && y == value[1]) {
                        isValid = true;

                        data = data.slice(j + 1);

                        break;
                    }
                };
            }

            if (!isValid) {
                continue;
            }
        }

        ctx.beginPath();
        x = axisx.p2c(x);
        y = axisy.p2c(y) + offset;
        if (symbol == "circle")
            ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false);
        else
            symbol(ctx, x, y, radius, shadow);
        ctx.closePath();

        if (fillStyle) {
            ctx.fillStyle = fillStyle;
            ctx.fill();
        }
        ctx.stroke();
    }
}

ctx.save();
ctx.translate(plotOffset.left, plotOffset.top);

var lw = series.points.lineWidth,
            sw = series.shadowSize,
            radius = series.points.radius,
            symbol = series.points.symbol,
            datapoints = series.datapoints;

if (lw > 0 && sw > 0) {
    // draw shadow in two steps
    var w = sw / 2;
    ctx.lineWidth = w;
    ctx.strokeStyle = "rgba(0,0,0,0.1)";
    plotPoints(datapoints, radius, null, w + w / 2, true,
                        series.xaxis, series.yaxis, symbol);

    ctx.strokeStyle = "rgba(0,0,0,0.2)";

    plotPoints(datapoints, radius, null, w / 2, true,
                        series.xaxis, series.yaxis, symbol);
}

ctx.lineWidth = lw;
ctx.strokeStyle = series.color;
plotPoints(datapoints, radius,
                    getFillStyle(series.points, series.color), 0, false,
                    series.xaxis, series.yaxis, symbol);
ctx.restore();

}

David Schnur
Owner

From song.edm...@gmail.com on April 10, 2011 22:56:36
Still having this issue. Did anyone manage to bypass it?

David Schnur
Owner

From marc.hen...@gmail.com on January 14, 2011 06:56:58
Did you ever manage to delete the extra threshold points? I'm having this exact issue now!

David Schnur
Owner

From dnsch...@gmail.com on June 04, 2012 19:38:33
We need to review this and other plugins that insert extra points. They should be re-implemented to either not add points, or add them in such a way that we can easily identify them and filter them out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.