Journal tags: coding

11

sparkline

Indy maps

Remember when I wrote about adding travel maps to my site at the recent Indie Web Camp Brighton? I must confess that the last line I wrote was an attempt to catch a fish from the river of the lazy web:

It’s a shame that I can’t use the lovely Stamen watercolour tiles for these static maps though.

In the spirit of Cunningham’s Law, I was hoping that somebody was going to respond with “It’s totally possible to use Stamen’s watercolour tiles for static maps, dumbass—look!” (to which my response would have been “thank you very much!”).

Alas, no such response was forthcoming. The hoped-for schooling never forthcame.

Still, I couldn’t quite let go of the idea of using those lovely watercolour maps somewhere on my site. But I had decided that dynamic maps would have been overkill for my archive pages:

Sure, it looked good, but displaying the map required requests for a script, a style sheet, and multiple map tiles.

Then I had a thought. What if I keep the static maps on my archive pages, but make them clickable? Then, on the other end of that link, I can have the dynamic version. In other words, what if I had a separate URL just for the dynamic maps?

These seemed like a good plan to me, so while I was travelling by Eurostar—the only way to travel—back from the lovely city of Antwerp where I had been speaking at Full Stack Europe, I started hacking away on making the dynamic maps even more dynamic. After all, now that they were going to have their own pages, I could go all out with any fancy features I wanted.

I kept coming back to my original goal:

I was looking for something more like the maps in Indiana Jones films—a line drawn from place to place to show the movement over time.

I found a plug-in for Leaflet.js that animates polylines—thanks, Iván! With a bit of wrangling, I was able to get it to animate between the lat/lon points of whichever archive section the map was in. Rather than have it play out automatically, I also added a control so that you can start and stop the animation. While I was at it, I decided to make that “play/pause” button do something else too. Ahem.

If you’d like to see the maps in action, click the “play” button on any of these maps:

You get the idea. It’s all very silly really. It’s right up there with the time I made my sparklines playable. But that’s kind of the point. It’s my website so I can do whatever I want with it, no matter how silly.

First of all, the research department for adactio.com (that’s me) came up with the idea. Then that had to be sold in to upper management (that’s me too). A team was spun up to handle design and development (consisting of me and me). Finally, the finished result went live thanks to the tireless efforts of the adactio.com ops group (that would be me). Any feedback should be directed at the marketing department (no idea who that is).

Indy web

It was Indie Web Camp Brighton on the weekend. After a day of thought-provoking discussions, I thoroughly enjoyed spending the second day tinkering on my website.

For a while now, I’ve wanted to add maps to my monthly archive pages (to accompany the calendar heatmaps I added at a previous Indie Web Camp). Whenever I post anything to my site—a blog post, a note, a link—it’s timestamped and geotagged. I thought it would be fun to expose that in a glanceable way. A map seems like the right medium for that, but I wanted to avoid the obvious route of dropping a load of pins on a map. Instead I was looking for something more like the maps in Indiana Jones films—a line drawn from place to place to show the movement over time.

I talked to Aaron about this and his advice was that a client-side JavaScript embedded map would be the easiest option. But that seemed like overkill to me. This map didn’t need to be pannable or zoomable; just glanceable. So I decided to see if how far I could get with a static map. I timeboxed two hours for it.

After two hours, I admitted defeat.

I was able to find the kind of static maps I wanted from Mapbox—I’m already using them for my check-ins. I could even add a polyline, which is exactly what I wanted. But instead of passing latitude and longitude co-ordinates for the points on the polyline, the docs explain that I needed to provide …cur ominous thunder and lightning… The Encoded Polyline Algorithm Format.

Go to that link. I’ll wait.

Did you read through the eleven steps of instructions? Did you also think it was a piss take?

  1. Take the initial signed value.
  2. Multiply it by 1e5.
  3. Convert that decimal value to binary.
  4. Left-shift the binary value one bit.
  5. If the original decimal value is negative, invert this encoding.
  6. Break the binary value out into 5-bit chunks.
  7. Place the 5-bit chunks into reverse order.
  8. OR each value with 0x20 if another bit chunk follows.
  9. Convert each value to decimal.
  10. Add 63 to each value.
  11. Convert each value to its ASCII equivalent.

