WherePost: update with new features & data!

I spent some time over the past couple of days pushing out a few minor updates to http://wherepost.ca. Here’s the rundown:

  • I imported, and now scrape, the KML file from Matthew Hoy’s mailbox-mapping project. This doubled the size of Where Post, and merges work doing the same thing.
  • I finally got around to adding in a “name” field, per David Eaves’ request of oh-so-long-ago. When you add a mailbox, if you enter a name or twitter handle (neither is linked anywhere), it should set a cookie that’ll remember who you are for next time.
  • I added in some social-sharing buttons. But because I actually dislike the way these look in general, and like the minimal interface WherePost presents, particularly on mobile, these currently only show on the “About” pages. I was thinking I should add these to the “add mailbox” results, but am holding off for now. I would appreciate it if you went ahead and used these though!
  • Caching: Most result-sets are now cached for an hour, although adding a  new mailbox will reset that cache. This is to account for the odd times when it looks like a bot is scraping the site and causes actual load.
  • Post Offices: Because the GooglePlaces API returns Yellow-pages data, whom I don’t like, and in a way that was pretty broken (you’d always get duplicates, for english/french names of the same place, even if the data was identical, plus it’d overlay a link to the Yellow Pages), I’ve removed this, and added in the ability to specify you’re adding a Post Office OR a Mailbox when adding a new location.
  • Feeds! It felt wrong to be pulling in all this data, but not providing an easy way to get it all back out for you to remix however you wanted. So you can now get all the data WherePost has in 2 formats: JSON & KML. To do this, simply go to: http://wherepost.ca/load. This page has a few query-string params you can pass in:
    1)FORMAT: you can pass ?format=kml to get the feed in KML format – JSON is the default.
    2)RECORDS: you can pass ?records=X, where X is an integer to limit the resultset. By default, WherePost will return up to 10,000 records.
    3)SW & NE: to limit your results to a particular region, pass sw & ne coordinate bounds. So, for instance, ?NE=49.350405349378214,-122.72854022578122&SW=49.16644496927114,-123.2606904943359 will *roughly* return all the results in Vancouver

I think that’s all the updates. Let me know if you run into any difficulties!

An Adaptive Image Technique: Thinking out loud

I’ve been playing a lot with responsive layouts, and the inevitable bugbear of adaptive images for responsive designs. Ethan Marcotte’s Fluid Images is what I’ve been playing with most, particularly via Matt Wilcox’s Adaptive Images script, and dreaming of the <picture> solution proposed by Mat Marquis. But and so, I’ve been doodling and fooling around with some ways of doing this, and have now come up with something that I like. I’m worried it’s actually terrible, but I’ve played with it enough that I’d like some feedback now.

I’ve come up with a a CSS3-only solution to adaptive images. For those who just want to see the example, go ahead. You can view source for all the details. The 3-col/2-col content is purely presentational.

To do this technique, I have an image tag, like so:

<img id="image1" src="/transparent.png" data-src="/fishing.jpg" alt="Man fishing on a log" />

That displays a 1 x 1 px transparent image. The data-src attribute is there to show the “true” source. In the CSS, I make use of the background-image property to provide media-query-attentive backgrounds & sizing.

The default declaration is:

#image1 {
background: url('/images/responsive/fishing-small.jpg') top center no-repeat;
width:100%;
max-height:67px;}

This is the “small device” version of the image. using media queries, I can also load in an hd/retina version for those devices:

@media only screen and (-webkit-device-pixel-ratio:2) {
#image1 {
background-image: url('/images/responsive/fishing-small.jpg')
}
}

I also can provide a mid-size version, a mid-size hd/retina version and a desktop version (or an infinite number of variations based on media queries).

@media only screen and (-webkit-device-pixel-ratio:2) and (min-width: 600px) {
#image1 {
background-image: url('/images/responsive/fishing-mid-retina.jpg')
}
}

To provide some fallback for IE users, I’ve included an IE-specific style:

<!--[if lt IE 9]>
<style>
#image1 {background-image: url('/images/responsive/fishing');width:100%;}
</style>
endif]-->

I like to start “mobile first” and use media-queries to “grow out” from there, but I could just as easily start with the largest version and work in – in which case the IE workaround wouldn’t be necessary.

Some of my thoughts on this technique

  • I like that this technique is really easy, really light-weight and doesn’t require any javascript or php.
  • The fact that I’m using a 1×1 transparent png fills me with the howling fantods as I remember spacer gifs.
  • Reusing a single tiny image all over the place has negligible bandwidth effects, but to be fair, I am making an “unnecessary” request to get it each time.
  • The data-src attribute is there to help with this. By default, things like Pinterest and Google Images could no longer grab your images with this technique (Whether that’s a good or bad thing, I leave to you). By leveraging a .htaccess rule, you could load in the data-src attribute as src for the pinterest or various bot user-agents.
  • This system could work pretty easily with automated CMS systems: using regex to replace a src attribute with a data-src attribute and injecting the 1×1 & an id is trivial, as is auto-generating some CSS to handle the variations of the image for each media-query break-point – but that’s definitely more work than not doing anything on the CMS -side and doing all replacements in JS or PHP on the front-end.
  • I like that I can easily update/replace any 1 image in the set without updating html source anywhere.
  • This feels “too easy” to me. All the other solutions I’ve found use some sort of scripting, be it PHP or JavaScript. That fact that there’s nothing to post to github here makes me feel like I’m doing something wrong.
  • Using background-image on images means that users can’t as easily download your image – right-click on an image and most browsers don’t give the option to “download background image” like they do on other elements.
  • I worry that this is doing something unexpected for accessibility – but mostly it should be ok, I think, as there’s an alt attribute, and will still work fine with a longdesc attribute.

