Drawing floating columns/bars in Flot

Leave a comment

Let me say first of all, that I mostly like Flot as a charting application. It provides a lot of charting functionality and is reasonably good looking.

But sometimes it is a bit of a pain to deal with. Case in point; I wanted to create a chart that had floating columns (Flot, in my opinion incorrectly, calls vertical columns, bars). In essence, what I wanted was this:

2016-04-25_2000

Well, it can be done but, after I spent far too many hours trying to figure out how, it is not exactly clear how to do it.

The first thing I learned was that the data format for a bar is the opposite of what one would intuitively expect.  That doesn’t mean that it’s wrong (it make sense in retrospect), it’s just not intuitive.

If you want to float a bar/column in Flot you do it in the following format:

[[index, max, min]]

I had figured that min would come before max.  But that does not.

But that does not completely solve the problem because Flot does not allow you to control how the bottom bar is rendered; it is automatic.  And that automatic rendering removes the bottom border with no option to force it.  The result of the previous JavaScript array is:

2016-04-25_2005

That’s not horrible, but the lack of a bottom looks a little cheap.  The solution?  Create a second item in your dataset like this:

[[index, max, min]],
[[index, min, min]]

It feels a little dirty but it works.  You are creating a 1px border by putting another column with no height immediately below your column.  This is the result:

2016-04-25_2000


Webview orientation with Phonegap

1 Comment

I was having this really weird problem in PhoneGap where when the orientation would change the webview would not resize to fit the whole screen.  Turns out that the meta viewport tag was causing the problem.  My viewport setting was this:

1
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>

So when I would re-orient my iPad to landscape it would still be using the device-width setting for its width.  So what I did was bind to the orientationchange event and call a JavaScript function each time the page re-oriented.  That function had this code in it.

1
2
3
4
5
6
var el = $('meta[name=viewport]');
if (window.orientation == 90 || window.orientation == -90) {
el.attr('content', 'width=device-height');
} else {
el.attr('content', 'width=device-width');
}

Now the orientation works in both portrait and landscape.


Get viewport size width and height with javascript – Javascript – Blog / Andy Langtons Website

Leave a comment

Get viewport size width and height with javascript – Javascript – Blog / Andy Langtons Website.

This is a neat little snippet of JavaScript code to get the size of your viewport on a browser.  I’m doing some work with progressive HTML rendering and viewport height is pretty important there.  This seems to  work.  Will be having a longer blog post coming up on the topic of progressive rendering.


Transform performance on mobile applications

Leave a comment

Just a quick one today.  I have read on several web pages that if you want to speed up the rendering of your site that you need to add -webkit-transform: translate3d(0,0,0) to the page elements to have the browser use the GPU to render the page instead of the CPU.

I tried this trick several times and it never seemed to work.  But I think that today I figured out why not.

I would apply this trick to a container element that houses the things that were animating.  This may not seemed to have been the correct way of doing it.  I had a DIV with a UL and several LI elements in it.  I applied the trick to the DIV under the assumption that it would accelerate everything in the container.

I think I was wrong.  It almost looks like you need to apply the trick to the individual element that you are animating.  In my case, the LI elements because they start out with a height of 0px and are expanded to Xpx.  The animations worked fine beforehand, but as soon as it was coupled with automated scrolling of the container the performance would drop tremendously down to around 6-8 frames per second.  When I moved the translate3d() trick from the DIV to the LI elements the animations and the scrolling became quite smooth.

So the lesson of the day is that if you want to use the GPU trick, apply it directly to the elements you are animating and not their container.

Additionally, it seems like applying the GPU trick also messes up CSS fixed position elements.  In other words, position: fixed ends up being not so.


Handling clicks for mobile platforms [UPDATED]

1 Comment

I’ve been doing a lot of work in Phonegap lately and I really like it.  However, one of the things I don’t like is that click events are really, really slow.  There’s a reason for this.  How does the browser know if it’s a click or the beginning of a move?  The answer to this is to bind your click events to the “touchend” event.

So, in JQuery you would previously do something like this.

1
target.bind('click', callback);

But that introduces the lag.  So I wrote a little function where instead of calling bind() I would call this function instead.  It would determine if it’s a desktop or mobile device and then either register the click event or the touchend event.

However, there is a problem with this.  The touchend call might come at the end of a move, in which case you don’t want to fire the click event’s callback.  So I wrote a little bit of code that checks for a move event and then unbinds the touchend event, storing the callback in the new function called at touchend.  If there is no move event the callback is called at touchend.  If the move event is not thrown the callback is re-bound at touchend so the next time a “click’ event is triggered the event will be there to handle it.

1
2
3
4
5
6
7
8
9
target.bind('touchmove', function() {
  var cb = callback;
  $(this).unbind('touchend', cb);
  $(this).bind('touchend', function() {
    var cbb = cb;
    $(this).bind('touchend', cbb);
    });
  });
target.bind('touchend', callback);

[EDIT]

It turns out that this is wrong.  One of the things that I neglected to see offhand was that this code was fine… IF only one touchmove event was fired.  However, if many were fired the callback would be added for each time touchmove was called.  If your finger was moving a lot, then a lot of calls to the callback would be executed on touch end.

Here is code that actually works properly.

1
2
3
4
5
6
7
8
9
10
11
12
target.bind('touchmove', function() {
  $(this).data('moved', true);
});
target.bind('touchend', function() {
  if ($(this).data('moved')) {
    $(this).data('moved', false);
    return;
  }
  $(this).data('moved', false);
  $(this).trigger('touchendnomove');
});
target.bind('touchendnomove', callback);

What this does differently is simply set a flag if a touchmove event is fired.  Then on touchend it checks to see if the flag has been set.  If not a CUSTOM event is fired.  This is important because we want $(this) to refer to the target when an event is fired.  This way we don’t have to do any magic to get the proper “this” association done and we don’t have the problem of those pesky touchmove events.