This was way beyond my brain’s pay grade. But surely someone else had written the code I needed? I did some Duck Duck Going and found a piece of PHP code to do the encoding. It didn’t work. I Ducked Ducked and Went some more. I found a different piece of PHP code. That didn’t work either.

At this point, my allotted time was up. If I wanted to have something to demo by the end of the day, I needed to switch gears. So I did.

I used Leaflet.js to create the maps I wanted using client-side JavaScript. Here’s the JavaScript code I wrote.

It waits until the page has finished loading, then it searches for any instances of the h-geo microformat (a way of encoding latitude and longitude coordinates in HTML). If there are three or more, it generates a script element to pull in the Leaflet library, and a corresponding style element. Then it draws the map with the polyline on it. I ended up using Stamen’s beautiful watercolour map tiles.

Had some fun at Indie Web Camp Brighton on the weekend messing around with @Stamen’s lovely watercolour map tiles. (I was trying to create Indiana Jones style travel maps for my site …a different kind of Indy web.)

That’s what I demoed at the end of the day.

But I wasn’t happy with it.

Sure, it looked good, but displaying the map required requests for a script, a style sheet, and multiple map tiles. I made sure that it didn’t hold up the loading of the rest of the page, but it still felt wasteful.

So after Indie Web Camp, I went back to investigate static maps again. This time I did finally manage to find some PHP code for encoding lat/lon coordinates into a polyline that worked. Finally I was able to construct URLs for a static map image that displays a line connecting multiple points with a line.

I’ve put this maps on any of the archive pages that also have calendar heat maps. Some examples:

If you go back much further than that, the maps start to trail off. That’s because I wasn’t geotagging everything from the start.

I’m pretty happy with the final results. It’s certainly far more responsible from a performance point of view. Oh, and I’ve also got the maps inside a picture element so that I can swap out the tiles if you switch to dark mode.

It’s a shame that I can’t use the lovely Stamen watercolour tiles for these static maps though.

Going Offline—the talk of the book

I gave a new talk at An Event Apart in Seattle yesterday morning. The talk was called Going Offline, which the eagle-eyed amongst you will recognise as the title of my most recent book, all about service workers.

I was quite nervous about this talk. It’s very different from my usual fare. Usually I have some big sweeping arc of history, and lots of pretentious ideas joined together into some kind of narrative arc. But this talk needed to be more straightforward and practical. I wasn’t sure how well I would manage that brief.

I knew from pretty early on that I was going to show—and explain—some code examples. Those were the parts I sweated over the most. I knew I’d be presenting to a mixed audience of designers, developers, and other web professionals. I couldn’t assume too much existing knowledge. At the same time, I didn’t want to teach anyone to such eggs.

In the end, there was an overarching meta-theme to talk, which was this: logic is more important than code. In other words, figuring out what you’re trying to accomplish (and describing it clearly) is more important than typing curly braces and semi-colons. Programming is an act of translation. Before you can translate something, you need to be able to articulate it clearly in your own language first. By emphasising that point, I hoped to make the code less overwhelming to people unfamilar with it.

I had tested the talk with some of my Clearleft colleagues, and they gave me great feedback. But I never know until I’ve actually given a talk in front of a real conference audience whether the talk is any good or not. Now that I’ve given the talk, and received more feedback, I think I can confidentally say that it’s pretty damn good.

My goal was to explain some fairly gnarly concepts—let’s face it: service workers are downright weird, and not the easiest thing to get your head around—and to leave the audience with two feelings:

  1. This is exciting, and
  2. This is something I can do today.

