Showing posts with label web development. Show all posts
Showing posts with label web development. Show all posts

2010-06-06

My experience creating a Google Chrome extension

The Chrome extension for Oplop went up on to the extension gallery today. I figured I would just quickly jot down some thoughts of mine on creating an extension in Chrome, lessons learned, etc.

First off, writing an extension is easy. Over the years I have toyed with the thought of creating a Firefox extension, but the thought of having to use XUL always scared me away. Eventually I switched to Chrome as my primary browser (and I have been extremely happy, especially with the developer tools; only use Firefox now to test offline stuff because of its "Work Offline" menu option) but I still had not thought much about trying an extension again. But then Chrome released details of their extension design and how it revolved around extensions being nothing more than web pages. That seemed reasonable; why not treat an extension like some other web page? Less custom code just for extensions and people already have experience with HTML and JavaScript, so why not?

Eventually I started Oplop and my focus shifted to HTML5 web apps thanks to my Ph.D. (which I have started writing). But I still kept an eye on Chrome's approach to extensions (which Mozilla Jetpack takes a similar approach). Finally I found the time to give it a shot.

Chrome extensions fall into three types: browser actions, page actions, and content scripts. Browser actions are the icons you see to the right of omnibox. Those are extensions whose icons are always present no matter what the browser is showing you and will present a popup when you click the icon. A page action is an extension where the icon shows up within the omnibox at its far right edge. This is for extensions that conditionally want to present you with a popup (like Oplop only being useful on pages with a password field). Lastly there are content scripts which run based on a regex for the URL of the page being viewed. They have no visible icon. Now you can mix and match any of these three approaches, e.g. Oplop is a page action as it only shows itself when needed, but a it also uses a content script to find out what pages have a password field.

