neolite / flot

Automatically exported from code.google.com/p/flot
MIT License
0 stars 0 forks source link

Flot with Overview and Crosshair not working properly #542

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
Hi guys! Maybe this is a bug (maybe not :-)

I'm mashing up the samples and found out that my plot is not working properly 
when using Crosshair, and Overview chart and series selection.

Here's the problem: Crosshair with label's update works fine when the page 
loads, but whenever I change zoom in the #placeholder plot, the crosshair 
doesn't update the series' labels. I debugged all the way to the text extend in 
jQuery 1.5.1 and the replacements are working fine. But something happens and 
the labels are not refreshed. 

Here's the code:

    $(function () {

        var dates = $( "#desde, #hasta" ).datepicker({
                                            defaultDate: "+1w",
                                            changeMonth: true,
                                            numberOfMonths: 3,
                                            onSelect: function( selectedDate ) {
                                                var option = this.id == "desde" ? "minDate" : "maxDate",
                                                    instance = $( this ).data( "datepicker" ),
                                                    date = $.datepicker.parseDate(
                                                        instance.settings.dateFormat ||
                                                        $.datepicker._defaults.dateFormat,
                                                        selectedDate, instance.settings );
                                                dates.not( this ).datepicker( "option", option, date );
                                            }
                                        });

        var datasets = {
                        "activa": {
                            label: "Potencia Activa Total = 0.00",
                            color: 0,
                            data: @Model.DataActiva,
                            lines: { show: true }
                                },        
                        "contratada": {
                            label: "Contratada = 0.00",
                            color: 1,
                            data: @Model.Contratada,
                            lines: { show: true }
                                },
                        "fase1": {
                            label: "Potencia Activa Fase I = 0.00",
                            color: 2,
                            data: @Model.DataFase1,
                            lines: { show: true }
                                },
                        "fase2": {
                            label: "Potencia Activa Fase II = 0.00",
                            color: 3,
                            data: @Model.DataFase2,
                            lines: { show: true },
                                },
                        "fase3": {
                            label: "Potencia Activa Fase III = 0.00",
                            color: 4,
                            data: @Model.DataFase3,
                            lines: { show: true },
                                }
                        };

        var choiceContainer = $("#choices");
        $.each(datasets, function(key, val) {
            choiceContainer.append('<br/><input type="checkbox" name="' + key +
                               '" checked="checked" id="id' + key + '">' +
                               '<label for="id' + key + '">'
                                + val.label + '</label>');
        });

        choiceContainer.find("input").click(plotAccordingToChoices);

        // first correct the timestamps - they are recorded as the daily
        // midnights in UTC+0100, but Flot always displays dates in UTC
        // so we have to add one hour to hit the midnights in the plot
        //for (var i = 0; i < d.length; ++i)
        //    d[i][0] += 60 * 60 * 1000;

        // helper for returning the weekends in a period
        function weekendAreas(axes) {
            var markings = [];
            var d = new Date(axes.xaxis.min);
            // go to the first Saturday
            d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 1) % 7))
            d.setUTCSeconds(0);
            d.setUTCMinutes(0);
            d.setUTCHours(0);
            var i = d.getTime();
            do {
                // when we don't set yaxis, the rectangle automatically
                // extends to infinity upwards and downwards
                markings.push({ xaxis: { from: i, to: i + 2 * 24 * 60 * 60 * 1000} });
                i += 7 * 24 * 60 * 60 * 1000;
            } while (i < axes.xaxis.max);

            return markings;
        }

        var options = {
            xaxis:      { mode: "time", tickLength: 5, tickDecimals: 0 },
            selection:  { mode: "x" },
            yaxis:      { min: 0 },
            zoom:       { interactive: true },
            crosshair:  { mode: "x" },
            grid:       { markings: weekendAreas, hoverable: true, autoHighlight: false  }
        };

        var plot = null;

        function plotAccordingToChoices()
        {
            var data = [];

            choiceContainer.find("input:checked").each(function () {
                var key = $(this).attr("name");

                if (key && datasets[key])
                    data.push(datasets[key]);
            });

            if (data.length > 0)
            {
                plot = $.plot($("#placeholder"), data, {
                    xaxis: { mode: "time" },
                    yaxis: { min: 0 },
                    selection:  { mode: "x" }, 
                    crosshair: { mode: "x" },
                    grid: { hoverable: true, autoHighlight: false },
                    lines: { show: true, lineWidth: 1 }
                }, options);

                var overview = $.plot($("#overview"), data, {
                    series: {
                        lines: { show: true, lineWidth: 1 },
                        shadowSize: 0
                    },
                    legend: { show: false},
                    xaxis: { mode: "time" },
                    yaxis: { min: 0 },                 
                    selection: { mode: "x" }
                }, options);

                $("#placeholder").bind("plotselected", function (event, ranges) {
                    // do the zooming
                    plot = $.plot($("#placeholder"), data,
                              $.extend(true, {}, options, {
                                  xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to }
                              }));

                    // don't fire event on the overview to prevent eternal loop
                    overview.setSelection(ranges, true);
                });

                $("#overview").bind("plotselected", function (event, ranges) {
                    plot.setSelection(ranges);
                });
            }

            $('#zoomOut').click(function (e) 
            {
                 e.preventDefault();
                 plot.zoomOut();
            });

            var today = new Date();
            var yesterday = new Date();

            yesterday.setDate(today.getDate() - 1);

            $("#24horas").click(function () {
            plot = $.plot($("#placeholder"), data, 
                    {
                        xaxis: {
                            mode: "time",
                            min: yesterday.getTime(),
                            max: today.getTime()
                                },
                        yaxis: { min: 0 },
                        crosshair: { mode: "x" },
                        selection:  { mode: "x" }, 
                        grid: { hoverable: true, autoHighlight: false },
                        lines: { show: true, lineWidth: 1 }
                    });
            });

            $("#rango").click(function () {

                var from = Date.parse($("#desde").val());
                var to = Date.parse($("#hasta").val());

                plot = $.plot($("#placeholder"), data, 
                    {
                        xaxis: {
                            mode: "time",
                            min: from.getTime(),
                            max: to.getTime()
                                },
                        yaxis: { min: 0 },
                        crosshair: { mode: "x" },
                        selection:  { mode: "x" }, 
                        grid: { hoverable: true, autoHighlight: false },
                        lines: { show: true, lineWidth: 1 }
                    });
            });

            $("#todo").click(function () {
                plot = $.plot($("#placeholder"), data, {
                    xaxis: { mode: "time" },
                    crosshair: { mode: "x" },
                    grid: { hoverable: true, autoHighlight: false },
                    yaxis: { min: 0 },
                    selection:  { mode: "x" }, 
                    lines: { show: true, lineWidth: 1 }
                }, options);
            });

        }

        plotAccordingToChoices();

        // Crosshair
        var legends = $("#placeholder .legendLabel");

        legends.each(function () {
            // fix the widths so they don't jump around
            $(this).css('width', $(this).width());
        });

        var updateLegendTimeout = null;
        var latestPosition = null;

        function updateLegend() {
            updateLegendTimeout = null;

            var pos = latestPosition;

            var axes = plot.getAxes();
            if (pos.x < axes.xaxis.min || pos.x > axes.xaxis.max ||
                pos.y < axes.yaxis.min || pos.y > axes.yaxis.max)
                return;

            var i, j, dataset = plot.getData();

            for (i = 0; i < dataset.length; ++i) {
                var series = dataset[i];

                // find the nearest points, x-wise
                for (j = 0; j < series.data.length; ++j)
                    if (series.data[j][0] > pos.x)
                        break;

                // now interpolate
                var y, p1 = series.data[j - 1], p2 = series.data[j];
                if (p1 == null)
                    y = p2[1];
                else if (p2 == null)
                    y = p1[1];
                else
                    y = p1[1] + (p2[1] - p1[1]) * (pos.x - p1[0]) / (p2[0] - p1[0]);

                legends.eq(i).text(series.label.replace(/=.*/, "= " + y.toFixed(2)));
            }
        }

        $("#placeholder").bind("plothover",  function (event, pos, item) {
            latestPosition = pos;

            if (!updateLegendTimeout)
                updateLegendTimeout = setTimeout(updateLegend, 50);
        });

    });