I deliberately left time for questions, bribing people with free copies of my book. I got some great questions, and I may incorporate some of them into future versions of this talk (conference organisers, if this sounds like the kind of talk you’d like at your event, please get in touch). Some of the points brought up in the questions were:

  • Is there some kind of wizard for creating a typical service worker script for any site? I didn’t have a direct answer to this, but I have attempted to make a minimal viable service worker that could be used for just about any site. Mostly I encouraged the questioner to roll their sleeves up and try writing a bespoke script. I also mentioned the Workbox library, but I gave my opinion that if you’re going to spend the time to learn the library, you may as well spend the time to learn the underlying language.
  • What are some state-of-the-art progressive web apps for offline user experiences? Ooh, this one kind of stumped me. I mean, the obvious poster children for progressive webs apps are things like Twitter, Instagram, and Pinterest. They’re all great but the offline experience is somewhat limited. To be honest, I think there’s more potential for great offline experiences by publishers. I especially love the pattern on personal sites like Una’s and Sara’s where people can choose to save articles offline to read later—like a bespoke Instapaper or Pocket. I’d love so see that pattern adopted by some big publications. I particularly like that gives so much more control directly to the end user. Instead of trying to guess what kind of offline experience they want, we give them the tools to craft their own.
  • Do caches get cleaned up automatically? Great question! And the answer is mostly no—although browsers do have their own heuristics about how much space you get to play with. There’s a whole chapter in my book about being a good citizen and cleaning up your caches, but I didn’t include that in the talk because it isn’t exactly exciting: “Hey everyone! Now we’re going to do some housekeeping—yay!”
  • Isn’t there potential for abuse here? This is related to the previous question, and it’s another great question to ask of any technology. In short, yes. Bad actors could use service workers to fill up caches uneccesarily. I’ve written about back door service workers too, although the real problem there is with iframes rather than service workers—iframes and cookies are technologies that are already being abused by bad actors, and we’re going to see more and more interventions by ethical browser makers (like Mozilla) to clamp down on those technologies …just as browsers had to clamp down on the abuse of pop-up windows in the early days of JavaScript. The cache API could become a tragedy of the commons. I liken the situation to regulation: we should self-regulate, but if we prove ourselves incapable of that, then outside regulation (by browsers) will be imposed upon us.
  • What kind of things are in the future for service workers? Excellent question! If you think about it, a service worker is kind of a conduit that gives you access to different APIs: the Cache API and the Fetch API being the main ones now. A service worker is like an airport and the APIs are like the airlines. There are other APIs that you can access through service workers. Notifications are available now on desktop and on Android, and they’ll be coming to iOS soon. Background Sync is another powerful API accessed through service workers that will get more and more browser support over time. The great thing is that you can start using these APIs today even if they aren’t universally supported. Then, over time, more and more of your users will benefit from those enhancements.

If you attended the talk and want to learn more about about service workers, there’s my book (obvs), but I’ve also written lots of blog posts about service workers and I’ve linked to lots of resources too.

Finally, here’s a list of links to all the books, sites, and articles I referenced in my talk…

Books

Sites

Progressive Web Apps

A tiny lesson in query selection

We have a saying at Clearleft:

Everything is a tiny lesson.

I bet you learn something new every day, even if it’s something small. These small tips and techniques can easily get lost. They seem almost not worth sharing. But it’s the small stuff that takes the least effort to share, and often provides the most reward for someone else out there. Take for example, this great tip for getting assets out of Sketch that Cassie shared with me.

Cassie was working on a piece of JavaScript yesterday when we spotted a tiny lesson that tripped up both of us. The script was a fairly straightforward piece of DOM scripting. As a general rule, we do a sort of feature detection near the start of the script. Let’s say you’re using querySelector to get a reference to an element in the DOM:

var someElement = document.querySelector('.someClass');

Before going any further, check to make sure that the reference isn’t falsey (in other words, make sure that DOM node actually exists):

if (!someElement) return;

That will exit the script if there’s no element with a class of someClass on the page.

The situation that tripped us up was like this:

var myLinks = document.querySelectorAll('a.someClass');

if (!myLinks) return;

That should exit the script if there are no A elements with a class of someClass, right?

As it turns out, querySelectorAll is subtly different to querySelector. If you give querySelector a reference to non-existent element, it will return a value of null (I think). But querySelectorAll always returns an array (well, technically it’s a NodeList but same difference mostly). So if the selector you pass to querySelectorAll doesn’t match anything, it still returns an array, but the array is empty. That means instead of just testing for its existence, you need to test that it’s not empty by checking its length property:

if (!myLinks.length) return;

That’s a tiny lesson.

Switching

Chris has written about switching code editors. I’m a real stick-in-the-mud when it comes to switching editors. Partly that’s because I’m generally pretty happy with whatever I’m using (right now it’s Atom) but it’s also because I just don’t get that excited about software like this. I probably should care more; I spend plenty of time inside a code editor. And I should really take the time to get to grips with features like keyboard shortcuts—I’m sure I’m working very inefficiently. But, like I said, I find it hard to care enough, and on the whole, I’m content.

I was struck by this observation from Chris:

When moving, I have to take time to make sure it works pretty much like the old one.

