There are more details up on the Chrome wiki for how to build a Chrome extension thanks to illustrious Aaron Boodman.
You create a JSON manifest in your extension directory, tell Chrome about it via –enable-extensions –load-extension="c:myextension" (only required while extensions are in dev mode) and then you can navigate to chrome-extension://00123456789ABCDEF0123456789ABCDEF0123456/hello_world.html assuming the manifest of:
PLAIN TEXT
JAVASCRIPT:
1. |
2. { |
3. "format_version": 1, |
4. "id": "00123456789ABCDEF0123456789ABCDEF0123456", |
5. "version": "1.0", |
6. "name": "My First Extension", |
7. "description": "The first extension that I made." |
8. } |
Aaron’s work wouldn’t be complete with some notion of userscripts, and the document discusses that:
PLAIN TEXT
JAVASCRIPT:
1. 2. { 3. "format_version": 1, 4. "id": "00123456789ABCDEF0123456789ABCDEF0123456", 5. "version": "1.0", 6. "name": "My First Extension", 7. "description": "The first extension that I made.", 8. "content_scripts": [ 9. { 10. "matches": ["http://www.google.com/"], 11. "js": ["foo.js"] 12. } 13. ] 14. } 15. |
Finally, NPAPI plugins are supported for the binary side of the house, and you just need to point to the location of that code via "plugins_dir": "plugins".
There are also more resources:
* API Pattern
* Manifest details
* Todo list example
* Userscripts
Not your mothers JavaScript
The Chrome team has also launched a new website to showcase interesting web app examples and samples.
Calling it openwebexperiments or something, and being a bit more inclusive would have been nice (since these all seem to work fine in Safari, Firefox, etc ….. but the idea is good!
Yvo Schaap has created a reasonably interesting real-time front-end to Reddit data over at erqqvg.com. It’s actually a really cool visualization of how Reddit’s stories change over time, with “yellow-fade” indications when new comments and votes and registered. Super-nice.
(The screenshot doesn’t do it justice; go check it out.)
But that’s only half the story. They’ve got a much-better-named service called “Vizeddit” that displays the same data with much richer graphics and animations:
Once again, you really need to go see it. The numbers along the bottom represent stories, and they grow and swap places over time, new ones are inserted, and so forth. You see the votes drop down in real-time, and new comments float in as well.
Over at the Flickr development blog, Ross Harmes , one of those lesser sung JavaScript heroes explains in detail how Flickr creates really fast client side searches and one of the implementations of these findings is the newly released find people faster feature:
The main findings of the team were that eval()
is not only evil but also very slow whereas dynamic script nodes are fast but insecure. The solution was to do a custom evaluation of string data rather than using JSON:
Having set the performance bar pretty high with the last approach, we dove into custom data formats. The challenge would be to create a format that we could parse ourselves, using JavaScript’s String and RegExp methods, that would also match the speed of JSON executed natively. This would allow us to use Ajax again, but keep the data restricted to our domain.
Since we had already discovered that some methods of string manipulation didn’t perform well on large strings, we restricted ourselves to a method that we knew to be fast: split(). We used control characters to delimit each contact, and a different control character to delimit the fields within each contact. This allowed us to parse the string into contact objects with one split, then loop through that array and split again on each string.
PLAIN TEXT
JAVASCRIPT:
-
that.contacts = o.responseText.split("\c");
-
for (var n = 0, len = that.contacts.length, contactSplit; n <len; n++) {
-
contactSplit = that.contacts[n].split("\a");
-
that.contacts[n] = {};
-
that.contacts[n].n = contactSplit[0];
-
that.contacts[n].e = contactSplit[1];
-
that.contacts[n].u = contactSplit[2];
-
that.contacts[n].r = contactSplit[3];
-
that.contacts[n].s = contactSplit[4];
-
that.contacts[n].f = contactSplit[5];
-
that.contacts[n].a = contactSplit[6];
-
that.contacts[n].d = contactSplit[7];
-
that.contacts[n].y = contactSplit[8];
-
}
Once this had been speeded up, all they needed to use was the YUI AutoComplete control and voilà – fast client side searches even with massive datasets.
David Mandelin has announced“a visualization of TraceMonkey performance, with the goal of revealing what the JS VM is doing, and why it runs certain programs fast or slow, so we can figure out how to make the slow ones fast too.”
David starts off explaining what TraceMonkey is about, and pieces together the activities:
- When TM starts running a program, it always starts by interpreting the program, exactly as in the non-tracing JS engine.
- When execution reaches a point where TM might want to start a compiled trace, TM spends a bit of time monitoring the execution: checking to see if it already has a compiled region, counting the number of times passed, and deciding whether to start a trace. Monitoring is a kind of overhead: while monitoring, TM isn’t running the user’s program, but monitoring is a necessary cost of finding and optimizing traces.
- If TM does decide to create a new compiled trace, it runs in the interpreter while recording the trace, including operations and types of values. During this time, it is running user code a little slower than the basic interpreter.
- When the trace is finished, TM compiles the trace to native code. This is another form of overhead.
- As I mentioned above, as part of monitoring, TM checks to see if it already has a compiled native trace starting at the current point. If so, TM selects the right trace and prepares to run it, which I call executing the trace. This is a third form of overhead.
- Finally, TM can be running native code compiled previously. Compiled native traces run 2-20x faster than the interpreter, with a typical speedup factor of about 2.5.
With these new eyes, David walks through various benchmarks to see how they are effected. Now that it is easier to see what is going on, the team should be able to optimize even faster.
Sometimes you find leftovers of old technology in browsers that blow your mind. One of these “ghost in the machine” problems exists in Firefox: if you use window.sun
or function sun()
in JavaScript you effectively start the Java VM.
There are a few “magic” properties on Mozilla’s DOMWindow interface for supporting LiveConnect that will initialize the Java plugin and all the baggage that comes with it (which, with modern Java plugins, means launching java.exe as a subprocess). Looking up these properties on the window object is all it takes.
There are a few more of these still in the Mozilla source code and they are part of the old Netscape LiveConnect engine. They are:
- java
- Packages
- netscape
- sun
- JavaClass
- JavaArray
- JavaMember
Avoid these at all cost lest you want the performance of your JavaScript to be like a Java Applet.
I saw two posts at the same time on the topic of multiple-file uploading from a Web app which is a topic that we have covered many times before.
This time we have our good friend Scott Schiller posting on the Flickr uploader. He details the user experience from file selection, to progress, to completion, and then delves into the technical details including the Flash 10 changes:
Due to a change in the security model beginning with Flash 10, file selection must now begin via the user clicking directly on the Flash movie. With previous versions, you could call [Flash movie].selectFiles() from JavaScript and the selection dialog would be shown without requiring user action.
To keep the user experience consistent on Flickr where an HTML link could trigger the selection dialog, we made the Flash movie transparent and overlaid it on top of the HTML link. Thus, the Flash movie captures the click and the selection dialog works as expected. One might call this a legitimate, local form of clickjacking.
If repositioning the Flash movie is undesirable in your use case, another option is to render the link, text or button UI within the Flash movie itself and show the movie as a normal inline element.
Then, Gmail finally launched multifile uploading and people will rejoice.
It, as most of these things do, uses Flash:
This is the pragmatic choice, even though Gears has nice support. Time for browsers to step up!
Let’s lead with code:
PLAIN TEXT
JAVASCRIPT:
-
Namespace(‘foo.bar’);
-
foo.bar.myFunction = function() {};
-
Namespace(‘com.example’, {
-
MyClass: function() { return {}; }
-
});
-
var obj = new com.example.MyClass();
-
Namespace.use(‘com.example.MyClass’);
-
var obj2 = new MyClass();
-
// include com/example/RemoteClass.js
-
Namespace.include(‘com.example.RemoteClass’);
-
var obj3 = new com.example.RemoteClass();
-
Namespace.registerNativeExtensions();
-
‘com.foo.bar’.namespace();
Reading the code above is probably all you need to know about the new, library independant, JavaScript library Namespace.js, created by Maxime Bouroumeau-Fuseau.
The goals for the library are:
- Simple API
- Framework independent
- Remote file loading (synchronously or async)
- Tested against Firefox 3.x, Safari 3.x, IE 6/7 and Opera 9.5
- Highly configurable
- Events
- Optionally add methods to native objects
You can see more in the How To.
A little over two months after their initial launch of Titanium, Appcelerator today followed with the “PR2? release of their open-source web-as-desktop-app run-time platform (i.e., an open-source competitor to Adobe AIR).
This release adds support for Linux to their OS X and Windows versions and also provides a GUI for creating stand-alone Titanium apps (the previous version relied on command-line utilities). This application is a Titanium app itself and includes some innovative features, including a view of the Titanium group’s Twitter / FriendFeed streams and a direct connection to their IRC channel.
Appcelerator is also trying to make it as easy as possible hack away on the Titanium platform without requiring the use of C++; they’ve added a new module API that lets you use JavaScript, Ruby or Python in addition to Bjarne Stroustrup’s spawn.
On a lower level, and of more probable interest to our community, the JavaScript APIs have been greatly extended. Let’s consider the File API in the first release of Titanium, which consisted of one documented method (”read”) and one undocumented method (”write”). In the PR2 release, it looks quite a bit richer:
copy ( to ) : boolean
Copies a file to another location.
createTimestamp ( ) : number
Returns a timestamp of the file’s creation.
createDirectory ( recursive ) : boolean
Creates a directory.
deleteDirectory ( recursive ) : boolean
Deletes an existing directory.
deleteFile ( ) : boolean
Deletes a file.
exists ( ) : boolean
Checks whether or not a file exists on the user’s system.
extension ( ) : string
Returns the file’s extension.
getDirectoryListing ( ) : array
Returns an array of files inside a directory.
isDirectory ( ) : boolean
Checks whether the file object is a directory.
isFile ( ) : boolean
Checks whether the file object is a file.
isHidden ( ) : boolean
Checks whether the file object is hidden.
isSymbolicLink ( ) : boolean
Checks whether the file object is a symbolic link.
modificationTimestamp ( ) : string
Returns a timestamp of the file’s last modification.
move ( to ) : boolean
Moves a file to another location.
name ( ) : string
Returns the name of the file.
nativePath ( ) : string
Returns the full path of the file.
parent ( ) : File
Returns the parent directory where the file resides.
read ( ) : string
Reads the content of the file.
readLine ( reset ) : string
Reads a particular line in the file’s content.
resolve ( path ) : boolean
Changes the file or directory referenced by a File object.
size ( ) : number
Returns the size of the file.
spaceAvailable ( ) : number
Returns to space available on a user’s system.
toString ( ) : string
Returns the file’s properties as a string.
write ( data [, append] ) : boolean
Outputs data into a file.
Check out the full API docs to get a feel for the rest of the APIs; but being an open-source project, Titanium’s newest APIs are still in the source only.
In terms of the run-time itself, they’ve updated their WebKit renderer to be very close to the latest and greatest and it includes all of the new HTML 5 goodies that Safari 4 has.
Nolan Wright, Appcelerator CTO, has created some screencasts to show off some of the new features; here’s one of them:
The Dijit UI library brings a ton of visual capabilities to the table and I think most people look to it for the power and simplicity of rendering well made user interface components such as grids, modals and calendars. Another aspect that people may overlook is it’s excellent form handling capabilities and in this tutorial, Mike Wilcox walks you through the steps of enhancing the appearance of Dijit form elements:
In this post, I’ll show you how to set up your form with the proper style sheets, and do some minimalist CSS targeting to adjust each form so they’ll all be the proper size. The result will be a style sheet base that you can use and modify to create custom Dijit forms.
The tutorial is squarely aimed at users of the popular Dojo framework and it’s companion UI library, Dijit and will show the flexibility and power of the theming capabilities of the frameworks. The tutorial focuses on creating a form that is styled to look like this using the built-in theming capabilities of Dijit:
While their are many methods of doing this via CSS or other styling frameworks, the advantage for Dojo users is that the capabilities are baked straight into the framework and helps to eliminate some of the overhead of including other frameworks or services as well as learning another framework.
JSONView is a new Firefox extension that gives you a nice way to view your JSON documents (JSONovich also does the trick).
Ben Hollis talks about the extension:
The extension itself is pretty simple. I wasn’t sure how to approach the problem of supporting a new content type for Firefox, so I followed the example of the wmlbrowser extension and implemented a custom nsIStreamConverter. What this means is that I created a new component that tells Firefox “I know how to translate documents of type application/json into HTML”. And that it does – parsing the JSON using the new native JSON support in Firefox 3 (for speed and security) and then constructing an HTML document that it passes along the chain. This seems to work pretty well, though there are some problems – some parts of Firefox forget the original type of the document and treat it as HTML, so “View Page Info” reports “text/html” instead of “application/json”, “Save as…” saves the generated HTML, Firebug sees the generated HTML, etc. Just recently I came across the nsIURLContentListener interface, which might offer a better way of implementing JSONView, but I’m honestly not sure – the Mozilla documentation is pretty sparse and it was hard enough to get as far as I did. I’m hoping some Mozilla gurus can give me some pointers now that it’s out in the open.