Archive for the ‘Post’ category
I just gave my talk on Chrome Extensions at the Scandinavian Web Developer Conference:
The code for the extensions can be downloaded from http://files.11born.net/swdc/. Enjoy!
While working on hosting Dojo within Node I arrived at a neat solution to isolate the Dojo code from Node itself: evaluate it in a new context. Here’s how it’s done.
var sandbox = {};
process.binding("evals").Script.runInNewContext('this["-eval-"] = function(code){ eval(code); };', sandbox);
runInNewContext evaluates the code in a separate JavaScript context, sandboxed within our sandbox object. We then define this["-eval-"] to call the eval method from the context. This exposes the -eval- method on the sandbox.
We can call it:
sandbox["-eval-"]('this.foo = function(){ return "bar"; };');
require("sys").puts(sandbox.foo());
// bar
Unfortunately declaring global variables inside the context won’t cause them to be set on the sandbox, so this doesn’t work:
sandbox["-eval-"]('baz = function(){ return "thud"; };');
require("sys").puts(sandbox.baz());
// TypeError: Object #<an Object> has no method 'baz'
Same for accessing foo as a global:
sandbox["-eval-"]('this.baz = foo');
// ReferenceError: foo is not defined
I’m not quite sure why this is the case, global variables are treated a bit differently within the context.
On Saturday, May 22nd the first ever dojo.beer(“Copenhagen”) will take place. We’ll start as an open space meeting in the afternoon, discussing any subject related to JavaScript development. At some point we’ll progress into the “beer” part of the program.
Special guest is Dylan Schiemann, co-founder of the Dojo Toolkit project and CEO of SitePen.
I’m on the lookout for a good location to host the event. Suggestions are most welcome. Actual time and location will be announced here later.
MOCH A/S has graciously offered to host us. We’ll start around 15:00 at Toldbodgade 51 D.
So, are you a JavaScript hacker? Let us know you’re coming by signing up here.
In our previous installment we discussed how to create a simple extension for Chrome, using content scripts to interact with web pages visited by the user. Content scripts can be somewhat limiting however, so this time we’ll look into how we can run our extension code at all times, not just when a page is loaded. Coincidentally this is also a nice introduction to the general approach taken by the Chrome team when implementing extensions.
As you might know, each tab in the Chrome browser runs in an isolated process. This is done both for stability and security but it also means that Chrome is very good at running many small “web browsers”. Extensions run in isolated processes as well. In fact, you could say that extensions run inside hidden tabs. To put it differently, an extension is just a web page you can’t see.
Let that sink in a bit. Chrome extensions are just web pages. They have HTML, they have the DOM, they have JavaScript. They have all the browser features you have in a normal website!
Chrome has quite a few more tricks up its sleeve than content scripts. One of them is background pages. A background page is one of those web pages you can’t see. This is how you specify one in the manifest.json file:
{
"name": "Hello World",
"version": "2.0",
"background_page": "background.html"
}
background.html is the path to the background page in the extension directory. It can be called anything really, but by convention it’s called background.html. There can be only one background page per extension and it’ll exist as long as the browser is open (and the extension remains installed). You can even open the Web Inspector for a background page: simply click on its name in the Extensions overview.
Now, if the background page were really just another web page that happens to be hidden, it’d be rather useless. Web pages can’t talk to each other, so what could the background page possibly do!? This is where we get to the really great part about the Chrome extensions: there’s a special set of JavaScript APIs that can be used to give your extension way more power. These APIs are all inside the window.chrome object and are accessible from background pages and content scripts.
For example, the chrome.extension.getViews() method returns a list of window objects of the various tabs the extension has access to. Let’s try to recreate the Hello World example with a background page.
background.html:
<script>
chrome.extension.getViews().forEach(function(view){
view.alert("Hello world");
});
</script>
Since the background page is an HTML document, we do need to wrap our code inside a <script> tag. Note that we can use Array.prototype.forEach (introduced in JavaScript 1.6) here. One of the niceties of Chrome extensions: more powerful JavaScript!
When you install this extension it will alert “Hello World” straight away, since this code runs when the background page loads. That’s nice, but not really what we had in mind. And, its alerted only once, so apparently the extension only has access to itself. chrome.extension.getViews() (see docs) doesn’t return all tabs, it only returns those that the extension is loaded into through a content script, plus its background pages. Since we don’t want to use a content script this time around, let’s see if we can get access to the tabs that are currently open.
As the background page is still isolated from the rest of the browser, it needs to talk through the Chrome APIs to access other tabs. For this to work though we need to request the appropriate permissions. To access the tabs, we need to request the tabs permission. Update the manifest file:
{
"name": "Hello World",
"version": "2.0",
"background_page": "background.html",
"permissions": ["tabs"]
}
We can get all tabs in a given window using chrome.tabs.getAllInWindow() (see docs). This is an asynchronous method, so we need to pass it a callback. Also, we pass null as the first argument to get the tabs in the current window:
chrome.tabs.getAllInWindow(null, function(tabs){});
You’ll find that many API methods in Chrome are asynchronous.
Here’s our updated background.html, which alerts “Hello World” for each open tab and includes the URL of each tabs current page for good measure:
<script>
chrome.tabs.getAllInWindow(null, function(tabs){
tabs.forEach(function(tab){
alert("Hello world\n" + tab.url);
});
});
</script>
It’d be extra nice if we could run the alert() from within the tab itself. To do so we can use chrome.tabs.executeScript (see docs), which executes a script (either from a string or a file) inside a given tab:
<script>
chrome.tabs.getAllInWindow(null, function(tabs){
tabs.forEach(function(tab){
chrome.tabs.executeScript(tab.id, { code: "alert('Hello World')" });
});
});
</script>
This, however, doesn’t work! It turns out that we don’t have permission to execute scripts inside the tab. If you open the Web Inspector for the background page, you’ll notice this:
Error during tabs.executeScript: Cannot access contents of url "http://supercollider.dk/blog". Extension manifest must request permission to access this host.
Remember how with the content script we had to specify which URLs it matched? We’ll do the same here, but add the URLs to the permissions instead:
{
"name": "Hello World",
"version": "2.0",
"background_page": "background.html",
"permissions": ["tabs", "http://*/*"]
}
Now when the alert comes up, Chrome focuses the tab the alert originated from. Success! (You might still see some error logs for https:// pages and the internal Chrome pages, these were not part of our permissions.)
This is all good, but it only works when the extension loads. How can we know when a tab loads? Well, there’s the chrome.tabs.onUpdated event (see docs) which fires when a tab starts loading and when the loading has completed:
<script>
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
if(changeInfo.status == "loading"){
chrome.tabs.executeScript(tabId, { code: "alert('Hello World')" });
}
});
</script>
You can listen to Chrome API events by calling addListener on the event object. You pass a callback function, which is called with specific arguments depending on the event. As you can see this is not the typical DOM event model, it’s better geared to the API use cases.
In this case tabId is the identifier for the tab, changeInfo contains some information about the update, and tab is a reference to the tab object itself (just like the tabs returned by chrome.tabs.getAllInWindow()).
At this point we’ve reproduced the original Hello World example, but now through a background page. In our next installment we’ll look more closely at the security constraints on Chrome extensions.
Earlier this year Google’s Chrome browser landed official support for extensions. This is incredibly exciting, not only because extending browsers is cool, but because Chrome’s extensions are fully based on open web standards. And who knows about open web standards? Yup, web hackers.
In other words, if you can build a website, you can build a Chrome extension. They don’t consist of anything else but HTML, CSS, JavaScript, HTML5ish features such as localStorage and <canvas>, and some APIs (implemented in JavaScript) to interact with the browser itself. It’s much easier than developing extensions for Firefox, which has a complicated setup and configuration and the XUL language to work with Firefox’s user interface. (Admittedly, Mozilla is trying to rectify this through Jetpack, which I haven’t looked into closely, but is not included by default in Firefox.) Another advantage of Chrome over Firefox is that Chrome can reload extensions without restarting the browser, which is a fair bit nicer!
Let’s see about building a very simple extension that will alert “Hello world” for every page you load. This will help cover the basics of extension development. First, open up the Extensions overview, which is under the Tools menu in the toolbar. This page shows the extensions you’ve already installed. It also has a Developer mode, which you can select by clicking on the “Developer mode” link in the top right. This should show a few extra options: “Load unpacked extension…”, “Pack extension…” and “Update extensions now”.
We’ll focus on “Load unpacked extension…” first. If you click on it a folder selector dialog will come up. It only lets you select folders, which is great because a Chrome extension is nothing more than a folder with a few files! In the folder selector, go to your Documents folder and open it. Chrome will try to open the Documents folder as an extension, which, of course, is silly. Luckily it finds out quickly and gives this error message:
Could not load extension from ‘/Users/mark/Documents’. Manifest file is missing or unreadable.
This then brings us to what a Chrome extension really is: a manifest file inside a folder. More specifically, a file called manifest.json, that contains a valid JSON object describing your extension. At the very minimum, a manifest file looks like this:
{
"name": "Hello World",
"version": "1.0"
}
Create a hello_world directory somewhere on your computer, and place the above in manifest.json (inside that directory). Now in Chrome, click on “Load unpacked extension…” again and open the hello_world directory you just created. You’ll see how the extension is added to the list of installed extensions. Congrats, you just build your first Chrome extension!
Uhm, okay, technically the extension doesn’t do anything yet. There are a few different ways an extension can interact with the browser, but for now we’ll just look at content scripts. These allow you to run JavaScript for pages visited. If you’ve ever written a user script for Greasemonkey you’ll be familiar with content scripts, since they do pretty much the same thing. In fact, Aaron Boodman, who originally started Greasemonkey, is a main driving force behind Chrome extensions.
An extension can define multiple content scripts, each of which can load multiple JavaScript files. First create alert.js in the hello_world folder, it should contain:
alert("Hello world");
To load this for all web pages we use the following manifest:
{
"name": "Hello World",
"version": "1.0",
"content_scripts": [
{
"matches": ["http://*/*"],
"js": ["alert.js"]
}
]
}
content_scripts is an array, each item being a declaration of the actual content script. matches lets you specify on which pages you want your content script to work, by providing a set of match patterns. js specifies which JavaScript files (included in your extension folder) to load if the page matches. (And yes, technically speaking this content script only works with http:// sites, not https://.)
In the Extensions overview, click the “Reload” link underneath the “Hello World” extension. This will reload the extension. Then go to any website and you should see a “Hello World” alert as it loads.
You can also specify CSS files that should be included on the matched pages. Create red.css (again in the hello_world folder) containing the following:
html, body { background: red !important; background-image: none !important; }
Change the manifest to:
{
"name": "Hello World",
"version": "1.0",
"content_scripts": [
{
"matches": ["http://*/*"],
"css": ["red.css"],
"js": ["alert.js"]
}
]
}
Save and reload the extension. Again go to any webpage and it should now have a red background color.
Admittedly this example extension is rather contrived. In future articles we’ll build more advanced extensions, look at different UI concepts supported by Chrome extensions, Chrome’s security model and how you can publish your extensions for others to use. In the meantime, have a look at the official documentation for Chrome extensions.
As a final note, I’ll be speaking about Chrome Extensions on the Scandinavian Web Developer Conference in Stockholm on June 2nd. Go check it out!
Just a quick tip: if your login form is missing the action attribute, Chrome won’t offer to remember the user’s password. This is tracked as issue 29513 on Chromium.
Update May 8, 2010: The issue has been resolved, so this should be fixed in Chrome soon.
On June 2nd and 3rd Stockholm will be home to the Scandinavian Web Developer Conference. Day one covers front-end & back-end development, day two covers the mobile web. I’m giving a talk titled Chrome: Browser Extensions for Web Hackers. There’s a 20% discount until the end of the month, so check out the insanely great lineup and get your ticket!
Chrome Extensions files (those with the .crx extension) are, in essence, signed ZIP files. The extension data is signed with your private key, while the public key is included in the .crx. A hash of this public key is used as the extension identifier when you install the extension. This identifier is important because you need it if you want to generate an update manifest. (Of course, if you’re hosting your extension on the extension gallery you won’t have to worry about this.)
Let’s say you’re hosting your extension yourself and you want to build the .crx file and the update manifest automatically. You could install the extension first and copy the identifier from the extensions list, but you can also calculate the identifier.
Chrome Extension developer Erik Kay explains the format on Stack Overflow:
To be precise, it’s the first 128 bits of the SHA256 of an RSA public key encoded in base 16.
Another random bit of trivia is that the encoding uses a-p instead of 0-9a-f. The reason is that leading numeric characters in the host field of an origin can wind up being treated as potential IP addresses by Chrome. We refer to it internally as “mpdecimal” after the guy who came up with it.
Here’s a short Ruby script to do exactly this:
require "openssl"
require "digest/sha2"
def pkey_to_id(pkey)
# Key algorithm, found in <http://github.com/Constellation/crxmake>.
algo = %w(30 81 9F 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 00 03 81 8D 00).map{ |s| s.hex }.pack("C*")
# Calculate public key, get hex hash of first 128 bits / 32 characters
hash = Digest::SHA256.hexdigest(algo + OpenSSL::PKey::RSA.new(pkey).public_key.to_der)[0...32]
# Shift hex from 0-9a-f to a-p
hash.unpack("C*").map{ |c| c < 97 ? c + 49 : c + 10 }.pack("C*")
end
For example the extension id for this private key:
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANRvspoXYkKCTQple
mUX/Umh8zgmmz7xJ/oUiQSca7vd/3eDvLRBTOy7o4NwRmIzDHr/AbDkVRzXDd6ale
oGBj8ABvAf+3XAO7KdFsjIxmSfUI5M7F8EsqTDT+AR+YGiGOrF/9s4ganiqGSyIuk
Fe1UWrxlUBHKcazzgSdpsOZ2pAgMBAAECgYBNHIJ7NpO/SqcGaBGGkq+pQ7USo8jk
jwsQ1tVprBHbLtklm9cqoy12HSJceqvBx3/3QYtul2NhxZpOPFTAjxFCsaBP5I8rn
fgFzdSvKZXtZmQ7DsYaglclYqSwhKtKM9j5xVbqEh4r0LXYAvM1dlRSJQrFtqhLiI
Nc5jyWL2HHxQJBAPMWXG8BOwo0yM3eb27Foz6jjO92iQ+pHgWNFoW+QZIhVUGHkIH
ESl94UF86k0uurVBO22oHNoeLAwZ1XLIulN8CQQDfuIbPu4WAGyshyT/rdk/MuRXd
gcnbUkwKbyYfiKsSLpmMryM9ugFqyO+AQNIGA1xQHEP3znxUE/Y1tyE74NZ3AkBih
dOc4gDN2Cry1Y6QdOX/A0ah34cZo8+ZLF/OgRgOZBgr4Qf+sFH8c8UPc6wzZm60N+
HSDW5abUsimPqi9SI9AkEAzhbaeXqxXHWqohEWRP5UPK8zqT3qiZOiYOpLIDlx/en
XoXWk7TPwIkK//lG4J7nozBN9uUYJ2hoZcRomD1bruQJBAI49v2hvt24JV870F8Lf
oEReK/26DpyMFfH7a4I4O2JkGX79M/aVXBbSbNlnl01Esoxsx9kYzksP4CpR7CdYH
og=
-----END PRIVATE KEY-----
is cigbjabahnfnnmplhmjeolnhobhfjggp.
The script uses OpenSSL::PKey::RSA.new(pkey).public_key to calculate the public key for the given private key. It then adds the key algorithm (a subject of which I understand not much more than what is described on Wikipedia) and takes the SHA256 hash in hexadecimal form. Of this hash it takes the first 32 characters, corresponding to the first 128 bits of the SHA256 hash.
Finally we need to shift from 0-9a-f to a-p. Technically this means that the extension id is not in hexadecimal format, but it is still in base 16. hash.unpack("C*") gives an array of ASCII character codes for the string. Each character code in the original 0-9a-f format is mapped to the corresponding code in the a-p format. We can exploit the ASCII table for this. Digits are character codes 48 to 57, while lowercase characters start at 97. Therefore, we can simply add 49 (the difference between 97 and 48) to each number and, since we’re shifting by ten characters, 10 to the letters a-f. Finally we pack("C*") the character codes back into the extension id.
I’ll be writing more about Chrome Extensions here, and am giving a talk on the subject at the Scandinavian Web Developer Conference at the end of May in Stockholm. I’ll also give a brief Chrome Extensions Primer at the Øresund JavaScript Meetup in Malmö this Wednesday.
Computed style values for clip:rect() are different in WebKit compared to Gecko and Opera. Given this test code:
<div id="test" style="clip:rect(0, 50px, 50px, 0);width:100px;height:100px;position:absolute;background:red"></div>
<script>
window.onload = function(){
alert(window.getComputedStyle(document.getElementById("test"), null).clip);
};
</script>
You get:
- WebKit:
rect(0px 50px 50px 0px) - Opera:
rect(0px, 50px, 50px, 0px) - Gecko:
rect(0px, 50px, 50px, 0px)
Nothing I couldn’t fix in the regular expression I was using to split the values, but an odd difference nonetheless.
Being a Dojo hacker I’ve been wanting to use Dojo in combination with Node for a while now. So on a recent flight to London I added support for the Node environment to Dojo. I cleaned it up yesterday and – after figuring out Git – the code is now available on my Dojo fork.
Dojo is available for other environments than browsers, although the pre-compiled Dojo Base code you might have downloaded will only work in a browser. Other supported environments are Firefox extensions, the Rhino JavaScript engine and the Spidermonkey JavaScript engine. And now, Node.
Dojo is able to support multiple environments by dynamically bootstrapping itself for the given environment. In the non-compiled code, the dojo.js file detects its environment and loads the appropriate hostenv_*.js file. The biggest task of the various hostenv files is to fix the loader code to ensure dojo.require() works. Depending on the environment the file might also add some other features, for example the Rhino environment adds an implementation for setTimeout.
Right now I’m detecting the Node environment by seeing if the process object exists in the global scope. This object provides various utility methods to Node and is, as far as I know, unique to just the Node environment.
We briefly need to interrupt this explanation by discussing how we invoke Dojo within Node. As far as I can tell Dojo needs to exist in the global scope, and the only way to accomplish this is by loading the Dojo code when Node starts. Therefore you’d run node dojo.js to kick things off.
Based on this invocation we can use the path to dojo.js to calculate the root location of the Dojo files. I use process.ARGV[1].replace(/[^\/]+\.js$/, "") to do this. The primary reason for calculating the root is because the Dojo bootstrapping code uses the root location to load the host environment file. Technically I could have left it empty but that’s a bit silly.
Finally we use require() to load further bootstrapping code, the loader, the host environment and Dojo Base. As a special trick for the Node environment, dojo.js invokes dojo._loadInit() to signal that the environment is ready for use. In browsers this function would be invoked on DOM ready, but of course that’s not possible in Node.
The Node host environment file (hostenv_node.js) patches the loader so we can use dojo.require() in combination with Node’s module loading support. I’ve also added support for passing djConfig properties to Dojo. Simply pass the JSON object to the --djConfig argument: node dojo.js --djConfig='{isDebug:true}'.
Because we have to start Node with the dojo.js file we need a way to load additional JavaScript code into Node. This is accomplished by passing the -s or --script argument, which should point to a JavaScript file to be loaded into Node with require().
Currently the Node environment is largely untested, and it is quite probable that there are parts of Dojo that are depending on other features that haven’t yet been ported. I did try implementing the XMLHttpRequest object however, as a wrapper around Node’s HTTP libraries, to make it easier to execute HTTP requests through dojo.xhr().
Check out the code at Github. Some examples are also available. See the documentation on usage.
Last month I travelled to Stockholm to give a lecture at Södertörn University. Entitled Building Installations in Five Days (and a bit) it discussed the main takeaways from the Hacker camps run by Mediamatic at PICNIC:
- Simplify, simplify, simplify, because there’s only five days and because it’s about the real value of the experience.
- Constraints are freeing, they limit what you can attempt, so you can actually build your installation.
- Have a Plan B, so you focus on what you can do in Plan A, and never even need Plan B.
- Share your shit, shared brainstorming, shared problem solving, shared code.
- Find a mentor, for experienced outside feedback.
- Get a support team, so you don’t have to run to the hardware store yourself.
These takeaways are illustrated by actual projects undertaken in the past three years, with a focus on the ikSpin, a frisbee game created by Eelco Wagenaar and myself.
Via Paul Irish a bunch of tips on optimizing your HTML structure. From the obvious in unobtrusive coding (no onclick="…" attributes) to not specifying method="get" on form elements, 22 tips on optimizing your site’s HTML.
Using the localStorage object, the storage event and the postMessage() API, it is possible for browser windows to discover each other and to communicate with each other.
Crosscasting is a small Dojo package that publishes Dojo PubSub events to other browser windows that are running the Crosscasting code and are active within the same domain. Crosscasting of course stands for cross-window broadcasting.
Check out the example page, which of course you should open a couple different windows. Right now this only seems to work in the latest WebKit nightly builds.
The implementation is quite straight-forward. The first part is the Window Discovery Phase. An item is set in localStorage, which triggers the storage event. The Storage Event object has a source attribute which points to the Window object that set the item. (The storage implementation in Firefox 3.5 does not support this.) This is how a window informs other windows of its existence. The other windows subsequently use the postMessage() API to send a message to the original window. The Message Event also has a source attribute, pointing at the Window object that posted the message. At this point all windows know of each other’s existence. This phase is triggered by invoking supercollider.crosscast.init()
The second part is broadcasting Dojo PubSub events. Using supercollider.crosscast.subscribe("topic") you can register topics for broadcasting. The topic and any arguments are serialized to JSON and send to all other windows through postMessage(). The other window deserializes the message back to the PubSub event and publishes it locally.
// Initialize and start discovery
supercollider.crosscast.init();
// Subscribe to a topic for crosscasting
supercollider.crosscast.subscribe('crosscast/test');
// Subscribe to the topic
dojo.subscribe('crosscast/test', function(s) { alert(s) });
// Publish a PubSub event, both locally and to other windows
dojo.publish('crosscast/test', ['hello world']);
Again, have a look at the example. You can find the source at js-collider/crosscast.
P.S. I do not believe this is an original idea, but when I set about implementing this earlier today I could no longer find the site where I read this first. If you do know which site I’m talking about, let me know in the comments so I can give proper credit. Thanks!
I spoke at Geek Meet in Stockholm last night. The slides are now up on Slideshare:
- Web Typography and sIFR 3 is about the current state of web typography, and a quick run through sIFR 3
- Homemade Ubicomp is about ubiquitous computing you can do in your kitchen, with examples from PICNIC and the Copenhagen Institute for Interaction Design.
I had a great time, thanks to Robert Nyman and bwin for organizing.
dojo.Deferred would have been part two in my single part series on Method Chaining. It’s a pretty awesome way for setting up callback hierarchies for asynchronous programming:
function async() {
var d = new dojo.Deferred();
// Start something asynchronous,
// call d.callback(response) when done.
return d;
}
async().addCallback(function(response) {
alert('Ready!');
return response;
});
I can add multiple callbacks to async() or even chain them to the result of adding a callback:
async().addCallback(function(response) {
alert('Ready!');
return response;
}).addCallback(function(response) {
alert('Double ready!');
return response;
});
Parallel to the callback hierarchy, there’s an ‘errback’ hierarchy which is invoked in case a callback throws an error. This makes it easy to handle errors within the callback chain. Unfortunately it also prevents the error from being logged in the browser’s error console.
Luckily, it isn’t hard to log these errors ourselves. Simply run the following before using any deferreds:
;(function() {
var addCallback = dojo.Deferred.prototype.addCallback;
dojo.Deferred.prototype.addCallback = function() {
var cb = addCallback.apply(this, arguments);
cb.addErrback(console.error);
return cb;
};
})();
This overwrites the original addCallback method to automatically register an ‘errback’, which logs to console.error. Then, it returns the original return value, so it doesn’t affect other code.
Happy Dojo’ing!
XStream is a cool library for serializing Java objects to XML files, and back again. Given that I prefer to work with JavaScript, rather than Java, I spent some time today trying to make XStream work with Rhino objects.
First, a quick example of XStream, from their two minute tutorial. We start with two small Java classes:
public class Person {
private String firstname;
private String lastname;
private PhoneNumber phone;
private PhoneNumber fax;
// ... constructors and methods
}
public class PhoneNumber {
private int code;
private String number;
// ... constructors and methods
}
Set up XStream:
XStream xstream = new XStream();
xstream.alias("person", Person.class);
xstream.alias("phonenumber", PhoneNumber.class);
And instantiate the classes, plus serialize to XML:
Person joe = new Person("Joe", "Walnes");
joe.setPhone(new PhoneNumber(123, "1234-456"));
joe.setFax(new PhoneNumber(123, "9999-999"));
String xml = xstream.toXML(joe);
And here’s the result:
<person>
<firstname>Joe</firstname>
<lastname>Walnes</lastname>
<phone>
<code>123</code>
<number>1234-456</number>
</phone>
<fax>
<code>123</code>
<number>9999-999</number>
</fax>
</person>
Good, readable XML, as a serialization from Java objects. Going back is as easy as:
Person newJoe = (Person)xstream.fromXML(xml);
XStreaming Rhino
Unfortunately, things aren’t as easy when you try to serialize a JavaScript object from within Rhino:
xstream = new Packages.com.thoughtworks.xstream.XStream();
xstream.toXML({foo: 'bar'});
This results in a rather long error stack trace, which boils down to:
org.mozilla.javascript.WrappedException: Wrapped com.thoughtworks.xstream.converters.ConversionException: Could not call org.mozilla.javascript.NativeObject.writeObject()
---- Debugging information ----
message : Could not call org.mozilla.javascript.NativeObject.writeObject()
cause-message : null
cause-exception : java.lang.reflect.InvocationTargetException
-------------------------------
The problem here is that Rhino objects can’t be directly serialized by Java classes. Luckily, XStream is quite flexible and allows you to write your own serializer. Or, in XStream terms, Converter. So, that’s what I did:
xstream = new Packages.com.thoughtworks.xstream.XStream();
converter = RhinoConverter.create();
xstream.registerConverter(converter);
xstream.toXML({foo: 'bar'});
This gives:
<org.mozilla.javascript.NativeObject>
<object>
<foo type="string">bar</foo>
</object>
</org.mozilla.javascript.NativeObject>
Before we continue, I’ve put the code up on Github. Here’s an example file.
If we serialize the following object:
{
'foo': 'bar',
'answer': 42,
'truth': true,
'falsehood': false,
'nothingness': null,
'everything': undefined,
'nested': {
'birds': 'nest'
},
'feist': [1, 2, 3, 4],
'now': new Date
}
We get:
<org.mozilla.javascript.NativeObject>
<object>
<foo type="string">bar</foo>
<answer type="number">42.0</answer>
<truth type="boolean">true</truth>
<falsehood type="boolean">false</falsehood>
<nothingness type="null"/>
<everything type="undefined"/>
<nested>
<object>
<birds type="string">nest</birds>
</object>
</nested>
<feist>
<array>
<length type="number">4</length>
<_0 type="number">1.0</_0>
<_1 type="number">2.0</_1>
<_2 type="number">3.0</_2>
<_3 type="number">4.0</_3>
</array>
</feist>
<now>
<date stamp="2008-11-09T23:13:26.282+01:00"/>
</now>
</object>
</org.mozilla.javascript.NativeObject>
What’s interesting here is that only the XML root element is org.mozilla.javascript.NativeObject. This root element is created by XStream, and is a serialization of the main object. From XStream’s point of view, this main object is a Java object, as modelled by Rhino. The converter itself, however, is written in JavaScript. All descendent elements are serializations of JavaScript objects. That’s why <nested> doesn’t contain a <org.mozilla.javascript.NativeObject>.
The constructors of the JavaScript objects are retained in the XML, in the form of <object>, <array> and <date> elements. Children of these elements are the object’s properties. Primitive data types are indicated by the property having a type attribute, and a raw value. <date> elements have an extra stamp attribute, which is the value of the original Date object in RFC 3339 format. Because XML property names may not start with a digit, the array indices are prefixed by an underscore. (And yes, underscores themselves are escaped by another underscore. _ is serialized to __.)
It’s possible to add custom constructors to the converter:
function Klass() {
this.property = 'foobar';
}
Klass.prototype.print = function() {
print(this.property);
};
converter.register('klass', Klass);
k = new Klass;
k.property = 'hello world';
xml = xstream.toXML(k);
Here I’ve created a class Klass, and registered it with the converter we created earlier. This does run against XStream’s alias() method, which you saw earlier in the XStream example. This is because XStream deals with Java objects, and it’s our JavaScript converter that deals with JavaScript objects.
The XML serialization is as follows:
<org.mozilla.javascript.NativeObject>
<klass>
<property type="string">hello world</property>
</klass>
</org.mozilla.javascript.NativeObject>
We can now deserialize the XML, and run Klass.prototype.print(), to see if deserialization worked:
k1 = xstream.fromXML(xml);
k1.print(); // 'hello world'
Marvelous!
Look ma, no constructor!
Here’s the code which creates an instance for deserialized objects:
object = {};
object.__proto__ = constructor.prototype;
This is where the JavaScript truly shines. Rather than doing object = new constructor(), where constructor is a previously derived reference to a constructor method, we simply create an object and point it to the prototype of the constructor, without invoking the constructor method!
At this point it may help to explain how JavaScript finds a property on an object. If we have object o, and we try to resolve o.foo, JavaScript first checks if o has a property foo. If it does, it just returns the value of this property. If it does not, JavaScript checks if the object referenced by o.__proto__ has the property. If it does, the value is returned, if it doesn’t, o.__proto__.__proto__ is checked. This continues until either foo has been found, or we run out of __proto__ references. In JavaScript, __proto__ tends to point to a prototype object of a constructor method. Object.prototype for example. The __proto__ references form a prototype chain. Object.prototype is usually the last object in this chain.
As it turns out, we could program, say, new MyClass(), ourselves, like this:
function MyClass() {
this.foo = 'bar';
};
MyClass.prototype.baz = function() {
return 'thud';
};
var auto = new MyClass();
auto.foo; // 'bar'
auto.baz(); // 'thud'
var manual = {};
manual.__proto__ = MyClass.prototype;
MyClass.apply(manual, []);
manual.foo; // 'bar'
manual.baz(); // 'thud'
Strings
When working with Rhino, the Java versus JavaScript object issue comes up more often. In the converter code, you’ll often see something like '' + reader.getAttribute('type'). For example:
switch ('' + reader.getAttribute('type')) {
case 'string':
value = '' + reader.getValue();
break;
The problem is that reader is a Java object, and reader.getAttribute('type') returns a Java string. For some reason, Java strings don’t match JavaScript strings in switch() statements, although they often do otherwise:
javaString = new Packages.java.lang.String('string');
javaString == 'string'; // true
switch(javaString) {
case 'string':
print('Match');
break;
default:
print('No match');
}
// 'No match'
Something to watch out for!
XStream & Rhino
Back to XStream. What I’ve built now is a basic implementation, which does not support duplicate or circular references. Neither does it serialize JavaScript functions, and I haven’t really tried serializing Java objects referenced by a JavaScript object. But, it’s a start! Let me know if you use it, find faults, or want to commit a fix.
Last month, together with Andreas Rasmussen and Anders Borre Hansen of MacVærk and Aron Allen of Copenhagen Cocoa, I co-organized iPhone Dev Camp Copenhagen. We saw fifty people show up for pizza and a quick iPhone crash course, and during the night about 20 people stayed to work on their iPhone apps.
Together with Aron, Jonathan Bunde-Pedersen and Philip Bruce I worked on TrainTrack, a neat little app which shows the next departures from S-Train stations here in Copenhagen.
Above is a small sketch of the TrainTrack UI. Here’s what we ended up with after a night of hard work (back then, it was less broken):
The feature set on the morning of October 4th:
- Displaying next ten departures from all S-Train stations.
- Support for favorite stations.
- Finding the nearest station, based on GPS coordinates. Or, well, finding whether København H or Lyngby is the closest station, since we had only entered GPS coordinates for those two stations.
Since we wanted the app to work even without a data connection, and we didn’t want to query a web service to find the next departures, we had to figure out a way of getting the departure time table. The best hackish way to do that was to parse a RTF file found on the DSB website.
This then was my task. That’s right, I went to iPhone Dev Camp and I wrote Python code!
I figured out how to parse the RTF file to extract stations and departure intervals from those stations, taking into account the various exceptions, such as weekends, rush hour trains, et cetera. At least, I hope I did. I’ve had to make some improvements to the database since the camp, and I’m still not confident that it’s fully accurate. Which makes sense, because parsing an RTF file is the wrong way to get the data!
As it turns out, it should be possible to get the database from Rejseplanen, which gives us a reliable solution. Then, of course, we’ll also have to figure out how to keep the database up to date, and perhaps discover last minute delays.
For the camp though, getting the data from an RTF file worked out quite okay.
Jonathan and Philip did most of the application programming. The departure times and favorites were stored in a SQLite database. Following the MVC paradigm, we used a model to manage favorites, query train stations and departure times. There were views and controllers for the station list, favorites list, nearby stations list, and the departures list. This, of course, worked quite nicely. Unfortunately we arrived at a hacky way of figuring out the next departures, by using integers for departure times rather than NSDate objects. This introduced some bugs, especially after midnight. Another example of where the quick ‘n dirty way breaks down quickly and dirty.
That said, we really did build a prototype of the app. We’d like to take it further, make some big improvements and hopefully put it up on the App Store. The current version is working a lot better, at least:
I had a great time at iPhone Dev Camp, and it was quite cool building a small app. It helped me grasp the concepts of Cocoa development and Cocoa itself. It’s a bit different from web programming, but still quite straightforward.
TrainTrack screenshots on Flickr
Home Made Ubicomp. Slides plus presenter notes from my presentation at SHiFT 08 in Lisbon, Portugal.
Photo by Lali Masriera. CC-BY-2.0.
Ubiquitous computing, or physical computing, or everyware, or pervasive computing, or ambient intelligence, or whatever you may want to call it, are terms for computers that are not in front of you, but around you. It’s about an invisible cloud of computerized intelligence that has filled up all spaces you could ever go.
This fluffy computer stuff is or will be in your clothes, on your banking cards, in the packaging of the food you buy, in the keys to your house. It’ll come in the form of RFID tags, Bluetooth devices, and sensors: for heat, movement, smell, taste, and so on.
Basically, it’ll be everywhere. It’ll be ubiquitous. It’ll be ambient. It’ll be physical. It’ll be pervasive. You get the point.
Photo by Incase Designs. CC-BY-2.0.
And all these things will be interconnected. Sensors will pick up the RFID tags in your clothes, so when you walk into a jeans store, a computer can analyze the brand of jeans you’re wearing, and suggest which pair to try on. Your fridge knows which dinner ingredients are available, so it can suggest recipes; warn you when the milk is out of date, and automatically order food. Your house knows when you arrive, so it can switch on the lights.
In all, pretty awesome!
Photo by Michell Zappa. CC-BY-2.0.
Provided, of course, that we get this big utopia working. Of which I’m somewhat skeptical, and Tijmen, who’s giving a talk later today, is even more skeptical. So, go see his talk.
Photo by Michell Zappa. CC-BY-2.0.
Also, it’ll become possible to track where you are. Which supermarkets do you frequent? How much time do you spend in that hotel, when you’re supposedly working late? What is your daily exercise route? It’ll be known, both by governments and private parties. Probably without your knowledge or consent.
Where will this take us?
Photo by Daniel Martini. CC-BY-2.0.
This, then, is the fundamental question of our technological age. We do concern ourselves with questions about privacy, and yet we eagerly give it up. How much does Google know? It knows what I search for, and therefore it can deduce that I’m a web developer. It knows where I live – for that is the starting address of Google Maps, and the country most searches originate from. It knows where I travel, when the searches originate from a different country, and perhaps even a different city.
It knows a lot, you know.
And with ubicomp, a lot of organizations are going to know a lot more. How we’re going to deal with that, I do not know. Nor do I intend to answer that question here, so that’s okay
Photo by Lali Masriera. CC-BY-2.0.
However, what I do know, is that we have to start playing with ubicomp ourselves. Because only then can we hope to understand privacy issues, as well as figure out what we actually want it to do. And if we never reach utopia, at least we have made our lives more fun and interesting on the way.
And, on the road to utopia, we will hopefully be able to stop big company interests from dictating how our environment is going to react to us.
Photo by Ed Schipul. CC-BY-SA-2.0.
To illustrate this, I’m going to read out for you a few bits of the Ambient Intelligence Vision Scenario from Philips.
Photo by Jon Fife. CC-BY-SA-2.0.
Ellen returns home after a long day’s work. At the front door she is recognized by an intelligent surveillance camera, the door alarm is switched off, and the door unlocks and opens. When she enters the hall the house map indicates (…) that her daughter Charlotte is in the children’s playroom, where she is playing with an interactive screen. The remote children surveillance service is notified that she is at home, and subsequently the on-line connection is switched off. (…) She briefly connects to the playroom to say hello to Charlotte, and her video picture automatically appears on the flat screen that is currently used by Charlotte.
Source: Scenario from http://www.research.philips.com/technologies/syst_softw/ami/vision.html
What jumps out first is surveillance. You’ve got to ask yourself, is this the first thing we can come up with in ambient intelligence scenarios? Surveillance?
However, surveillance is ever more important. Not in the least because we seem to want it ourselves. In a society based on fear, technology is a method of alleviating the fear. However, ubicomp is not romanticized for its utility in security and surveillance, it’s romanticized or the positive stuff.
This then is about play. Something positive?
Charlotte is in the playroom. She’s playing with a screen. Hmm, that’s not very ubicomp now is it? But the worst part is that all the mother does, is connect to the playroom from somewhere else in the house, just to say hello. Through the screen.
All this technology, and we can’t figure out how to have actual play between mother and daughter? Actual, interesting interaction? Like “magic bracelets”, which can glow based on remote commands. Perhaps used by the mom to encourage her daughter before an exam.
No. Big companies won’t be bringing us the kind of ubicomp that we can actually use. Instead, they’ll likely focus on complete home automation systems, on retail services. Not on play, not on fun, not on open networks we can hack ourselves. Therefore, rather than wait for the big corp version of ubicomp, we should take matters into our own hands and go build it ourselves!
We must build our own ubicomp because only then will we learn to understand it. Because only then will we figure out precisely why we’d want it. Because only then can we introduce fun and play into it.
Photo by Sara Petagna. CC-BY-2.0.
Now, then, what are some examples of home made ubicomp?
Last month I participated in the Mediamatic Social RFID Hackerscamp at PICNIC 08 in Amsterdam. In five days, about 30 people build 8 RFID installations to be used at the conference. We used a bunch of laptops, RFID readers, various electronic things, and construction materials. Nothing ridiculously expensive, nor something that takes months to create.
Let’s look at some of the installations we built.
Photo by Daria Perevezentsev. Used for the greater good of Mediamatic promotion.
First, a foundation. At PICNIC, you could get an RFID tag, which was then linked to your online PICNIC profile. Quite useful for the installations, who could figure out who you are by looking up the RFID tag. The RFID tag was the primary means of interaction with the installations, starting or enabling other actions.
iktag image from http://www.mediamatic.net/page/51173/en.
A battery powered, couch on wheels, providing free massages. Both armrests have an RFID reader, on which you put your RFID tag to receive a massage. Other people can place their tag on the armrest to recharge your massage credit. And, for even more social interaction, if you use the couch with somebody else, you’re automatically connected on the online PICNIC network.
What you need to build this? An old couch, car massage chairs, two RFID readers and a laptop. Perhaps a car battery and LED displays to show massage credit. Not very high tech, but pretty awesome!
A sprint race! Touch your tag to a reader hidden in the start structure, wait for the “start gun” to fire, and run to the finish. Again, touch your tag, and a photo is taken and your time is placed in the ranking.
ikRun ranking table.
And a finish photo. This is me “running” the impossible time of 15.1 seconds.
What do you need to build this? In essence you’ll need two RFID readers and two laptops. In this case, you also need one camera, and one or two displays at the finish, and a sound system both for the start signal and at the finish. Of course, you can come up with all kinds of interaction beyond simply using the RFID tag to start and finish.
I noticed there’s a segway in the building, anyone up for a Segway race?
Google popularity contest! RFID tags are used to find your profile name, then a Google search is performed. The person with the highest number of search results, goes highest.
Requirements: two small lifts (not exactly home made, but hey). Computer, two RFID readers, some mechanics and Arduino to control the lifts via computer.
The awesomenest installation was Vbird, but that’s only because I helped create it. Vbird is a bird that you throw to other people. Catch it, let it read your RFID tag, and throw it to somebody else. It says “Nice to meet you” when it reads your tag, and makes happy sounds when flying. Plus, it records its flight on video, and the video created after it read your tag is uploaded to your PICNIC profile.
Unfortunately the hardware kept breaking, so in total we only played with it for about 15 minutes. That said, those were 15 very cool minutes.
Requirements: large bird, Arduino with accelerometer and RFID reader, laptop for communicating with the bird and playing the sounds. Less easy to get: wireless camera and processing infrastructure.
This is a project from last year. An RFID reader is hidden underneath the tea cup, and when you place your tag in the cup, various information that can be found about you on Google is displayed around the cup. Great conversation starter!
Requirements: laptop, RFID reader, beamer.
A memory game written by yours truly. Finds names of Bluetooth devices in the room. Uses these names as if they were Flickr usernames, and finds the recent photos from these Flickr users. Then randomly assigns photos to two RFID tags. Your job is to find the two tags that have the same photo.
Requirements: Laptop, RFID reader.
Looking at these examples, what is the technology you need for home made ubicomp?
Basically, a laptop, one or two RFID readers, and perhaps some micro controllers to control other hardware. What hardware is available on the consumer market for playing with these technologies?
Photo by Lali Masriera. CC-BY-2.0.
Arduino provides actual hardware. If you took part in yesterdays Arduino workshop you’ll have seen it. I’ve also got some hardware right here. Arduino does RFID readers, bread boards, micro controllers, Bluetooth, and so on. Use Arduino if you want to program hardware and do soldering. Requires a larger up-front investment than, say, using a computer with the built-in Bluetooth, but you can do some pretty awesome things.
The Arduino hardware designs are open source, as is the software. Open hardware, open software, low prices. What’s not to like?
Photo by Oliver Keller. CC-BY-SA-2.0.
Tikitag is pretty new, launched just over two weeks ago. They provide an RFID reader and RFID tags, plus a website that you use to configure actions for tags. Right now they only provide a few actions, like opening a website, going to a special photo page, or your online business card. You can use Tikitags to control iTunes or make a Skype call. You should also be able to create your own actions, although the setup seems rather complicated.
The cool thing about Tikitags is that you can get a starter kit, with reader and a few tags, for € 35 (excluding tax). That’s pretty cheap! Also, by using the website, you can give an RFID tag (or a tagged object) to somebody else, who can then read the tag with her Tikitag reader to execute the action you configured.
And you don’t have to go through the Tikitag software. You can use the Tikitag reader directly on your computer to read RFID tags, so you can hook up your own actions. These won’t work on somebody else’s machine, however.
Photo by Mark Wubben. (Not on Flickr, yet)
Violet is the maker of Nabaztag, the rabbit you see here. It’s a rabbit that’s connected to the internet, and can therefore give you updates on the weather, the news and your e-mail. You can link it to another rabbit, so you can communicate with somebody else through the rabbit. It also has an RFID reader so you can trigger actions, much like Tikitag. Indeed, much like Tikitag, the rabbit is controlled via the Nabaztag website, making Nabaztag a closed system.
Next week Violet is coming out with Mir:ror, a RFID reader that is very similar to the Tikitag system. So, again, a closed system. Fun to play around with, less interesting to use for creating new stuff.
Photo by Régine Debatty. CC-BY-SA-2.0.
OpenSpime, also present here, is an open standard – in development – for connecting objects. Could be quite interesting if you want to hook up your home made ubicomp to other ubicomp.
Photo by David Orban. CC-BY-2.0.
It’s also a good idea to get an EEE PC running Linux. These are small, and not very expensive machines that you can hide in many places.
Photo by Benjamin Busche. CC-BY-SA-2.0.
An interesting magazine to read may be MAKE, which is about making cool stuff yourself.
Logo from http://makezine.com.
In terms of software, most hardware as Java libraries available. Therefore, programming in Java may be a good option. Python is also a good choice.
I’ve been working on my own framework, written in JavaScript, but running in Java. You can get it from http://code.google.com/p/physical-js/.
Photo by Windell Oskay. CC-BY-2.0.
Now, for the project I’ve been working on for SHiFT. In each room there’s one or more computers which look for Bluetooth devices. For example your phone or your laptop. All computers communicate with each other and with a main computer, which aggregates the data. Through this, we know which device is in which room, so we can derive the popularity of the sessions, and we can also know who’s where.
The data we collect is posted – live – to Jaiku and Twitter. If you go to the reception, you can link your actual, human name, to the Bluetooth device. That way, we can announce where you are.
Make sure to enable Bluetooth on your phone or laptop, and set it to be discoverable. That way, we can find and track you!
Unfortunately we didn’t manage to set this up.
Photo by Lali Masriera. CC-BY-2.0.
Obrigado!
Photo by Jeff Kubina. CC-BY-SA-2.0.
I’m in Lisbon currently, for the SHiFT conference. Working on a installation using Bluetooth to track people as they move throughout the conference, and doing a session on Home Made Ubicomp. More later.
Three weeks ago already I participated in the Mediamatic Social RFID Hackers Camp at Picnic 08 in Amsterdam. At Hackers Camp, in about five days time, an excellent group of designers, tinkerers, builders and hackers built eight Social RFID installations to be enjoyed by the Picnic’ers.
Together with Erik Borra, Eelco Wagenaar, Martijn Pannevis and Adriaan Wormgoor I built Vbird. Vbird is a flightless bird, equipped with a wireless camera and Arduino BT powered RFID reader and accelerometer. Since Vbird can’t fly, you have to throw it to each other to make it fly! It continuously records video, and if you let it scan your Picnic RFID tag, the next video will be uploaded to your profile. In all, pretty awesome. You can see some videos here: http://www.justlol.net/vbird/.
Unfortunately Vbird did not last very long. Every piece of hardware inside the bird that could fail, failed. It worked briefly at the end of Wednesday, the first Picnic conference day. It consistently broke down on Thursday, at the end of which day we finally gave up. No more Vbird.
I primarily worked on making Vbird interface with anyMeta, the community management system created by Mediamatic Lab and used to drive the Picnic website. This involved setting up the video processing infrastructure with Martijn and some help from Robin Gareus. The video processing ran on a MacBook Pro – converted to a Ubuntu machine – hooked up to a analogue to MPEG video converter. (We had it working on an EEE PC, and figured it’d be faster to install Ubuntu on the MacBook than figuring out how to do the video processing on OS X.) We used ffserver to set up a Flash video stream we could display live, and used ffmpeg to make video segments encoded in Flash video. This then was controlled using OSC messages from a second MacBook Pro, which did the main anyMeta interactions, handled Arduino communication, and drove the UI.
The second MacBook Pro did all this using Physical.js, which is an open source library, by yours truly, for doing physical computing in JavaScript. It runs inside Rhino, which is a JavaScript-interpreter written in Java. The big advantage of Rhino is that you can use the Java libraries, and still write lovely JavaScript.
Physical.js builds upon Dojo, which makes it easy to separate the code into modules, has a fantastic event system, and even a Twisted-like Deferred implementation. Now, Dojo hasn’t really focused on its Rhino support, but that’s something I hope to change going forward, by contributing code from Physical.js back to Dojo.
In any case, Dojo’s event system leads to some interesting “Action Oriented” code. For example, the code reading the output from the Arduino BT is encapsulated in a ArduinoReader class:
dojo.require('picnic.ArduinoReader');
reader = new picnic.ArduinoReader('/dev/tty.Arduino_bt121-Bluetooth-1');
Then, we simply hook up a few events:
reader.onOpenComplete = function() {
// …
};
reader.onOpenError = function(e) {
// …
};
reader.onAcceleration = function() {
// …
};
reader.onDeceleration = function() {
// …
};
reader.onTagEnter = function(evt) {
// …
};
(Admittedly, perhaps I should have used dojo.connect() instead of directly overwriting the event callbacks, but hey.)
From a programming perspective, it’s quite awesome that you can simplify the input stream to a few events, to which you can hook up other actions. Having such a framework available, and being able to clearly express the actions, helped a lot in creating Vbird.
And, when the onboard RFID reader died, it was easy to hook up a physically connected RFID reader:
dojo.require('picnic.OSCReader');
reader2 = new picnic.OSCReader(7007);
dojo.connect(reader2, 'onTagEnter', reader, 'onTagEnter');
Here picnic.OSCReader implements the ph.rfid.Reader interface, just like picnic.ArduinoReader. It receives OSC messages from the Tikitag reader we used, through the RFID-to-OSC gateway written by Mediamatic. (Ironically, we had no Java software available for the Tikitag reader.) It’s simply a matter of connecting the two onTagEnter handlers to use a second RFID input with the original code.
Another incredibly useful thing was automatically generating an API for anyMeta. A slightly older version of the code I used can be seen in the Flickr API implementation in Physical.js. It uses dojo.getObject() and the __noSuchMethod__ method to dynamically set up an API. In the Flickr API example, there’s an API declaration for people, which lets you use all people.* methods, without explicitly declaring them.
anyMeta uses OAuth to control access to API methods. The API implementation I wrote – and which has yet to be ported to Physical.js – automatically signs API calls before sending them to the server. This, then, lets us do:
dojo.require('picnic.anyMeta.anyMeta');
api = new picnic.anyMeta.anyMeta(OAUTH, ANYMETA_ENDPOINT);
profile = api.picnic.persons.get({rfid: 'urn:rfid:1AA037EF'});
Which gives us the profile corresponding to a specific RFID tag.
The API code takes care of serializing to and from JSON, as well, which made it incredibly easy to interact with anyMeta.
The UI Adriaan built for Vbird was a small Flash movie, served and updated straight from the Physical.js code. See, the Jetty web server is included in Physical.js, making it easy to serve-up static files, and register handlers for specific URLs:
dojo.require('jetty.Server');
server = new jetty.Server(8080, jettyResources);
server.register('/stream/latest.js', function(request, response) {
response.type = 'text/javascript';
response.body = dojo.toJson({
latest: 'Latest data here…'
});
});
server.start();
This then is a far more elegant solution than writing data to a file, accessed via a separate web server. Breathlyzer, created by Matt Cottam and Jasper Speicher of Tellart also used Physical.js for this purpose.
In all, using Physical.js at Picnic was great fun, and it’s definitely cool to use JavaScript for something completely different than web programming. Let me know what you think of Vbird and Physical.js!
BBC News:
Scientists have hailed a successful switch-on for an enormous experiment which will recreate the conditions a few moments after the Big Bang. They have fired a beam of particles called protons around the 27km-long tunnel which houses the the Large Hadron Collider (LHC).
The Large Hadron Collider has made its first test run.
As suggested by Johan Bouveng, the first real post here is about Method Chaining. This is the technique jQuery uses for its magic.
To take an example from the jQuery home page:
$("p.neat").addClass("ohmy").show("slow");
This takes all <p> elements with a class name of neat, adds the class ohmy and then slowly animates the appearance of the elements. Equivalent code without chaining could look like this:
var neatos = $("p.neat");
for (var i = 0; i < neatos.length; i++) {
addClass(neatos[i], "ohmy");
show(neatos[i], "slow");
}
neatos = null;
In this example a few advantages of chaining become clear:
- Clear, concise code: this makes it easier for fellow programmers to spot the important bits, such as adding a class name and showing the elements.
- No variables used: the actions on the paragraphs are invoked on the result set of the
p.neatselector - No worries about memory leaks, because there are no references to DOM elements
Disadvantages include more magical code, that quite possibly runs slower that non-chained code. For example, whereas the non-chained code uses one iteration over all paragraphs, the chained code iterates twice. Once for addClass() and once for show(). That said, this slight performance loss usually doesn’t hurt, and if it does, you can always remove the chains.
How does method chaining work? The general principle is that each function call returns an object on which you can call other functions. Many jQuery functions return the object on which they are called themselves:
var neatos = $("p.neat");
neatos === neatos.addClass("ohmy"); // true
Others, like filter(), return a different object, which supports the same methods.
Chaining Ourselves
Let’s play with some method chaining ourselves:
var chain = { // Create a new object
set: function(name, value) {
this[name] = value; // Do stuff here, in this case, set a property
return this; // Return a reference to the object itself.
},
get: function(name) {
return this[name]; // Return the value
}
};
This creates a chain object, which has a get() and a set() method. The set() method lets you set properties on the object, and returns the chain object. get() returns a value.
Now we can run the following:
chain.set("foo", "bar").get("foo"); // "bar"
chain.get("foo"); // "bar"
chain.set("baz", "thud").set("hello", "world").get("hello"); // "world"
chain.get("foo"); // "bar"
chain.get("baz"); // "thud"
chain.get("hello"); // "world"
We can’t run this:
chain.get("foo").get("baz"); // chain.get("foo").get is not a function
chain.get("foo") returns the value, which is not the chain object, and does not have the get() method.
Chaining with Class
Here we have only one chain object. Let’s create a class, so we can create several chainable objects:
function Chain() {};
Chain.prototype.set = function(name, value) {
this[name] = value;
return this;
};
Chain.prototype.get = function(name) {
return this[name];
};
Now we can do this:
var chain = new Chain();
chain.set("foo", "bar").get("foo"); // "bar"
Let’s add a filter() method, which creates a new Chain object:
Chain.prototype.filter = function() {
var result = new Chain();
for (var i = 0; i < arguments.length; i++) {
result.set(arguments[i], this.get(arguments[i]));
}
return result;
};
For example:
var chain = new Chain();
var filtered = chain.set("foo", "bar").set("baz", "thud").set("hello", "world").filter("foo", "baz");
filtered.get("foo"); // "bar"
filtered.get("baz"); // "thud"
filtered.get("hello"); // undefined
Conclusion
This concludes Part One of Method Chaining. We’ve seen why method chaining is so useful, and how it works. In Part Two, we’ll look at dojo.Deferred, which uses Method Chaining in order to, well, chain methods!
Hello, welcome to the Supercollider blog. We build web applications. We blog about their development here.
Currently, we is me, as in Mark Wubben. You may know me for building sIFR. I also did some fun stuff for Xopus. Rather than spilling my JavaScript beans over at my personal site, I’ll be doing that here. Starting of with Method Chaining.






