That reminded me of a recent switch I made, not with code editors, but with browsers.

I’ve been using Chrome for years. One day it started crashing a lot. So I decided to make the switch to Firefox. Looking back, I’m glad to have had this prompt—I think it’s good to shake things up every now and then, so I don’t get too complacent (says the hypocrite who can’t be bothered to try a new code editor).

Just as Chris noticed with code editors, it was really important that I could move bookmarks (and bookmarklets!) over to my new browser. On the whole, it went pretty smoothly. I had to seek out a few browser extensions but that was pretty much it. And because I use a password manager, logging into all my usual services wasn’t a hassle.

Of all the pieces of software on my computer, the web browser is the one where I definitely spend the most time: reading, linking, publishing. At this point, I’m very used to life with Firefox as my main browser. It’s speedy and stable, and the dev tools are very similar to Chrome’s.

Maybe I’ll switch to Safari at some point. Like I said, I think it’s good to shake things up and get out of my comfort zone.

Now, if I really wanted to get out of my comfort zone, I’d switch operating systems like Dave did with his move to Windows. And I should really try using a different phone OS. Again, this is something that Dave tried with his switch to Android (although that turned out to be unacceptably creepy), and Paul did it ages ago using a Windows phone for a week.

There’s probably a balance to be struck here. I think it’s good to change code editors, browsers, even operating systems and phones every now and then, but I don’t want to feel like I’m constantly in learning mode. There’s something to be said for using tools that are comfortable and familiar, even if they’re outdated.

On the side

My role at Clearleft is something along the lines of being a technical director. I’m not entirely sure what that means, but it seems to be a way of being involved in front-end development, without necessarily writing much actual code. That’s probably for the best. My colleagues Mark, Graham, and Charlotte are far more efficient at doing that. In return, I do my best to support them and make sure that they’ve got whatever they need (in terms of resources, time, and space) to get on with their work.

I’m continuously impressed not only by the quality of their output on client projects, but also by their output on the side.

Mark is working a project called Fractal. It’s a tool for creating component libraries, something he has written about before. The next steps involve getting the code to version 1.0 and completing the documentation. Then you’ll be hearing a lot more about this. The tricky thing right now is fitting it in around client work. It’s going to be very exciting though—everyone who has been beta-testing Fractal has had very kind words to say. It’s quite an impressive piece of work, especially considering that it’s the work of one person.

Graham is continuing on his crazily-ambitious project to recreate the classic NES game Legend Of Zelda using web technology. His documentation of his process is practically a book:

  1. Introduction,
  2. The Game Loop,
  3. Drawing to the Screen,
  4. Handling User Input,
  5. Scaling the Canvas,
  6. Animation — Part 1,
  7. Levels & Collision — part 1, and most recently
  8. Levels — part 2.

It’s simultaneously a project that involves the past—retro gaming—and the future—playing with the latest additions to JavaScript in modern browsers (something that feeds directly back into client work).

Charlotte has been speaking up a storm. She spoke at the Up Front conference in Manchester about component libraries:

The process of building a pattern library or any kind of modular design system requires a different approach to delivering a set of finished pages. Even when the final deliverable is a pattern library, we often still have to design pages for approval. When everyone is so used to working with pages, it can be difficult to adopt a new way of thinking—particularly for those who are not designers and developers.

This talk will look at how we can help everyone in the team adopt pattern thinking. This includes anyone with a decision to make—not just designers and developers. Everyone in the team can start building a shared vocabulary and attempt to make the challenge of naming things a little easier.

Then she spoke at Dot York about her learning process:

As a web developer, I’m learning all the time. I need to know how to make my code work, but more importantly, I want to understand why my code works. I’ve learnt most of what I know from people sharing what they know and I love that I can now do the same. In my talk I want to share my highlights and frustrations of continuous learning, my experiences of working with a mentor and fitting it into my first year at Clearleft.

She’ll also be speaking at Beyond Tellerrand in Berlin later this year. Oh, and she’s also now a co-organiser of the brilliant Codebar events that happen every Tuesday here in Brighton.

Altogether that’s an impressive amount of output from Clearleft’s developers. And all of that doesn’t include the client work that Mark, Graham, and Charlotte are doing. They inspire me!

100 words 098