The other part to an extension is the background page. This is an HTML page that is constantly running headless in the background (why it is HTML and not just JavaScript I don't know since it has no UI). This kind of gives you an MVC for extensions: popups from a page or browser action is the view with the background page as the main controller and content scripts kind of acting like worker threads per tab.

The real trick in all of this is when you have to start communicating between the various parts. Content scripts run in their own space, as do background pages and popups. But content scripts run in a very restricted space since they can mutate the running tab's DOM. And things get a little bit more complicated as the background page is running for every tab while content scripts and popups are only running for their respective tab. So how the heck do you tie all of this stuff together?

Content scripts communicate through message passing. You can either do one-off messages or open a port that stays open. Now anyone can communicate with content scripts, including popups, so you kind of have to be careful when using one-time messages that you don't interleave communication through the extensions' mailbox. You can do the long-running message port if you want and store the port so that you send multiple pieces of information. The trick here seems to be having the background page truly act as the central controller. Basically you have any communication dealing with content scripts either start or terminate in the background page. If a popup needs to communicate with a content script it's best to have the background page implement a function for communicating and then use chrome.extension.getBackgroundPage() to send the message on the popup's behalf. You can use chrome.tabs.getSelected() in a popup to find out what the current tab happens to be in so you can send the message to the right content script by having the background page store the port or callback response function in an object keyed on tab ID.

The communication thing was the hardest thing I found. Everything else made sense. It's actually so straightforward that I have a catch-all extension which I have do stuff for me, e.g. skip full-screen ads. So if you are a Chrome user and have ever had an interest in writing an extension I recommend giving it a try.

2010-02-16

Taking a web app offline (including iPhone support)

As part of having Oplop take advantage of as much cool HTML5 features as possible and being available as widely as possible, I decided to add offline support and to add iPhone OS support as a home screen app.


2010-01-23

HTML5 will lower the use of CDNs for delivering JavaScript

As Firefox 3.6 was released today, people have begun to use the async attribute for the script tag from HTML5. For those of you unaware of the new attribute, it tells the browser to execute the JavaScript that a script tag points to through its src attribute in an asynchronous manner. Now from my reading of the spec that should be asynchronously, but one at a time based on the order of the script tags are found in the doc. But if you play with Firefox 3.6 it becomes apparent that Mozilla disagrees with my interpretation as Firefox will begin executing the next async JavaScript file without waiting for the previous one to finish.

And this immediate execution is where things begin to make things interesting for using a CDN for JavaScript code. I don't know about some of you, but I use the Google AJAX Libraries
to get my copy of jQuery through their URL interface. This is great for me as it means the traffic is served by someone (i.e. free for me), Google's CDNs are fast, and there is a decent chance that others have used the CDN as well which lets the browser uses a cached copy of jQuery instead of fetching it again just for my web app. This means you don't concatenate jQuery in with your JavaScript code to get a single JavaScript file to serve, but my thinking (until now) has been that the perk of the browser already having a cached copy of jQuery was enough to not care about the potential separate HTTP request.

But you can't reliably use the async attribute with library code that subsequent JavaScript code depends on. In my case I use jQuery to execute JavaScript code once the page is loaded and rendered. When I put the async attribute on both the CDN-served jQuery code and on my own code, I was able on my local machine to occasionally trigger a race condition where my JavaScript code was executed before jQuery, triggering an error as $ was not defined yet. It was tough to trigger, but it definitely happened.

This means either you execute the CDN-served library code synchronously or you concatenate it with your code and serve that entire file asynchronously. The decision then becomes what gives you more benefit: possible faster downloading from a CDN plus cache hits but blocking JavaScript execution, or having to download from your servers but having fully asynchronous execution.

Now some of you might view this as a somewhat thin argument that CDNs serving JavaScript will get marginalized, and that's fair. But what I really think will impact it is offline web applications and the app cache. For a web application to work offline you define a cache manifest file which lists what URLs to cache, which URLs to hit a specific file if not online, and which ones should always go to the network no matter what. But at issue here is the fact that all listed URLs must follow the same-origin policy. This means that for you to serve up some JavaScript library while offline you need to have it hosted on your server to be able to list it in your cache manifest to get the benefits of an offline web app.

As people begin to look at offline web apps more and more I think it will be interesting to see how this impacts people's use of CDNs for stuff like JavaScript.

2010-01-19

Oplop web app, now using HTML5

Back in October I blogged about why I liked jQuery UI in my search for a JavaScript library that would let me create a wizard interface the way I wanted to do it for Oplop (which is a password hash algorithm app for creating unique account passwords; more details can be found in the How Oplop Works page). And while jQuery UI worked for the initial launch of the wizard approach I took, I quickly realized it was not going to work for me in the long term as I wanted the web app to work on both a desktop and a cell phone using a single version and that meant minimizing download size. While jQuery UI looked fine on my Android phone, it did have some extra overhead that was simply not needed by me. That's when I decided I would create my own replacement for my use of jQuery UI's accordion to get the same effect, albeit specifically tailored to my needs.

I also took this opportunity to completely go all out and only use HTML5 (which should now simply be called HTML). Having used the new version of HTML heavily for my thesis work, I have come to know and appreciate all of the new features in the spec. Add in Mark Pilgrim's wonderful Dive Into HTML5 site/book, and I knew I wanted to go nuts and be entirely cutting edge and essentially give Internet Explorer the finger (for now; I plan to add support for Chrome Frame in the future). While I am sure most of you pro developers are not looking at HTML5 yet, you should still at least give it a glance as there is already JavaScript out there to help make IE function properly with some of the new stuff (see Mark's discussion on this).

First thing I did for this redesign was go for a semantic markup of the site. There was to be no CSS styling embedded in a tag or the page, nor any JavaScript anywhere to be seen in the page layout markup. Based purely on tags, id, and class markups I should be able to look at the HTML have the UI be obvious and clean. I also wanted the page to render exactly how it should look upon initial load with nothing but the CSS stylesheet and HTML; JavaScript was to be purely for logic and later style changes, but it should not be an initial load requirement (although at the moment the JavaScript is blocking the loading of the rest of the page; I will talk more about how I might solve that later on). The idea is that the load should take no longer than downloading and parsing all the files and not have to wait on any JavaScript short of wiring up form controls; no nasty UI pop-in from JavaScript execution, etc.

Luckily my goal of using only CSS and HTML for the initial page load styling turned out not to be a problem. Thanks to various new tags like section (to encase each step in for semantic reasons) and new attributes on form elements like autofocus (so the proper text field is selected upon initial load) the page looks exactly as it should sans JavaScript, making the view cleanly separated from the controller, all while being proper HTML.