Original issue reported on code.google.com by sebastia...@gmail.com on 26 May 2011 at 11:28

GoogleCodeExporter commented 8 years ago
Hi!

I appreciate you took the time to report this, but I suggest you either spend a 
bit more time debugging it or take it to the forum/mailing list and see if you 
can get some more eyes to look at it there. I don't have time to debug it 
unless it's pretty clear there's a bug in Flot and I'm afraid at this stage 
with so much code, it's not so clear yet. :)

Original comment by olau%iol...@gtempaccount.com on 3 Jun 2011 at 4:44

GoogleCodeExporter commented 8 years ago

Original comment by dnsch...@gmail.com on 4 Jun 2012 at 9:17

GoogleCodeExporter commented 8 years ago

Original comment by dnsch...@gmail.com on 10 Jul 2012 at 11:41

GoogleCodeExporter commented 8 years ago
Has anybody looked into this issue yet? I came across a similar problem. 
Whenever I change the values after initial display, the values are not updated 
in the legend anymore. Debugging shows that interpolation is done properly. 
When passing the values to legends.eq(i).text(series.label.replace(/=.*/, "= " 
+ y.toFixed(2))); they get lost.

To make this easier to reproduce, I took the tracking.html example and added a 
button to change the data of the sine curve:
<input class="changeData" type="button" value="Change data">

$("input.changeData").click(function () {
    for (var i = 0; i < 140; i++) {
        sin[i][1] = sin[i][1]*1 + 0.1;
        }
    plot = $.plot($("#placeholder"),
                      [ { data: sin, label: "sin(x) = -0.00"},
                        { data: cos, label: "cos(x) = -0.00" } ], {
                            series: {lines: { show: true }},
                            crosshair: { mode: "x" },
                            grid: { hoverable: true, autoHighlight: false },
                            yaxis: { min: -1.2, max: 1.2 }
                        });
    });
It also happens when I create a single data structure that contains both arrays 
of values (sin and cos).

In my application on http://www.sl-naturenergie.de/datalogs/test/showdata.html, 
I am displaying data from a photovoltaics installation. You can change date and 
load the data of this new day, i.e. there is no way around manipulating the 
data after the initial display, is there?

Thanks,
Stefan

Original comment by Stefan.L...@sl-naturenergie.de on 26 Dec 2012 at 11:40