When I’m grilling outside, I cook on a gas barbecue. There are quite a few people who would take issue with this. Charcoal is clearly better, they claim. And they’re right. But the thing is, I can fire up my gas barbecue quickly and just get down to cooking.

When I’m programming on the server, I code in PHP. There are quite a few people who would take issue with this. Any other language is clearly better, they claim. And they’re right. But the thing is, I can fire up my text editor quickly and just get down to coding.

A question of style

I’ve just a written a post over on the Clearleft blog about the way we’re currently nailing down some front-end design principles.

Front-end development principles Gathering principles

I’m a big fan of design principles for many reasons, not least of which is they way they can help to quickly resolve debates and arguments. They become a kind of higher authority to appeal to, taking opinion and ego out of the equation.

They can also lead to specific design patterns. This is something I’ve talked about in the past: the goals of a project inform its principles, which in turn inform the patterns that are used.

In the case of front-end design principles, they are informed by some higher-level goals. As I wrote on the Clearleft blog, some of those goals are user-centric, and some are developer-centric:

The user-centric goals include:

  • performance,
  • accessibility, and
  • device-agnosticism.

While the developer-centric goals include:

  • maintainability,
  • readability, and
  • modularity.

In turn, the final patterns produced—the actual markup and CSS and JavaScript—should be influenced by the resulting principles: the code should be maintainable, readable, and modular. So at the same time as we were figuring out high-level principles, we are also defining an in-house coding style.

In-house code style

Now here’s the thing about coding style: while it should ideally be informed by your design principles, there’s another factor that overrides everything else—what coding style is preferred by the developers who will be inheriting your code?

When it comes to things like tabs vs. spaces, or indentation, or naming variables, what matters is not which style you use, but that everyone is using the same style.

So, for example, I favour tabs over spaces. And I don’t tend to camelCase variable names in JavaScript. And I don’t like indenting my markup (I make judicious use of new lines instead). But I’m in the minority. I could try to force my style on everyone else at work but that wouldn’t be very productive. It’s far more important that everyone settles on the same style—any style—than it is for a coding style to be “correct.” The only “correct” coding style is the one that everyone is agreeing to use.

Mind you, people who write JavaScript functions with the opening curly brace on a new line are just plain wrong.

Announcing Huffduffer

Back in April, I wrote:

I’ve been thinking about maybe putting together a podcast — just an RSS feed — that points to interesting inspirational talks, sort of like Jon’s Found Sounds podcasts but for spoken word instead of music.

Well, as soon as I started trying to do that I discovered that, contrary to what Tim Bray says, creating an RSS feed by hand is a pain in the ass. So I decided that I would automate the task of creating an RSS feed complete with enclosures. Then I realised that if this was going to be useful to me, it might well be useful to other people looking to create podcasts of found sounds. So I made a website:

Huffduffer

The term derives from the abbreviation HF/DF. It refers to a technique, widely employed during World War II, to triangulate the position of radio transmissions. I thought that was a suitable term to revive for the practice of finding interesting MP3 files on the web.

Using the service is pretty straightforward. First of all, you have to sign up. No, I haven’t implemented OpenID support. Sorry. I hope to get around to it at some stage.

Secondly, you find MP3 files out there on the web. Using either a bookmarklet, or a form on the site itself, you “huffduff” the file: give it a title, description, and tags.

That’s pretty much it. People can subscribe to your podcast and you can subscribe to other people’s podcasts. You can also subscribe to a podcast of files with a certain tag or a combination of files from a particular person with a particular tag. Basically, if there’s a page for it on the site, there’s probably a corresponding podcast you can subscribe to.

So if you’ve ever fancied curating your own podcast, head on over to huffduffer.com and sign up for an account. If you’re interested in the kind of audio I find interesting, you can subscribe to my podcast.

By its nature, this will never be a popular, mass-market site. But, as is the case with most things built to scratch a particular itch, I hope it will turn out to be useful for some other people. If other people do end up using the site, that will open some opportunities for bubbling up some interesting stuff: popular MP3s, popular tags, recommendations of files from users who share similar interests with you.

I had quite a lot of fun building Huffduffer. It’s been a while since I’ve done any back-end programming so I used this as an opportunity to get intimate with the whole MVC idea. I thought about building the site in Django or Ruby on Rails, but in the end I decided to stick with PHP. I investigated some of the PHP frameworks out there and, while they all had parts that I liked, I decided to roll my own code …my own framework, really.