With the look out of the way I tackled replacing jQuery UI's accordion widget. Because I imposed my restriction that the UI had to look correct w/o JavaScript, I had used CSS to hide the steps of the wizard that had not been reached yet with an open class. Using that as a base, I decided to have transitions from one step to another occur by triggering a nextStep() method which uses jQuery to find the step that has the open class, toggle that class off, go to the next section, and then toggle on the class there. This made the query simple in jQuery and allowed the transition code to be generic from step-to-step (although I had to add some hook support through jQuery.data() for step-specific prep and validation stuff).

That got me as far as having the web app function just like it did before I started this endeavour. But at this point I wanted to extend the potential audience, so I added iPhone support as well. This turned out to  be basically simple, but I did have to tweak the UX just for the iPhone. When I designed the web app I was designing it for me while I am on my laptop, which means a full keyboard. I also made sure it worked on my adp1 (which is the developer version of the HTC Dream) which has a physical keyboard. And being somewhat of a UNIX geek, I made sure the entire web app could be driven from the keyboard under at least Google Chrome, from proper focus between form controls by pressing Enter, down to having your account password be in a text field that is already selected for easy cutting by hitting Cmd-X (or whatever your cut keyboard shortcut is). Nice and elegant and damn quick for getting your account password.

But the damn iPhone has no Enter key on its soft keyboard when you are filling out a form. Instead you get a "Go" button which acts as form submission. In my case that's useless as there is no place to submit the form to; everything is client-side for security reasons. That meant I had to tweak the UX so that you can not only press Enter to transition to the next step in Oplop, but you can also click the title of the next -- and only the next -- step as well to trigger a transition. In other words Oplop can be driven by a mouse now.

Since I was already adding UX support specifically because of the iPhone I figured I would also make the web app support being a web clip (web app that can be added to your home screen) as well. Thanks to Jonathan Stark's in-progress book on iPhone developement I made Oplop be zoomed in, have a proper home screen icon, and to ditch the location bar.

I would also like to thank ImageOptim while I am at it for being such a great little tool to optimize all the PNGs I have as icons (favicon, web clip icon, etc.).

So now I have a web app that works under (at least) Chrome, Safari (both desktop and Mobile), Firefox, and Android. I am rather happy with that browser coverage considering there is no magical browser detection stuff require, nor two versions of the web app.

But of course I am not finished yet. First thing is to write up some UX tests using Selenium 2/WebDriver and Jython. Now that everything is functioning as expected I want to keep it that way.

After that I want to clean up my JavaScript code to be more event-driven. While it is part way there thanks to having a generic function that handles step transition details, that function gets called explicitly. It would be better to instead trigger a custom event and have a single event handler for that at the top of my HTML structure. Minor, to be sure, but just feels more "right".

Once that is done comes time to start really optimizing the web app. I still have yet to use Google's Closure compiler to minify all of my JavaScript code into a single file to shrink total download size and minimize the number of HTTP connections required to download everything (which can matter on a cell phone that has a high latency connection). I also want to play with the new async attribute on link tags. My hope is that I can add that to my minified JavaScript file so as to have it start downloading concurrently while the rest of the page is downloaded and rendered and have them finish roughly at the same time. Unfortunately I don't know if that will work reliably enough to let this work w/o somehow letting the user know when everything is finally wired up. Plus no browser currently supports the attribute (although Firefox 3.6 will have support apparently). After that there will be lots of time spent with Speed Tracer to see if there are any other obvious things to tweak.

And then back to adding features! The next big ones will be adding offline web app support and creating a Google Chrome extension based on the web app. The former should be relatively straight-forward, but lead to some custom Mercurial hooks for properly updating the cache manifest (need to tweak the file every time something changes to trigger a new download of the app) and the latter should simply be fun as I think my planned approach will be more secure and have a better UX than the other password has algorithm extensions already available (if my idea works  =).

