Articles tagged: javascript

Drawing directions with canvas and JavaScript

1472 days ago

One of the debug pages that I work with regularly is a HTML page full of tables of statistics. Some of the statistics are ranges for wind directions. My workmate commented that he would like some indication of the direction in words (like “N” for north), as constantly calculating if 230 is closer to 180 or 270 is unnecessarily tiresome. I thought about it for a while and thought, surely there must be a way using HTML/JavaScript to actually visually represent these ranges. Then one could easily look at a row of statistics and see if the numbers were swinging westerly or easterly.

First I tried poking around to see if anyone had done anything similar. I couldn’t find anything, although I found plenty of clocks. Close but no cigar.

With a bit more reading I realised I could do it quite directly and elegantly using the famed canvas element in HTML5. Which, you know, is here now. So, let’s see…

After some clicking…

I’m sure there are other fancy things that one could do, like putting coloured lines to indicate the start and end direction (in case your directions go backwards), and maybe putting an image in the background with a “N” at the top, just in case you are prone to forgetting. But I am pretty happy with the couple of hours work to get these looking as they do.

The screenshots are from an example page I put together to put up on Bitbucket: canvasdirections. You can look at or download the JavaScript from there. Is there something I can do so the HTML page can be viewed directly in the Bitbucket web interface? I couldn’t figure out how to do that.

It’s my first time using Bitbucket. I started using Mercurial at work for my own little projects a couple of months ago. I’ve used Bazaar for my little projects at home in the past, and I’ve been reasonably impressed with Launchpad, but Bitbucket seems to have a lot of fans so I doubt I will mind too much. I am not sure which I will end up using. This time I just happened to reach for hg. It would be nice if Bitbucket knew about having multiple email addresses, but then, it would be nice if bzr was smarter about symlinks, so hey, you can’t have everything.

tags: , , ,

Comment

---

Frogspotter v4 and GGD Afternoon Hack

1616 days ago

Today was the second GGD Afternoon Hack. We had six women show up for some Saturday arvo social hacking, with projects ranging from learning Rails, exploring Zend, trying out some Golog style Prolog…and I was working on my JavaScript for frogspotter, following on from the MelHack event last week.

Although frogspotter doesn’t look too different, I managed to get the check boxes and cluster markers working correctly, and do some nice Flickr images (see below). And now you don’t need to zoom in too far before it switches to individual markers.

One problem came from the fact that the library actually had a bug! I was starting to think I was going mad, so I was happy to find it actually was a problem with the library and not with me. The bug report says “fixed in dev” so I tried to find the dev branch so I could reference that file instead of 1.0. I was using http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/src/markerclusterer.js and from poking around here I just could not find the development code. After some more searching and clicking I realised they had moved their project and the development was now at http://gmaps-utility-library-dev.googlecode.com/svn/trunk/markerclusterer/src/markerclusterer.js. Rather subtle.

Getting the Flickr images in the pop-ups was really a trial. Note: my approach here was purely naive, to see if I could make it work. I will likely rewrite it so that Python gets and stores the images, to save 30-odd calls to the Flickr API on every page load (!). Doing that will also be far simpler than that JavaScript approach below, so I only put this as a cautionary tale…!

Pop-ups themselves are simple:

var html = '<b>' + spotting.name + '</b><br/><a href="' + url + '">' + spotting.specy + "</a><br/>" ;
marker.openInfoWindowHtml(html);

Querying Flickr was quite easy, once I decided to start using jQuery.

   $.getJSON(
		"http://api.flickr.com/services/rest/?jsoncallback=?",
		{ method : "flickr.photos.search",
			api_key : flickr_key,
			format : "json",
			text : specy,
			sort : "relevance",
			per_page: 1
			},
		callbackwrapper(specy, id)
    );

(“Specy” is my backformed singular of “species”.) So as you can see I just get the first most relevant image from Flickr by giving it the species name to search on. The “$” means the results get stored in some magical jQuery place. NO REALLY.

The problem is…the HTML in the pop-ups is not, AFAIK, a normal part of the page that jQuery might know about. And jQuery really likes to hang off existing stuff in the page rather than just return a string of HTML. So there didn’t seem to be any way I could get a plain old return value back from that json query.

After a bit of thought, I decided that I would put the image HTML in some hidden divs on the page, which the pop-ups could then display. That was it was easy for jQuery to store and also accessible for the pop-up.

So now I have this:

function getFlickrImage(specy) {
    var id = specyToID(specy);
    var html = '<div id="' + id + '"></div>';  //holder for flickr image;
    $("#speciesimages").append(html);
    $("#" + id).hide();
    $.getJSON(
		"http://api.flickr.com/services/rest/?jsoncallback=?",
		{ method : "flickr.photos.search",
			api_key :  flickr_key,
			format : "json",
			text : specy,
			sort : "relevance",
			per_page: 1
			},
		callbackwrapper(specy, id)
    );
}

$(”#foo”) is a cool jQuery short-hand for “find the element with the id foo.” So in my HTML page, I simply added <div id="speciesimages"></div> and with this call, I put one div per species inside it.

specyToID is also very simple:

function specyToID(specy) {
    return specy.replace(" ","-").replace(".","");
}

I spent waaaaaay too long trying to figure out why nothing was happening, not realising that spaces and full stops are not valid in CSS identifiers. Bah! JavaScript accepts whatever you throw at it, why not CSS?! ;)

Now the only mystery left is callbackwrapper(specy, id).

function callbackwrapper(specy, id) {
 return function( data, status) {
    var small_url = "";
    var photo_url = "";
    $.each(data.photos.photo, function(photoIdx, photo) {
	    // Build the thumbnail url
	    small_url = ["http://farm", photo.farm, ".static.flickr.com/", 
			photo.server, "/", photo.id, "_", photo.secret, "_s.jpg"].join("");
	    // Build the photo url
	    photo_url = ["http://www.flickr.com/photos/", 
			photo.owner, "/", photo.id].join("");
	});
    imagehtml = '<a href="' + photo_url + '" target="_blank"><img src="' + small_url + '" width=75 height=75 border=0 /></a>'; 
    $('#' + id).append(imagehtml);
  }
}

(Hm, and I can see now that I don’t even need to pass in specy!)

The each bit above is pretty hacky, because I know I’m only going to get one result. jQuery also really likes those “each” pseudo loop constructions… it was easier to use that than figure out a more accurate syntax.

getJSON is one of jQuery’s AJAX functions. It was a hard lesson for me (and lots of other newbies, from the looks of Google) to remember that the first A in AJAX is asynchronous. So when you call getJSON, you actually call it with three bits: a URL, a set of parameters and values for the URL, and a “callback” function. It seems the callback function will be executed at some time of jQuery’s choosing (hence asynchronous).

The main difficulty with the callback function is that it’s not very straightforward to pass extra data items to it. See the “data” and “status” arguments? I don’t really know how JavaScript or jQuery knows what their values are, but somehow it does. data is what comes back from the getJSON query. But how do I find what my original search term was when it comes time for this function to be executed? Because in my case I want to add a div with an identifier for that.

So there’s this wrapper thing. All I really know is, doing it this way WORKS. Don’t touch the second line. You will regret it.

It seems so simple in the retelling. But figuring this much out was painful. :) You can read all the JavaScript together on Launchpad.

tags: , ,

Comment

---

Frogspotter v3 and MelHack wrap-up

1622 days ago

So first I will show off a bit more frogspotter and then talk about #melhack as an event.

After making version 1, I got some great advice from people at melhack and not, about how to do clustering of Google Map markers. It seems there are quite a few options. I ended up going with MarkerClusterer:

(Oh and check that species list. But more on that later :))

MarkerClusterer looks great… in fact, maybe it looks too good. I do prefer the colour explosion of seeing all the different coloured markers directly. With MarkerClusterer, the “cluster” markers have their own colour scheme which is just related to the total number of markers. I can’t figure out a way to preserve the different species-ness of the markers when they get turned into clusters.

But, OTOH, with MarkerClusterer I can actually display all 6,700 points on the map, with minimal complaint from Firefox. So… that’s a tradeoff.

So yeah, when I build the markers, I also insert checkboxes in the table on the right for each species, and buttons to add or remove all of them. The buttons work perfectly, but the per-species toggling is a little wonky. If you click “Remove all”, then check one species, then uncheck it again, they don’t disappear when you uncheck it. I have to rework the JavaScript relating to that.

The cluster markers also freak out if you do “Remove all”, check some species, then try and zoom in. They stay as cluster markers and don’t convert to individual markers like they are supposed to if you zoom in enough. But if you just zoom in on the initial map with everything, you can see the individual markers. :)