I’m hoping for feedback on this for the world at large – as I said, I’m thinking out loud about this – it seems like a workable solution, so your feedback, thoughts, critique would be very much appreciated before I go do anything silly like use this in a client’s project.

WherePost: now even more useful!

Since I launched Where Post? on Friday morning, the response has been pretty gratifying. My thanks to David Eaves for his nice post about Where Post? this morning. I launched the app with a total of 28 mailboxes and 1 post office. Since then, 29 contributors have added in another 400-odd mailboxes and about 20 post offices. (NB: ‘contributors’ are identified currently via a combination of a cookie & IP Address – so it’s not exact, but close enough).

I’m please to announce a very useful addition: Every post office in the Google Maps database, everywhere, pulled in from the Google Places API. I had noticed while adding post offices that there was often an envelope icon already in the map where I wanted to add a post office. After some digging this afternoon, I was able to pull in the places API to just get all the places that identify as a post office.

There’s a few oddities to figure out:

  1. Often each post office is listed 2 or 3 times at least in Canada: The french name & english name appear to be 2 places, and sometimes the post office in english, the post office in french and the store containing the post office are all listed. Odd, and I haven’t yet figured a way to filter this, but still pretty nice.
  2. I have a rate limit of 100,000 queries a day. Given that each time you see the “loading mailboxes” message there’s a query to Google, there’s a distinct possibility I’ll reach that. For now not a worry, but definitely a scaling/caching issue to think about in the future.
  3. Integrating with the “nearest” function. Currently, the “nearest” mailbox is simply pulled from an SQL query – which means that post offices, coming in from Google, are ignored. There’s likely a way to merge the two, but nothing’s coming to mind at the moment.

As always, if you have any suggestions, comments or anything else, please let me know!

Introducing: Where Post?

Where Post? is a small web-app I wrote over a couple of evenings this week to serve a very particular purpose: To help me, and anyone else, find their nearest mailbox.

The site should work on iPhones, Windows Phones & Androids. It’s meant to run as an app, so you can install it to your home screen for the greatest effect.

There are currently 2 ways of adding new mailboxes – as time permits, I’ll add more:

  1. In the app: to add a new mailbox, click on the “+” at bottom right, then click on the map where you know there’s a box. If you like, add some notes like “next to the garbage can” or “across the street from the pink house” to help people find it.
  2. Instagram: You can also take a picture of a mailbox on instagram, tag it #wherepost and include a location. A mailbox, with the photo you took, will be added at that location. Your photo’s caption will become the notes for the mailbox. I think it’s a fun use of the instagram API.

Of course, you can also simply find directions to the nearest mailbox to you. Just click on the magnifying glass, and Where Post? will provide you with walking directions to the nearest box (within 2km).

The app is very much a work-in-progress – to come is the ability to add in Post Offices, as well as pick-up/drop-off locations for the various courier companies, so that eventually, it’s a one-stop place to go to find where to send something from. Any and all feedback is much appreciated. In particular, if you know how to change the cursor icon in Google Maps v3, I’d love to know how.

So please have a look, play with it and send me any feedback you might have!

Greasemonkey VPL Catalogue Listings Script for Amazon

So David Eaves posted “5 Municipal apps I’d love to see“. One of them was an extension of an existing Greasemonkey script to search local library catalogue listings when browsing Amazon. So I downloaded Bryan Larsen’s Ottawa library script, modified it to look up in the Vancouver library, and have now posted in on Userscripts.org, for all of your pleasure.

Even if the initial lookup fails, you can still do a direct title & ISBN lookup from links that the Greasemonkey script pushes into the page, directly below the title of the book:

The VPL Greasemonkey script at work on Amazon
The VPL Greasemonkey script at work on Amazon

So, install the script, and test it out on Amazon! Let me know if you have any issues

UPDATE: I’ve updated the script a couple of times since this was initially posted, with the following revisions:

1.0: basic modification of the script
1.1: updated to include a new ISBN look-up URL variable
1.2: updated the ISBN lookup to use the correct OCLC web service
1.3: Fixed getIsbn() regex to look for /,? or end-of-string to extract the ISBN.
1.4: edited the Code-matching to use a central array of codes, and loop over those to provide a simplified messaging around status, and in particular, multiple statuses.

This means that it should be *alot* easier for anyone to further modify this in the future for any other libraries they may want to hook into, as well as providing better answers for books with multiple statuses and copies.

Ideally, I’d like to have this crawl the resulting code to pull out both the branch & due-date information, but this’ll do for now I think.

UPDATE 2009-10-20: There’s now also a script for use on the Vancouver Island Regional Library too: http://userscripts.org/scripts/show/60170