Expect more blog posts on Oplop in the future as it is turning out to be a fun personal project. And if you actually use Oplop let me know and I will consider setting up a mailing list or something for Oplop-specific announcements (e.g. like the Python 3 command-line version I just uploaded to the project site) if there is enough users beyond just a handful of friends of mine.

2009-10-14

I ♥ jQuery (UI)

I had this grand plan for a blog post comparing the various JavaScript GUI libraries, which in the end ended up being this blog post stating how I like jQuery UI. If you don't care about reading a "love letter" to jQuery UI, then you can stop reading now.

2009-05-04

Does XHR lead to better testing/abstraction?

I was talking with a friend of mine who is a Ruby programmer who does Rails development and I asked her how best to handle a form submission that was malformed. I am thinking of the situation when I have a URL that accepts a POST from a web page and some argument is in the wrong format or an argument is entirely missing. I wanted some way to signal the POST submission was bad directly from the HTTP status code or something. I mean you should have some clear way to know that something failed along with a message as to why it failed.

But she said it should return a 200 with response page specifying what went wrong. When she said that my TDD sensibilities along with my separation of concerns training recoiled in horror. To test the URL response I have to parse the HTML for error output?!? That means I have to inspect the view to know that an error occurred! And this is simply not testing the view to make sure an error was made visible to the user, this was to test the error was caught, period.

After I recovered from my shock at this suggested practiced and realized most sites worked like this I realized why it offended me so much. Just like everyone else I was taught that MVC was generally the best way to structure GUI applications, and in general I agree with the assessment. In my opinion an application should function regardless of what the GUI iss, making the front-end a separate component of the overall application. One should be able to swap out the "V" from MVC and have things still work. That's just good abstraction in my opinion. That means I should be able to test the core components of an application -- the M and C -- without a GUI. And yet with most web apps we do not get this separation thanks to most forms signaling a failure based on what is displayed in the reply.

With this in mind I began to think about how I could rectify this situation for my web app I was developing. And that's when I realized that using XHR to send a form's data to a URL and use the response to handle errors was, from a testing perspective, the best way to go. It might make the client-side code more complicated as a click in a form would no longer simply be the case of the web browser redirecting to a specific page but require processing a response -- probably JSON -- and handling the reply. But from a testing perspective I would be able to test the submission URL in isolation from the web page, thus separating the V from the M and C. Plus it would give me a REST API upfront and thus not require me to create it later -- if I chose to document the API and make it public.

