It’s time to drink a beer and write a blog post. This week I worked on diaspora-x squared, an xmpp client written using javascript. It uses strophe.js and backbone.js. I had a few issues that needed attention with backbone:
Multiple render calls
I was receiving xmpp stanzas and inserting them into a backbone collection. The collection was firing the add
event and I had hooked that to call this.render
. That meant that I was calling render (and the browser was parsing html, creating dom nodes and reflowing the layout) about 30 times in a row, which is fucking inefficient (even though the browser never rendered the nodes).
This could be fixed by putting in a 20ms timeout before calling this.render
, and canceling the timeout when a subsequent update request came in (you need to make the timeouts at least 20ms or some browsers will call the timeout immediately).
LocalStorage
I didn’t implement localStorage to cache the previously received xmpp stanzas, mainly because there is no localStorage support built into backbone. I know that backbone is meant to stay lightweight and tiny, but it would be nice if the localStorage store was “officially supported”, then I’d use it more often.
Confusion about submitting forms
When I write form submission code, I do it in a view - so the view has a submit
method which is hooked using the delegateEvents method on form submission. I end up processing the form entry, saving the model, adding it to a collection and then doing a redirect (using window.location.hash), all in the view. Some of this code feels like it should be in the controller, but I’m not sure how to do that. Maybe I’m just getting confused with the rails way of doing things.
Adding production support to capt
I’ve used capt
(my code generation / development mode server tool for creating backbone apps) to build two apps now and it really is a good tool. I need to add:
- Production mode (concatenate files in order, run through closure)
- Server side coffeescript processing (not really needed, but a nice to have, esp. with growl support)
- Working test framework (I am generating test cases but haven’t been running them, need an easier way to do so)
- Documentation and promotion (so that people learn about it)
Interesting week all the same. I had two really good days in the flow (2000 loc on thursday, about 800 loc today). Invented two nice things, an xmpp-pubsub social network (diaspora-x2) and a bookmarklet that scrapes geodata from a currently open page (for adding places to weheartplaces).
Two levels deep
In my weheartplaces bookmarklet, I use this bit of code to search the dom for any google maps instances in the first two layers of the dom, and then extract the lat/long of the map and use it for the bookmarklet:
if google? and google.maps? and google.maps.Map
maps = []
# Search two levels deep...
for k,v of window when v instanceof Object
if v instanceof google.maps.Map
maps.push v
else
for i,j of v when j instanceof Object
if j instanceof google.maps.Map
maps.push j
for map in maps when map.getCenter
try
attributes.geo.push [map.getCenter().lat(), map.getCenter().lng()].join(", ")
catch e
# ...
for map in maps when map.getCenterLatLng
try
attributes.geo.push [map.getCenterLatLng().lat(), map.getCenterLatLng().lng()].join(", ")
catch e
# ...
Works really well. Quite stoked. I’ll try and release the weheartplaces bookmarklet next week.