So the pop-ups now have a link – to pages at Frogs of Australia, like Neobatrachus centralis. I was so happy to do that because Frogs of Australia have an awesome pretty/clean URL scheme. No API or searching or anything needed!

A few things more I would like to do

  • Fix the marker handling so that the check boxes work properly – hopefully will fix zooming on cluster markers too. (you never know)
  • convert to using jQuery
  • Add an image from Flickr/Wikimedia Commons in the pop-ups
  • And probably cache them…
  • Drop in a templating system…hmm, maybe Mako?
  • Add an ‘about’ page
  • Incorporate timeline data, per-species, in a graphic to the right of the checkboxes – so far I’ve just completely ignored this
  • Overlay other data like national parks

That’s all rather ambitious given I’m not devoting any more consecutive 24-hour stretches to this project, but you never know. :) Maybe I’ll be inspired for the MashupAustralia deadline this Friday. Or maybe I’ll work on it this Saturday at the GGD Afternoon Hack, even though the deadline is past it will still be a fun project.

Even though I know how simple it is to put together something with Google Maps, there is still something magic about seeing your dots show up on a map. Even other techies I showed it to over the weekend had the same reaction.

This weekend is also basically the first time I had ever written any JavaScript myself. Mostly, of course, I didn’t: lots and lots of cut and paste, save, refresh, console.log, rinse and repeat. But I was surprised to find that I quite like writing JavaScript. Must be the dynamic typing. I quite also liked that “object = associative array” because I use dictionaries (Python name for an associative array) a lot in Python. But although I liked writing it, debugging it is still another matter. Of course I made heavy use of Firebug, but I really need to go through a basic tutorial or two so I have a better understanding of the lay of the JavaScript universe. Overall that was a happy discovery.

I found out on Twitter when I got home that someone else had been inspired to work with the frog data too, at the Sydney oahack (OpenAustralia) hackfest. So I am very curious to see that. :)

During my presentation of frogspotter at the end of MelHack, I was corrected by Dr Gruen about where the data came from — I had wrongly assumed it was recorded by South Australian public servants. But no! It’s from the public. Pretty awesome.

To MelHack itself, it was such a great event. Lonely Planet provided a great building, great staff and support for everyone who came. Host Matthew Cashmore in particular did a really great job. We were fed well, had laser skirmish, won amazing prizes (set of every LP guidebook, Asus eee PCs, 24’‘ monitor etc…) and got to sleep under the stars on the top of a three storey building in Footscray. The staff were really friendly and happy to help out with anything. Even debugging JavaScript.

You might call it a geek adventure. ;)

tags: , , ,

Comment

---

MelHack - But does it have frogs?

1624 days ago

So I have been reading with interest the stuff coming from the Government 2.0 Taskforce. Even if the name is hard to take seriously, it’s a lot better than the last time the federal government tried blogging. Probably because those making the most interesting noises are not those in government, but nevermind…

Two interesting things to come from that have been the Mashup Australia competition and the data.australia.gov.au portal, which is really cool but I am afraid will not have a life much beyond the competition… hopefully I’m wrong there.

The NSW state government is also doing a similar thing, although they announced it earlier and released their data later.

As part of the Mashup Australia competition, the taskforce organised a “hacking event” in Canberra called GovHack (see also SMH story). Sydney had not one but two similar events, hosted by Open Australia and Google, and until quite late it looked like Melbourne was going to miss out. At more or less the last minute, Lonely Planet came to the rescue and converted their OpenSocial/LP API hack day to also incorporate the GovHack stuff. And hence we have MelHack where I find myself for the weekend.

This morning I also gave a short presentation on how to use Wiki[mp]edia data. You can see my slides on Slideshare. Feel free to ask me for more detail because they’re pretty sparse.

So now comes the 24 hours to hack. Unfortunately I don’t have any great society-transforming idea in mind, and the data sets at first glance don’t help. The interesting ones are sparse, or it seems an interesting app might combine 3 or more of them, whereas I’m pretty sure I should start with just 1 and make sure I can work with that, before using any more. So what to do?

Well, when in doubt, why not go with frogs.

The South Australian frog atlas contains over 6,700 sightings of frogs. This is what happens when you convert the CSV to XML and basically just chuck them all on a map. I haven’t worked with Google Maps before, but maps do seem to be a vital element in mashups, so it’s a good a time as any to learn.

OK, that’s frogspotter v1. I will work on making v2 more useful. ;)

tags: , , ,

Comment [5]

---