The "Ambiguous Operator" in JavaScript
I found this style of non-deterministic programming to be "mind blowing".
I found this style of non-deterministic programming to be "mind blowing".
We're writing Pageforest applications for the iPad (e.g., Quoridor). One really confusing issue popped up that seems to be a bug only when running in the full-screen mode of the iPad.
When we turn the display from portrait to landscape we would get a window.resize event. But then, as a side-effect of measuring a DOM element (like reading elem.offsetHeight), a RECURSIVE CALL to our window.resize event handler is called. I couldn't believe it - but it's true. This is the one case I've seen where the browser makes a re-entrant call to an event handling function.
To fix it, we created a simple function to serialize all calls to our real event handler:
$(window).resize( function () { setTimeout(onResize, 0); } );
Now all calls to our onResize function will be serialized, instead of occuring re-entrantly while we are in the middle of handling the first resize event.
We're not sure why our app is getting two calls to resize during a portrait to landscape flip - it looks like it might be giving us a smaller intermediate size, for the purposes of displaying a rotation animation of the page to the new orientation.
HTML5 applications support an offline mode - all the files needed for an application can be saved in the client, so it can run without and internet connect. For a great explanation of offline applications see:
http://diveintohtml5.org/offline.html
As you can see from the article, the concept is simple - but it can be a hassle to use:
Seems simple enough. The problem comes in when you change your application files.
pf.py to the rescue - autogenerated app.manifest
In order to simplify the process for Pageforest applications, I've introduced a new command into the pf.py utility:
$ pf.py manifest
When you issue this command, an app.manifest file will be automatically created for you, listing all the files in your application. More than that, when an app.manifest file exists in the root directory of your application, it will be automatically be updated whenever you do a put command to the server. So if any files change or are added, you don't have to manually update the manifest file yourself.
Customizing Manifest Files
You may want to add additional resources that are not part of your private application files to your manifest. For example, the scratch application adds:
http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js /lib/beta/css/client.css /lib/beta/js/json2.min.js /lib/beta/js/utils.js /static/images/appbar/green-left.png /static/images/appbar/green-center.png /static/images/appbar/green-right.png /static/images/appbar/down.png /static/images/appbar/logo.png
When placed above the AUTOGENERATED line in your manifest file, pf.py will preserve these lines and not modify them.
Excluding Files From a Manifest
If you have a large number of big files, you may not want to include them in the manifest (browsers will typically not download more than a few megabtes of data to the application cache). To exclude them from being added to your manifest, you can put an EXCLUDE directive in the auto generated section of your app.manifest:
#!EXCLUDE: big-images
Any files in the big-images directory will now be omitted from the manifest.
I presented Pageforest to the Seattle JavaScript user's group last night.
It was great to have the forcing function of a presentation to wrap up some loose ends, and get the site into shape to work well.
The other speaker, Jordan Dobson showed of his amazingly pristine designs for iPhone apps using web-kit CSS craziness. He's able to to some "no-images" layouts that look beautiful, perform great, and load really quickly on the phone.
I also met Thomas Yip, of BeeDesk at a Startup Weekend event this week. He's looking at using Pageforest for his new product - could be the "killer app" to show off our platform?
I just got back from a 3 week trip where I left my laptop behind, and only took my iPad (and my mobile phone). Spending more time with the iPad has convinced me that it represents a sea-change just as important as Windows was in the early PC evolution. What makes the iPad such an interesting new platform?
But there is a dark-side to the Apple-owned iPad/iPhone platform; the fact that it is controlled by a single company which exercises strict control on entrance into the App market and protects it's own competitive interests by rejecting applications that they themselves want to monetize (they have already had the US Justice department get involved in anti-trust complaints, such as when Google tried to deliver it's Google Voice service on the iPhone).
I'm looking forward to an Android-based tablet, and the introduction of another App marketplace being run by Amazon. That will give developers a great choice with more than one option for application distribution.
I also think there's an opportunity for the HTML5 platform to evolve into a competing API/platform for application distribution. Web apps will evolve to have all the capabilities of the iOS platform (offline support, local storage, rich graphics (SVG + Canvas), camera and microphone support, etc.). But we still lack an App Store equivalent for web apps. Google announced one around Chrome at Google IO in 2010 - perhaps we will see them ship it with the introduction of Chrome-based tablets.
One of the Pageforest applications I've been working on has prompted me to write a template generation language (modeled after Django's Template Language - DTL). DTL has a number of features that allow you to re-purpose templates and combine them in interesting ways. Yet, as a template language, it does not use the familiar concepts we, as programmers, are used to in our primary programming languages.
This got me thinking about the generalized patterns we use to help us design complex systems, by decomposing them into simpler parts. I'll compare DTL with JavaScript to show how the facilities in one comapare to those in the other.
Yet, DTL is missing some important techniques for composition.
DTL is a very nice, and constrained, template definition language. And I like that fact that it does not expose the full complexity of a programming language to its users (which was it's creator's design philosophy). Yet it would be very useful to build language extensions via functional-like programming practices directly in the template language, without having to resort to escape functions that require writing custom tags and filters in Python.
As we've been developing the Pageforest service, we've been developing sample applications in parallel. We think the best way to motivate features to support in our service, is to actually build applications that utilize those services. In fact, we explicitly stated that we won't implement any feature that we don't have an imminent need from a JavaScript application developer (including ourselves!).
If you've seen our simple Scratch application sample, you'll see that a simple Pageforest application can be written in just a few lines of code. And your application can save and load data from a cloud data-store on behalf of your users.
What you may not have realized, is that documents can contain much more than a single JSON blob storage. In fact, each "document" in our system, can also have associated with it, any number of child "Blobs". The permissions for reading and writing these blobs are controlled by their parent document. Blobs can contain any Internet data-type, including images, sounds, pdf's, html documents, javascript files, or JSON persistence.
With this feature in mind, we decided to push the envelope with a Mandelbrot set viewer application with the following goals:
We started the project over the Memorial Day weekend, and today we have a working prototype that meets all but the last goal.
If you would like to play with the Mandelbrot Set Viewer, be aware that you must be signed in to Pageforest in order to generate tiles (you should be able to view existing image tiles without signing in).
The way the Mandelbrot Viewer works, is that whenever the map UI generates a request for an image tile (all of the tiles at all of the magnifications have been assigned names according to their position - even if the tile hasn't been generated yet), we simultaneously query the Blob store to see if the tile exists. If it doesn't, we queue up a tile creation task and send it to a Worker. Because workers don't have direct access to Canvas elements for drawing, we compute the data for the bitmap in the Worker, and send that back to the parent window when the Worker is done. It can then be quickly saved into a Canvas element, converted to a PNG file, and then uploaded to the server.
We had some difficulty getting compatability across browsers to support raw binary upload's via AJAX, so we instead just send a base64 (text) encoded version of the file, and decode the data on the server before storing it.
Once the tile is generated, we update the url in the map image, so the browser attempts to download the tile again.
As is all of Pageforest's code, this example has been made open source. You're welcome to make a copy to make your own variations.