On the front end, the site is built in HTML5. I did this partly for the heck of it, and partly to show that HTML5 is not some future technology but something that you can use right now. The validator by Henri Sivonen proved invaluable.

The visual design of the site is very minimal, as most of my sites tend to be. On the plus side, this means the site is lean and fast-loading. On the minus side, it’s monochrome to point of boredom. But I spent quite a while crafting the typography just the way I want it in the belief that, if you’re going to concentrate on one aspect of visual design, the typography is probably the best place to start.

I’ll be iterating on Huffduffer over time. It’ll be interesting to see how the site gets used (if at all) and react accordingly.

Check it for yourself and see if it’s something you might like to use. If you have any questions, comments, or suggestions about the site, feel free to chime in on Get Satisfaction.

Iteravely Upcoming

Upcoming.org has rolled out some changes. The visual design has been tweaked, particularly on the events pages.

The colours and typography are looking very good indeed. The change to the way attendees are listed inline doesn’t work quite as well. I’m not the only one who thinks so. But instead of just bitching about it like me, others have provided mockups as part of their constructive criticism.

While this latest update is one of the biggest changes that has been rolled out on the site, it certainly isn’t the first. In fact, Upcoming seems to be in a constant state of gradual change and improvement.

There’s a lot of talk these days about , but Upcoming is one of the few places where I’ve noticed it in action. The design has been improving gradually and almost imperceptibly. Did anyone notice when the top banner changed from being a solid colour to a gradient? I wish now that I had taken screenshots of Upcoming every few weeks. They would make for an interesting time-lapse movie.

The Yahooiness of Upcoming is beginning to make itself felt. You can now migrate your Flickr buddy icon over to Upcoming. Also, if you tag photos on Flickr with “upcoming:event={event id}”, they will show up on the corresponding event page. Then there’s the maps integration.

Both Upcoming and Flickr are now making use of Yahoo maps. The Flickr map exploration page is, like so many things on Flickr, a real time-sink. It’s fun browsing photos with the added context of location.

But — and it’s a big but — Yahoo’s mapping data for Europe is particularly poor. So don’t expect too much detail when you’re browsing holiday snapshots from Brighton. I blame crown copyright myself (though I do wonder how Google has managed to get such detailed data).

As part of this latest iteration, Flickr are moving away from using tags for geocoding:

As a bonus there will be no more need for the unsightly “geotagged/geo:lat/geo:long” tags cluttering up your photos - we’ll offer an automated way to remove them all once the development community has had a chance to make the necessary changes to their code.

I’m not sure that’s such a good idea. There’s nothing wrong with using visible geographical co-ordinates. I’d prefer to keep my meta-data visible, thank you very much.

Mashing up with microformats

Back in March, during South by Southwest, Tantek asked me if I’d like to sit in on his microformats panel alongside Chris Messina and Norm! The audio recording of the panel is now available through the conference podcast.

I’ve taken the liberty of having the recording transcribed (using castingWords.com) and I’ve posted a tidied up version of the transcript to the articles section: Microformats: Evolving the Web. You can listen along through the articles RSS feed which doubles up as a podcast.

I’ve also posted the transcript on the microformats wiki so that others can edit it if they catch any glaring mistakes in the transcription.

During the panel I talked about Adactio Austin, a fairly trivial use of microformats but one that I’ve been building upon. I’d like to provide some cut’n’paste JavaScript that would allow people to get some added value from using microformats. Supposing you have a bunch of locations marked up in hCard with geotags, you could drop in a script and have a map appear showing those locations.

Perhaps the geotagging won’t even be necessary. Google added a geocoder to their mapping API two weeks ago. The UK, alas, is not yet supported (probably because the Post Office won’t let go of its monopoly that easily… Postman Pat, your money-grabbing days are numbered).

Unfortunately, Google Maps isn’t very suited to the cut’n’paste idea: you have to register a different API key for each domain where you want to use the mapping API.

The Yahoo maps API is less draconian about registration but its lack of detailed UK maps makes it a non-starter for me.

Maybe I should step away from maps and concentrate on events instead. It probably wouldn’t be too hard too write a script to create a calendar based on any hCalendar data found in a document. Perhaps I’ll investigate the calendar widget from Yahoo.

Ultimately I’d like to create something like Chris’s Mapendar idea. If only there were enough hours in the day.