wildanSawaludin / flot

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

Keeping extra info with each point #121

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Hey,
until recently you used the data that came from javascript directly. This
was very clean and extended functionality in many ways not conceived by the
original flot creators.

For example, I make use of that to point a third data on every datapoint,
in order to give a unique pk (pk=primary key) to every value. Then I can
attach click functionality using this data, or make use of it in custom
point drawing. 

Check my patch for custom point drawing, and then this function which i use
to draw bigger circles with labels for a certain subset of points:

function drawPoint(ctx,x,y,radius,plotOffset,dataitem,series) {
pk=dataitem[2];
if (eval(has_comments) && pk in comments) {
        ctx.arc(x, y, radius*3, 0, 2 * Math.PI, true);
        var seconddigit = commentCounter%26;
        var firstdigit = Math.floor(commentCounter/26);
        if (firstdigit > 26) {
                firstdigit = firstdigit%26;
        };
        var label =''
        if (firstdigit > 0) {
                label+= String.fromCharCode(firstdigit+96);
        };
        label+= String.fromCharCode(seconddigit+97);
        commentCounter+=1;
        var comments_text="";
        for (var i=0; i<comments[pk].length; i++) {
                comments_text+="<p>"+comments[pk][i][0]+"</p>";
                comments_text+="<p
class=\"signature\">"+comments[pk][i][1]+"</p>";
        };

        $("#"+query_id+"comments").append("<tr class=\"comment\"><td
valign=\"top\"><b>"+label+"</b></td><td valign=\"top\">"+comments_text+"</td>$
        var div = $('<div class="pointLabel"
id="'+pk+'">'+label+'</div>').insertAfter(this);
        var labelwidth= $('#'+pk).outerWidth();
        var leftOffset = plotOffset.left - (labelwidth/2) +.5;
        this.next().css({
            top: y,
            left: leftOffset +x,
          });
    this.next().bind("click", function () {
       if (!(comment_form_open)) {
            var theDate = new Date(dataitem[0]);
            var date = theDate.toDateString();
            var label=series.label;
            if (label=='') {
                label='producto';
            };
            create_comment_form(dataitem[2],label,dataitem[1],date);
        };
        });

} else {
        ctx.arc(x, y, radius, 0, 2 * Math.PI, true);
};
}

Original issue reported on code.google.com by johanneswilm on 1 Mar 2009 at 6:52

GoogleCodeExporter commented 9 years ago

Original comment by johanneswilm on 1 Mar 2009 at 6:58

Attachments:

GoogleCodeExporter commented 9 years ago
Neat screenshot!

You can still access the original data, it's in the series[i].data array 
instead of
the series[i].datapoints.points array. At some points Flot has to support 
copying
more coordinates anyway so your hack might work then.

Also, no matter what you can always do something like this by maintaining a map 
from
something that identifies the points uniquely to the primary keys, e.g. (x,y) or
(series index, data array index) (you could concatenate them to a string with a 
':'
in between). That's what I would have done in the first place.

I can't guarantee that internal data structures will stay the same, and there 
are
good reasons for abandoning the old model. One being that erratic input data is
propagated through-out Flot and may result in weird errors later on (I have 
gotten
quite a few reports on that kind of thing), another being that there's some
low-hanging fruit to be picked by simple input transformations.

Hope this answers your complaint.

Original comment by olau%iol...@gtempaccount.com on 1 Mar 2009 at 9:17

GoogleCodeExporter commented 9 years ago
Hmm, well the data needs to be send with pk-value from the server, because the 
graph
has the ability to add comments. So a translation would need to be calculated
client-side, and it would need to be updated for every comment that is add or 
deleted. 
I am no expert on javascript resource usage, but that seems like kind of waste 
of
programing time and computer calculation time.

So until future patches make it possible for our patch to work again like you
mention, I think we'll have to stick with revision 136.

Original comment by johanneswilm on 1 Mar 2009 at 11:51

GoogleCodeExporter commented 9 years ago
Hey, I looked through your sure code to see whether it would be possible to 
somehow
add a label for each datapoint again. However, it seems like you have switched 
to an
unusually complicated way of storing the datapoints.

First, you recover the data from the source:

    x = data[j][0];
    y = data[j][1];

The x and y values seem to be stored in one single long list like this:

points[k + 1] = y;
points[k] = x;

And then to get them out, you simply pick every other to get the x-values, and 
every
other to pick the y-value:

var x1 = points[i - incr], y1 = points[i - incr + 1],
    x2 = points[i], y2 = points[i + 1];

Is there a point to that, or did it just seem the easiest?

why not instead store them as a list in a list like this:

points[k] = [x,y];

then you could read them like this

var x1 = points[i - incr][0], y1 = points[i - incr][1],
    x2 = points[i][0], y2 = points[i][1];

And it would be relatively easy to add other data as with a simple patch, like 
this:

-points[k]=[x,y];
+    id = data[j][2];
+points[k]=[x,y,id];

And while the recovery of the main data would be the same:

var x1 = points[i - incr][0], y1 = points[i - incr][1],
    x2 = points[i][0], y2 = points[i][1];

The id would easily be found like this:

var id1 = points[i - incr][2], id2 = points[i][2]

Of course the increment of i would have to be halved both in storing and 
recovering
data. 

Now we need to store an id with every data. But I've seen another patch on the 
web
that's trying to just set single flags on some data points. I am sure there is 
quite
a lot of stuff people may want to associate with a datapoint directly, and so it
would really be great if Flot would be programmed in a way that would allow for
patches to add such functionality easily.

But maybe there is a good reason for why you need all the data in just one long 
list?

Original comment by johanneswilm on 2 Mar 2009 at 2:33

GoogleCodeExporter commented 9 years ago
I timed it last Friday, and on Firefox the old arrays-in-arrays representation 
was
about 10 times slower to construct. I have some users with very large datasets 
where
this overhead is not negligible. So that's why.

I appreciate that you have something working right now, but I don't think it's 
that
hard to port over. There are plenty of options. As I mentioned, if you don't 
want to
change the mapping around, you still have access to the original data in the 
series.
So you could just lookup your pk with a slight modification of your point 
drawing
callback change.

Original comment by olau%iol...@gtempaccount.com on 2 Mar 2009 at 2:54

GoogleCodeExporter commented 9 years ago
I think this issue has morphed into a "would like an easy way to associate 
extra data
with each point". For anyone interested, this should be relatively easy to add 
to
Flot by adding a little bit of API and fixing the (hardcoded, half-baked) way 
point
size is currently determined, take a look in processData.

Original comment by olau%iol...@gtempaccount.com on 25 May 2009 at 7:46

GoogleCodeExporter commented 9 years ago
I tried to create an extra work around by putting an extra json variable series 
called extra. The only Issue I'm having is linking the variable number for 
extra extra[#] with the datapoints.  

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

                    $("#tooltip").remove();
                    var x = item.datapoint[0].toFixed(2),
                        y = item.datapoint[1].toFixed(2);

                    if(item.series.label == 'Breakfast - Your Rating')
                            {
                                showTooltip(item.pageX, item.pageY,
                                item.series.label + " of " + x + " = " + y + ' & Item.extra = ' + item.series.extra[0]); //this is the line I'm talking about.  Is there a variable here that would link me to the data that's in x and y?  
                            }
                        else if(item.series.label == 'Breakfast - Food Markit Rating')
                        {
                                showTooltip(item.pageX, item.pageY,
                                item.series.label + " of " + x + " = " + y);
                        }
                }
            }

Bob

Original comment by rcave...@gmail.com on 22 Jul 2010 at 4:28

GoogleCodeExporter commented 9 years ago
Solved my issue, here's what I did...

Sent 2 extra values to the page along with extra(to store message): extray, and 
extrax (to check against x and y coordinates on the graph) and use a counter to 
retrieve the index for extra.  
                                $.each(item.series.extra, function(){
  if(x==(item.series.extrax[counter]+'.00'))
  {
    if(y==(item.series.extray[counter]+'.00'))
    {
      showTooltip(item.pageX, item.pageY,'Extra value will be'+item.series.extra[counter]);
    }
  }
  counter++;
});

I'm sure it's not the most efficient way to solve this issue, but solved for my 
needs. 

Original comment by rcave...@gmail.com on 22 Jul 2010 at 9:02

GoogleCodeExporter commented 9 years ago
you can use item.dataIndex to get the index of the data point corresponding to 
the x,y postion on the graph:

            showTooltip(item.pageX, item.pageY, item.series.tooltip[item.dataIndex]);

where tooltip is an extra array (corresponding to extras in the above example) 
of the comments you want to display in the tooltip.

Original comment by aromo...@gmail.com on 28 Sep 2010 at 10:32

GoogleCodeExporter commented 9 years ago
This is all possible in Flot right now; just not super-easy.  I'm treating this 
as an enhancement request for spending some time to investigate alternatives 
that would make this simpler without sacrificing performance.

Original comment by dnsch...@gmail.com on 7 May 2012 at 11:07

GoogleCodeExporter commented 9 years ago
Issue 176 has been merged into this issue.

Original comment by dnsch...@gmail.com on 7 May 2012 at 11:08

GoogleCodeExporter commented 9 years ago
    function redrawplot() {
       $('.tt1').remove();
       var points = plot.getData();
         var graphx = $('#placeholder').offset().left;
         graphx = graphx + 30; // replace with offset of canvas on graph
         var graphy = $('#placeholder').offset().top;
         graphy = graphy + 10; // how low you want the label to hang underneath the point
         for(var k = 0; k < points.length; k++){
              for(var m = 1; m < points[k].data.length-1; m++){
                if(points[k].data[m][0] != null && points[k].data[m][1] != null){
                      if ((points[k].data[m-1][1] < points[k].data[m][1] && points[k].data[m][1] > points[k].data[m+1][1]) && (points[k].data[m-1][1] - points[k].data[m][1] < -50 || points[k].data[m][1] - points[k].data[m+1][1] > 50)) {
                                     showTooltip1(graphx + points[k].xaxis.p2c(points[k].data[m][0]) - 15, graphy + points[k].yaxis.p2c(points[k].data[m][1]) - 35,points[k].data[m][1], points[k].color);
                  }
                                  if ((points[k].data[m-1][1] > points[k].data[m][1] && points[k].data[m][1] < points[k].data[m+1][1]) && (points[k].data[m-1][1] - points[k].data[m][1] > 50 || points[k].data[m][1] - points[k].data[m+1][1] < -50)) {
                                     showTooltip1(graphx + points[k].xaxis.p2c(points[k].data[m][0]) - 15, graphy + points[k].yaxis.p2c(points[k].data[m][1]) + 2,points[k].data[m][1], points[k].color);
                                  }
                                }
            }
          }

     }

 function showTooltip1(x,y,contents, colour){
      $('<div class=tt1 id="value">' +  contents + '</div>').css( {
            position: 'absolute',
            display: 'none',
            top: y,
            left: x,
            'border-style': 'solid',
            'border-width': '2px',
            'border-color': colour,
            'border-radius': '5px',
            'background-color': '#ffffff',
            color: '#262626',
            padding: '0px',
            opacity: '1'
      }).appendTo("body").fadeIn(200);
 } 

Original comment by mail.ako...@gmail.com on 1 Feb 2013 at 10:16