That's when I said to myself, "OK, so how does everyone else handle signifying an error when it comes to errors in a REST API"? And that's when I found out everyone does it there own little way. About the only thing I found that was consistent is that if everything went well the URLs returned a 200 and when it went to hell they returned a 404. But from there there was no consistency. Only looking at JSON responses, some included the HTTP status code in the error message while others did not. Some had the idea of a class of error and a message while others only had a classification. Some had no answer whatsoever (I'm looking at you XML-RPC), and some went over the top (that would be SOAP).

So I began to wonder about what I would do to signify a failure for a REST call. The first thing I agreed upon was that returning 200/404 was reasonable. It does irk me slightly since it is just like returning 0/1 in C to signal an error, but it works in this situation where one does not have proper exceptions nor other status codes to use to signal different types of errors. I could inspect the returned JSON object for an 'error' attribute to realize an error object was returned, but this works just as well and I would rather dispatch on status code than have to introspect the returned value.

Having chosen a way to signify an error, I then thought about what the JSON reply would require. I thought about how Python signifies errors and almost went down the road of something like exceptions complete with inheritance. But I quickly realized that would require loading JavaScript code just for defined exceptions and I didn't like that for an exposed API; for a REST API one should be able to just read the API docs to make a call and not require including any special JavaScript code. I also realized that this was an API issue, not a programming issue. I was more interested in how Python handled errors when calling functions than how bad syntax was flagged.

That means that I wanted something like TypeError when an argument is missing and ValueError when some input is malformed. That's when I figured why can't I just do something like that? If I had a JSON object have an 'error' attribute that specified the type of error, like "TypeError" or "ValueError", I would have my TypeError/ValueError in JSOn. A 'message' attribute would work as BaseException.args[0]. And then I could tack on arbitrary attributes on this error object for error-specific information such as what argument was missing or what kind of format was expected for a field.

And so all of this is what I plan to do the next time I have any data that needs to be sent to a URL for something that is public-facing and and not a hack (although honestly, isn't everything hack and we just happen to be willing to chance having the public use it?). Yes, it complicates the client-side stuff, but actually the JS code could be made into a library to nicely flag errors, etc. if one standardized on the type of errors that would be returned. Plus it makes unit testing the controller much easier. And it forces you to have a REST API upfront so you don't have to design it later.

Oh, and if anyone says, "what about XForms?", I will say, "get it in all of the major web browsers and then we can talk".

2008-09-21

I like Twill

In a previous blog post, I talked about how I really like Google App Engine, but was frustrated by not being able to test my web app thanks to a disconnect between GAE and the Django Helper. Well, instead of waiting to get up and going under Django 1.0, I decided to give Twill a try.

And the try worked out well! Twill was easy to to use and provided pretty much everything I desired for the basic sanity tests I wanted to do for my web site. And it provided it with an API that was easy to use and kept me from having to hard-code much about the structure of the pages. My only complaint is the slight disconnect between Twill's browser object and the various commands it has (e.g. there is not a nofind() method on the browser object). But that is a very minor complaint.

2008-09-14

First dynamic section to my web site is up

I finally got around to constructing the first dynamic part of my web site: a system for me to record what television shows I have watched from their pilot episode. While not designed to be a web app used by the world, I am able to add end edit any series listed. And the list that is there is not exhaustive; it's mostly so I know what shows I am behind in watching.

I started with this app because it was simple. The data schema has no relations so I didn't have to worry about doing any many-to-one relations (but another app I have planned will). Probably the trickiest part was setting a 'sort_on' field for TV titles that start with an article ('A', 'An', and 'The'). I wanted that to be based on the specified title for the series, so I overloaded the __init__() method for the model and set it manually. With a subsequent super() call the model class doesn't know that a required value was computed on the fly.

I did go back on forth on whether to use None values for season/episode to represent that I have watched an entire series, but decided against it. I figured it was better to be able to require a value for those attributes and just have an explicit 'completed' boolean attribute.

And I am not happy with how I am currently handling my templates. I am having a tough time deciding how much should be passed into a template through a view, what should be set through a block in a template, and what should just be a a global variable/filter. A good example of this stuff from Google App Engine's Users API. There are functions to specify login and logout URLs along with functions that return what user is logged in and whether they are an admin.

Right now I explicitly set 'user_is_admin' for my templates through the view to decide if a page should display admin-specific info (e.g. edit links by the names of the TV series). But since what user is logged in and whether they are an admin is a project-side thing I feel like writing a Django context processor to handle this. I could then provide a filter that generated login/logout URLs with default to the current URL (although that would probably require a RequestContext to work). Basically I am still feeling around to find out what the right abstraction level is for templates.

2008-09-08

Fiddling with the Google AJAX Feed API

Instead of going to bed I decided to do one last thing to the one page that is my web site; add dynamic "last updated" info based on a feed. I used the Google AJAX Feed API and it turned out to be pretty easy. Biggest pain was dealing with JavaScript's Data object and lack of built-in ability to pad digits. But otherwise it was rather easy to discover the feed on a page, get the feed, pull out the newest entry, and get the creation date for that entry. And then with some jQuery I was able to have the last-modified date fade in next to the link to the page.

2008-09-07

Adding simple jQuery effects

Me being me, I got sucked into doing the initial styling to my site. Got the basic CSS done. I have always been one to support really clean sites in terms of looks, so the page is basically just four div tags: header, nav, article, and footer (which correspond to new tags that are being proposed in HTML 5). I also tried to use colors to make an obvious contrast between links and descriptive text in the navigation sections.

But while I like simple sites, that does not mean I am not a sucker for eye candy. I decided to try jQuery loaded from the Google AJAX Libraries API. It turned out to be rather straight-forward to add hover events to the header and footer so that info that people will typically not care about and ignore are not visible unless you hover over the proper div (once I got back into my groove of coding JavaScript). And I made the div have the hover event instead some smaller section so that one does not have to do any overly accurate mouse work to trigger the text to show.

Adding a custom 404 page in Django

With my web site consisting of a single page, I suspect some 404s are going to get served rather quickly. So I decided to go ahead and do a custom 404 page. Google Webmaster Tools has a handy 404 widget you can paste into your 404 page that gives suggestions on where the person probably meant to go, along with a site-specific search box. Google Analytics also has some custom 404 code to help you track the bad pages.

And all of this was done by just defining a 404.html template in Django. The only problem I hit was that I couldn't have nested blocks for my Google Analytics code. The 404 code between a normal page view and the 404 are arguments to a single JS function. I wanted the Google Analytics code to be in a block and then have a nested block for the arguments to the JS function. In the end I just stripped out the Google Analytics block and just went with the argument block. Hopefully I won't come across a need to not track a page.

Baby steps with Google App Engine

You know that mythical personal web site I have been talking about for months? Well, today I finally started work on actually implementing www.DrBrett.ca (warning: it's ugly until I get around to doing some CSS for it). I figured I might as well blog about how this entire process goes to help others out and to keep track of stuff.

First of all, I am deploying on Google App Engine under Django. I using GAE as I am not a sysadmin and I do not want to have to worry about keeping my web server up any more. There is also the side benefit of preparing me for my internship with the team come November (I don't know what I am working on so don't bother asking or making requests for features). I am using Django because I love the community that has built up around the project. Plus the team leads are all really nice fellows.

Because I am using Django under GAE, I watched Guido's Google I/O talk on Django and GAE. That made me realize I really wanted to use the GAE Helper for Django. Knowing all of this I downloaded the OS X SDK, the docs, the GAE Helper for Django, and got to it.

The GAE Helper for Django makes starting a Django project REALLY simple. Because the Helper doesn't support Django 1.0 from the download and I am starting out small, I just used the version of Django included with GAE. I then went about to creating a dumb little app that does nothing more than directly return a rendered template for my index.html so that I can play with the site look to start.

I also registered my domain with Google Apps. That allowed me to deploy my app on my domain. The only drawback is that GAE doesn't support a naked domain (e.g., drbrett.ca), so I had to explicitly set my site to www.drbrett.ca. Not a huge deal, but still, it would be nice to be able to forward from the naked domain to www.drbrett.ca (my DNS host service doesn't seem to have the support itself).

At the moment I have nothing more than a Django site with a single app that does nothing more than return render_to_response("home.html") for my index page, that's HTML 4.01 Strict compatible and is under revision control with Hg. But it still feels good to have the darn thing moving forward.

At this point my plan is to use the site for content that I want to have written down somewhere and that I don't have any problems sharing publicly. I don't expect the site to be of any huge interest to most folks, but I am looking forward to learning how to do a proper web app.

Next step, figuring out how to do unit tests before I move on to something that is in any way complicated.

2008-07-21

Web service idea: helping identify outdated web browsers

Google, ETH, and IBM released a paper about how 59.1% of users are running the most up-to-date browser available to them, and that a decent number of people were not running fully-patched versions. From a security and standards-compliance position, this is bad.

How can this be dealt with? One suggestion made by the authors was to have an integrated part of the browser's GUI that specified how "expired" their browser is. That's a good idea, but we all know that users are slow on the pick up in terms of upgrading, as the paper points out. So what to do?

Well, what happened if a prominent warning came up on various web sites that a person visited, telling them that their browser was out of date? If instructions were included on how to update, would people actually update their browsers? If some prominent web sites had this info, it is quite possible. But having to keep track of all that user agent info would be a pain in the rear for each site.

And that is where a web service would come in handy. If there was a simple RESTful API for people to hit where the user agent for a browser could be sent to and return, in JSON, whether the browser was outdated or not, how outdated by time it was, and the severity of how outdated it is, it would make it easer for sites to include such information. One could go as far as to include a link that went to the proper page listing instructions on how to update their browser.

Do people think that would actually be useful?

2008-06-15

What is the best way to learn Django and web development?

Dear Lazyweb,

With PEP 3108 nearing completion, it is time to start thinking about finally developing my personal web site (so that I can then redo my father's business web site). That means I need to learn web development in general, and Django in particular.

But how to begin? I was planning on reading the Django book, but is there something else I should also read?

And how about web development in general? I believe Django comes with a testing framework, but is there something else I should be using? Any common design pitfalls I should be looking out for?

I am not looking to do fancy web applications. I just want the skills necessary to take information, both entered directly into the web site or from external files, and display it online. The goal is to be able to easily redo my father's static web site such that he can log into the site's admin page and add/edit content directly without me having to walk him through it over the phone (in other words my dad can browse the web but I am not about to ask him to write raw HTML or something).

Anyway, any help that people can lend me would be greatly appreciated.

2007-11-30

Doug Crockford's suggestions on cleaning up HTML

Through Slashdot I found out about Doug Crockford's (creator of JSON) ideas on how to clean up HTML. The suggestions are rather sound. They focus on a security perspective which makes sense as that has caused the web a great amount of pain over the years.

HTML has grown from being a way to mark up documents and their relationships for display purposes to being the container for applications. Quite the transition. =) The suggestions made by Doug seem to be taking the idea of marking up documents and cleaning it up so that it is more in line with defining the components of information.

In a way, one could view all of this as MVC. HTML is the model, where you define how data is stored. The view is CSS which controls the precise presentation of the data. JavaScript is the controller, making sure stuff is manipulated properly between the model and the view. The only twist in this analogy is that HTML as the model also acts as the container for the view and controller (e.g., <script> and <link> tags to pull in JavaScript and CSS), but otherwise the analogy works. And Doug's suggestions seem to support the idea of this separation of concerns, albeit for security reasons.

2007-07-26

Python might make it into Firefox 4

Brendan Eich, CTO at the Mozilla Foundation, posted in his blog about three new projects that were announced. The one I care about the most is IronMonkey, which is to make Mozilla's Tamarin VM run IronPython and IronRuby (and thus I would assume .NET code that can run under Silverlight).

At least I don't have to feel bad about not getting to try to get Python into Firefox now. =)

2007-04-19

Learning about the world of microformats

I was reading Doug Napoleone's blog (who also did a Python todo; looks like I may have started a micro-trend) and I noticed in his sidebar a link to something called XFN. Always curious about new technology and what people are developing, I followed the link and had a look.

Turns out it is a microformat for explaining your relationship to someone. Now I have avoided microformats up to this point as they seemed to be riding a buzzword wave of popularity. But XFN seemed somewhat interesting (even if the page that led me to it didn't use it, Doug =) as it was geared towards marking up links to other pages to describe your connection. Normally this wouldn't be a big thing, but it makes sense for blogrolls.

When you bother to list blogs to actual people (I am using the term "blog" to mean an online journal maintained by a person that at least on occasion discusses their personal life and thus is not always about work), it is nice to know the connection between the person with the blogroll and the person on the other side of the link. I could link to anyone, but I would hope that people who like my blog or know me would care more about links to blogs of people I consider a friend or an acquiantance than ones to total strangers. And so the idea of XFN makes sense to me (and makes me wish someone would implement a Blogger page element for blogrolls that used XFN to make it easy to use).

And this is what led to the exploration of microformats. Basically they seem like a more usable version of the Semantic Web, which I like. Having done a paper on ontology languages (e.g., OWL) I never really jumped on the web ontology bandwagon for the Semantic Web. But I like the idea of being able to glean information automatically from a web page. Microformats seem like a reasonable solution for that.

But then I started to consider what is required in order to use them. Every time I do a link to someone's blog on Blogger (or any other WYSIWYG blog editor for that matter) do I want to go into the raw HTML and add the proper markup to implement XFN? No. But would I be willing to do it for information that I don't have to edit often or is auto-generated? Yes.

In the end the usefulness of microformats, for me, is whether I can write the information once and then forget it. Otherwise it must have tool support to make it easy to add the information. I am not about to edit raw HTML constantly to support a microformat.

In the end, without tool support, I could see myself using hCard, XFN, hResume, and rel-home. All of the other ones would need tool support to make me want to bother with them. Although if they have an icon at least it lets people know I bothered to put the effort into supporting the format and thus gives me a little bit more motivation. =)