Blog
June 25th, 2008
Kind of last moment but I just got word that PPK (the creator of the excellent Quirksmode.org) is in Boston and looking to meet up with local developers. If you're interested we'll be at The Pour House at about 7pm (today, June 25th) and you're welcome! If you're coming please reply to this email or give me a call so that I can spot you.
Tags: boston, javascript, meetup
6 Comments on 'Meet PPK (Creator of Quirksmode.org)'
June 24th, 2008
A quick bookmarklet that I made for Asa Dotzler. If you've ever visited a tweet, on Twitter, directly, and had wished to immediately reply to its author you probably found it to be quite convoluted (typically this is the case if you subscribe to services like Summize or Tweetscan. It usually involves copying the username, visiting the reply screen, and then typing/pasting in the relevant parts to make the @reply. Instead you can just use the following bookmarklet to make that easy.
javascript:window.location=window.location.href.replace(/(com.)([^.\/]+).*/,"$1home?status=@$2+");
First, Drag this to your bookmark bar: Twitter Reply
Second, visit a tweet: http://twitter.com/jeresig/statuses/841204003
Then hit the bookmarklet and you should be taken to the reply screen with "@jeresig " (or whatever the appropriate username is) already pre-filled in. Enjoy!
P.S. As a bonus it maintains the http/https URL protocol, as well.
Tags: twitter, javascript
6 Comments on 'Twitter Quick Reply'
June 23rd, 2008
It was fascinating to watch the unveiling of Firefox 3 last week. I'm pleased that, in some small way, my contributions helped to bring this browser out the door.
First 24 hours: 8.3 million downloads, 69 downloads/second, 20 Gb/s Peak Transfer
While I generally focus on issues tangential to JavaScript code, at Mozilla - like testing, performance analysis, specifications, standards, bug hunting, speaking, demos, and blogging - some of my code is live within the browser, and that makes me quite happy.
One of my first tasks at Mozilla was to, with Mark Finkle, develop a JavaScript API for performing common interactions typically desired by extension developers, called: FUEL. This is a pure-JavaScript implementation that sits as a proxy inbetween the developer and the various, traditional, XPCOM-style ways of performing actions.
If you're interested in learning more about FUEL I've collected a number of links and examples:
The Development of FUEL
FUEL was created over the course of a couple months, in early 2007, by Mark Finkle and I. Mark had much-better knowledge of Mozilla's APIs and I had good knowledge of JavaScript and API design - the match worked out nicely. I've written a couple blog posts on FUEL and so has Mark.
You can also see the features and code that went into FUEL 0.1 and FUEL 0.2 in Bugzilla.
FUEL, Today
Today FUEL lives in Firefox 3 (meaning that you can use it to develop Firefox extensions) and is part of the core Mozilla platform (meaning that portions of the API will be available in any Mozilla-based application that is built). For example you can even use a FUEL-like API in Thunderbird (called 'STEEL'). Here are some of the best resources for getting started with FUEL in Firefox 3:
Here are some of my favorite example of FUEL in action. It was very important to me that the most-common actions take no more than a single line of code to perform - with even complex actions keeping nice and trim.
Open, and activate, a new tab pointing to Google.com
Application.browser.open("http://google.com/").active = true;
Close the active browser tab
Application.browser.activeTab.close();
Close all tabs that mention Google
Application.browser.tabs.forEach(function(tab){
if ( tab.url.match(/google/) )
tab.remove();
});
Add a new bookmark pointing to Mozilla
Application.bookmarks.add("Mozilla", "http://mozilla.org/");
Remove all bookmarks pointing to Google.com
Application.bookmarks.all.forEach(function(cur){
if ( cur.url.match(/google.com/) )
cur.remove();
});
FUEL, Future
Development is still going strong on FUEL. There's a Google Summer of Code student working on extending the API and porting it to more parts of the platform (along with backwards support for Firefox 2!). We'll probably end up seeing this in Firefox 3.1 (the next version of Firefox, due out later this year).
If you have any questions concerning how to use FUEL, or to develop Firefox extensions in general, your best bet would probably be to join the #extdev IRC channel on irc.mozilla.org. Lots of knowledgeable people hang out there and will be more-than-capable of answering any questions that you might have.
Once again, I'm terribly excited by the final release of Firefox 3 - here's hoping to many more excellent releases to come!
Tags: extensions, firefox, mozilla, javascript
12 Comments on 'Simple Extensions in Firefox 3'
June 16th, 2008
This evening I was playing around with the idea of profiling jQuery applications - trying to find a convenient way to completely analyze all the code that is being executed in your application.
I've come up with a plugin that you can inject into a jQuery site that you own and see how the performance breaks down method-by-method.
Here's how you can try this plugin on your own site:
Step 1: Copy site HTML, add base href, add plugin.
For example, Github.com uses jQuery for a few basic effects and pieces of interaction (they use considerably more on pages beyond the homepage).
I took a copy of their page, added a <base href> to the top and injected the profiling plugin giving a resulting test page.
Before:
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
...
<script src="/javascripts/bundle.js"></script>
...
</head>
After:
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<base href="http://github.com/"/>
...
<script src="/javascripts/bundle.js"></script>
<script src="http://dev.jquery.com/~john/plugins/profile/jquery-profile.js"></script>
...
</head>
Step 2: Use the site normally.
Use the site as you normally would. Load it up, click around - perform normal interactions. In the case of the Github.com page I let it load, scrolled down, and clicked on one of the demo images - which caused an overlay to appear. I then closed the X on the overlay and let it hide.
Step 3: View data.
In your console type jQuery.displayProfile(); and scroll down to the bottom of the page. You should see something like the following:
and here's a sample data dump:
Event: ready (165ms)
| % |
(ms) |
Method |
in |
out |
| 0.0% |
0 |
jQuery(#document) |
|
1 |
| 0.0% |
0 |
.bind("ready", function()) |
1 |
1 |
| 3.6% |
6 |
jQuery("a[hotkey]") |
|
|
| 0.0% |
0 |
.each(function()) |
|
|
| 0.0% |
0 |
jQuery(#document) |
|
1 |
| 0.0% |
0 |
.bind("keydown.hotkey", function()) |
1 |
1 |
| 0.0% |
0 |
jQuery("#triangle") |
|
|
| 0.0% |
0 |
jQuery("body") |
|
1 |
| 1.2% |
2 |
.append("<div id="triangle" style="position: absolute; display: none;"> </div>") |
1 |
1 |
| 0.6% |
1 |
jQuery("#repo_menu .active") |
|
|
| 3.6% |
6 |
jQuery(".jshide") |
|
|
| 0.0% |
0 |
.hide() |
|
|
| 1.2% |
2 |
jQuery(".toggle_link") |
|
|
| 0.0% |
0 |
.click(function()) |
|
|
| 0.6% |
1 |
jQuery("#beta :text") |
|
|
| 0.0% |
0 |
.focus(function()) |
|
|
| 0.6% |
1 |
jQuery("#beta form") |
|
|
| 0.0% |
0 |
.ajaxForm(function()) |
|
|
| 1.2% |
2 |
jQuery(".hide_alert") |
|
|
| 0.0% |
0 |
.click(function()) |
|
|
| 0.0% |
0 |
jQuery("#login_field") |
|
|
| 0.0% |
0 |
.focus() |
|
|
| 0.0% |
0 |
jQuery("#versions_select") |
|
|
| 0.0% |
0 |
.change(function()) |
|
|
| 1.2% |
2 |
jQuery("a[rel*=facebox]") |
|
3 |
| 17.6% |
29 |
.facebox() |
3 |
3 |
Event: load (1ms)
Event: click (29ms)
| % |
(ms) |
Method |
in |
out |
| 6.9% |
2 |
jQuery("#facebox .loading") |
|
|
| 3.4% |
1 |
jQuery("facebox_overlay") |
|
|
| 3.4% |
1 |
jQuery("body") |
|
1 |
| 6.9% |
2 |
.append("<div id="facebox_overlay" class="facebox_hide"></div>") |
1 |
1 |
| 0.0% |
0 |
jQuery("#facebox_overlay") |
|
1 |
| 6.9% |
2 |
.hide() |
1 |
1 |
| 3.4% |
1 |
.addClass("facebox_overlayBG") |
1 |
1 |
| 0.0% |
0 |
.css("opacity", 0) |
1 |
1 |
| 3.4% |
1 |
.click(function()) |
1 |
1 |
| 6.9% |
2 |
.fadeIn(200) |
1 |
1 |
| 3.4% |
1 |
jQuery("#facebox .content") |
|
1 |
| 3.4% |
1 |
.empty() |
1 |
1 |
| 3.4% |
1 |
jQuery("#facebox .body") |
|
1 |
| 0.0% |
0 |
.children() |
1 |
2 |
| 10.3% |
3 |
.hide() |
2 |
2 |
| 0.0% |
0 |
.end() |
2 |
1 |
| 6.9% |
2 |
.append("<div class="loading"><img src="/facebox/loading.gif"/></div>") |
1 |
1 |
| 0.0% |
0 |
jQuery("#facebox") |
|
1 |
| 0.0% |
0 |
jQuery({...}) |
|
1 |
| 3.4% |
1 |
.width() |
1 |
|
| 0.0% |
0 |
.css({...}) |
1 |
1 |
| 6.9% |
2 |
.show() |
1 |
1 |
| 0.0% |
0 |
jQuery(#document) |
|
1 |
| 0.0% |
0 |
.bind("keydown.facebox", function()) |
1 |
1 |
| 0.0% |
0 |
jQuery(#document) |
|
1 |
| 3.4% |
1 |
.trigger("loading.facebox") |
1 |
1 |
Event: beforeReveal.facebox (1ms)
Event: click (6ms)
| % |
(ms) |
Method |
in |
out |
| 16.7% |
1 |
jQuery(#document) |
|
1 |
| 66.7% |
4 |
.trigger("close.facebox") |
1 |
1 |
Event: close.facebox (3ms)
This quick table of data should be able to provide you with some interesting information about what's happening in your code. The result is still incredibly basic (really only providing the most basic level of jQuery method introspection) but it definitely shows some merit.
If you wish to create a different view for the data you can access the raw data structure by running jQuery.getProfile();.
The next stage of development for this plugin would be to reveal which methods are running inside other jQuery methods - in addition to monitoring other aspects of the application (such as timers, Ajax callbacks, etc.). I'm pleased with even this most-basic result - it gives me the ability to quickly, and easily, learn much more about a jQuery-using application.
Tags: jquery, javascript, performance
29 Comments on 'Deep Profiling jQuery Apps'
June 15th, 2008
One thing that I absolutely adore is the sheer embeddability of JavaScript. It's a (comparatively) simple language that is fiercely flexible. I tend to liken JavaScript to water - alone it's painfully simple but it can take the form of its container - and mixing it with anything enhances its flavor.
Since JavaScript, alone, is so dumb (we've become spoiled by browsers which provide DOM, setTimeout/setInterval, and even a global object reference - none of which are necessarily required my an ECMAScript implementation) we must rely upon the spice of 'larger' languages to help it gain some taste.
We can start by taking a look at some of the most popular languages that are available today: Python, Perl, PHP, Ruby, and Java -- all of which have, at least, one embeddable JavaScript interpreter.
One thing is the same in all the interpreter implementations, as well, they all have the ability to introduce (at least) simple objects into interpreter (from the parent language) and extract values again. Sometimes this may be as simple as executing a JavaScript function and getting its return value (which is often translated from its internal JavaScript form back into the native language).
There's a couple points upon which I like to evaluate the embeddability of a JavaScript interpreter, specifically:
- Object Translation: If objects/values are passed to/from the interpreter to/from the native language - is that translation handled automatically?
- Simplicity: How hard is it to get up-and-running? (Is extra compilation required or is it written using native language code?)
- Bleed-through: Can JavaScript communicate to the base language or is it a one-way-street?
The first point is the easiest one to find compatibility with - virtually all embeddable JavaScript interpreters do some form of object translation. Some do it better (like JE and Rhino) but it generally shouldn't be a problem for simple scripts.
PHP
» PHPJS
A flexible, pure-PHP, JavaScript interpreter that even accepts compiling to an intermediary bytecode. There is no bleed-through but good object translation.
include "js.php";
# Introduce a new JavaScript function, named print,
# which calls a PHP function
function show($msg) {
echo "$msg\n";
}
$jsi_vars["print"] = "show";
# Add in a new pure-JavaScript function which calls
# our previously-introduced print function
jsc::compile("function alert(msg){ print('Alert:' + msg); }");
# Prints out 'Alert: text'
js_exec("alert('text');");
» J2P5: Pure-PHP ECMAScript Engine
Probably the simplest of the available interpreters - there doesn't appear to be a clear way of communicating from JavaScript-to-PHP (or vice versa). Although, it is implemented in pure-PHP which allows for some nice cross-platform compatibility.
include "js/js.php";
$script = <<<EOD
print("Hello from JavaScript");
EOD;
js::run($script);
Perl
» JavaScript::SpiderMonkey
An embedding of Mozilla's Spidermonkey JavaScript engine into Perl. Since it uses Spidermonkey it'll require that extra source code and compilation. Object translation is good but there's no bleed-through (JavaScript calling native Perl functionality that isn't explicitly defined).
use JavaScript::SpiderMonkey;
# Instantiate the interpreter
my $j = JavaScript::SpiderMonkey->new();
# Introduce a new JavaScript function, named print,
# which calls a Perl function
$j->function_set("print", sub { print @_, "\n" } );
# Add in a new pure-JavaScript function which calls
# our previously-introduced print function
$j->eval("function alert(msg){ print('Alert:' + msg); }");
# Prints out 'Alert: text'
$j->eval("alert('text');");
» JE: Pure-Perl ECMAScript Engine
A pure-Perl JavaScript engine - shows incredible promise (probably my favorite new engine in addition to Rhino). Has tremendous potential (including the ability to serialize the runtime environment!).
use JE;
# Instantiate the interpreter
my $j = new JE;
# Introduce a new JavaScript function, named print,
# which calls a Perl function
$j->new_function(print => sub { print @_, "\n" } );
# Add in a new pure-JavaScript function which calls
# our previously-introduced print function
$j->eval("function alert(msg){ print('Alert:' + msg); }");
# Prints out 'Alert: text'
$j->method(alert => "text");
# So does this
$j->eval("alert('text');");
# Introduce the ability to do remote requests
use Net::FTP;
$j->bind_class( package => "Net::FTP", name => "FTP" );
# Execute native Perl functionality (FTP module)
# directly from JavaScript
$j->eval(<<'--end--');
var connect = new FTP("ftp.mozilla.org");
connect.get("index.html");
--end--
Note the extreme bleed-through that you can achieve with JE (in addition to excellent object translation).
Java
» Rhino
Probably one of the most famous embeddable JavaScript implementations. Implemented in pure Java has excellent object translation and perfect bleed-through. The bleeding can even be controlled explicitly at runtime (to create a more confined environment).
In the following code (using in some of the jQuery build system) two functions are defined which utilize a number of native Java packages - all without ever writing a single line of Java code.
importPackage
(java.
io);
function writeFile( file, stream ) {
var buffer = new PrintWriter( new FileWriter( file ) );
buffer.print( stream );
buffer.close();
}
function read( file ) {
var f = new File(file);
var reader = new BufferedReader(new FileReader(f));
var line = null;
var buffer = new java.lang.StringBuffer(f.length());
while( (line = reader.readLine()) != null) {
buffer.append(line);
buffer.append("\n");
}
return buffer.toString();
}
Python
» Python-Spidermonkey
Previously this was one of the most depressing embedding efforts (and, really, the only one available for Python) but it has since had some new life blown into it - which is much appreciated. It supports decent object translation and bleed-through (including the ability to call native classes, much like in JE).
from spidermonkey
import Runtime
j = RunTime().new_context()
# Introduce a new JavaScript function, named print,
# which calls a Python function
j.bind_callable("print", lambda msg: print(msg));
# Add in a new pure-JavaScript function which calls
# our previously-introduced print function
j.eval_script("function alert(msg){ print('Alert:' + msg); }");
# Prints out 'Alert: text'
j.eval_script("alert('text');");
Ruby
While there was a previous effort to embed Spidermonkey in Ruby it is largely defunct now, superseded by the new (strangely named) Johnson project.
» Johnson
This is a, relatively, new project that's working to completely overhaul how communication is currently done in-between Ruby and JavaScript (using Spidermonkey to power the engine). There is complete bleed-through: Ruby can dig in and manipulate JavaScript objects at run-time and JavaScript can call back and access native Ruby functionality. Additionally they're examining the ability to provide native browser environments using the env.js script that I created last year. While the cross-platform ease-of-use isn't there yet the project absolutely has a ton of potential.
require
"johnson"
j = Johnson::Runtime.new
# Introduce a new JavaScript function, named print,
# which calls a Ruby function
j.print = lambda {|msg| puts msg};
# Add in a new pure-JavaScript function which calls
# our previously-introduced print function
j.evaluate("function alert(msg){ print('Alert:' + msg); }");
# Prints out 'Alert: text'
j.evaluate("alert('text');");
Update: Another example of Johnson in action from John Barnette:
require
"johnson"
class Monkey
def eat
puts "Nom, nom, nom, bananas!"
end
end
j = Johnson::Runtime.new
# toss a monkey into the runtime
m = Monkey.new
j[:m] = m
# add a JSland function to our monkey...
j.evaluate("m.chow = function() { this.eat() }")
# ...and now it's available as an instance method on our native Ruby object!
m.chow
There's a ton of potential in all of these projects - providing interesting features for blurring the lines in-between JavaScript and different host languages. For your next project it should be pretty easy to find a solution to embedding JavaScript as your quick-and-dirty scripting language of choice.
Tags: ruby, java, python, php, perl, javascript
14 Comments on 'Spicing Up Embedded JavaScript'
June 11th, 2008
The always-excellent Aza Raskin had a little bit of fun recently - inspired by my recent Processing.js work - to port the popular Context Free Art language to JavaScript, using Canvas.
Renamed Algorithm Ink the result is a complete way to programmatically generate elegant pieces of artwork. Aza took the result a step further and built an in-browser IDE, gallery, and real-time result viewing. It appears to work best in Firefox 3, from my initial testing.
The result of one piece might look like this:
But that's the beauty since you'll likely never get the same piece of art twice. All works are seeded with a bit of randomness in order to create unique works. For example here is the CFA code that generated the above image:
startshape scale
rule scale{
SPIKES{ s .03 }
}
rule SPIKES {
SPIKE {}
SPIKE { r 90 }
SPIKE { r 180 }
SPIKE { r 270 }
}
rule SPIKE {
LSPIKE {}
}
rule SPIKE {
LSPIKE { flip 90 }
}
rule LSPIKE {
SQUARE {}
LSPIKE { y 0.98 s 0.99 r 1}
}
rule LSPIKE 0.005 {
SPIKE { r 90 }
SPIKE { r -90 }
LSPIKE { y 0.98 s 0.99 r 1}
}
rule MOUSECLICK{
SPIKES{ s .025 }
}
The code is quite simple - just a set of rules that are initiated and seeded based upon a few parameters. More information can be found in the Context Free Art documentation.
Of course the entire Context Free port is open source: contextfree.js. Looking through the source you'll note that the result is much more math-heavy than Processing performing frequent matrix-based transformations to the display. The result, however, is that pieces written in CFA (as shown above) involve much less, obvious, mathematical calls and is a much-purer result.
I think this particular port shows a ton of promise: It shows that it's possible to create elegant works using JavaScript while doing it in a completely standards-based way. I'm excited to see people start to play around with this - I think it shows a lot of promise.
Tags: visualization, javascript
7 Comments on 'Algorithmic Ink in JavaScript'
June 10th, 2008
I've been chatting with the Free Software Foundation and they've posed a tricky question: What is trivial JavaScript? - or - What is not trivial JavaScript?
It seems like an especially hard question to answer - especially without using subjective terms.
For example I would say that the following are all trivial:
- Use of inline JavaScript/DOM 0-style code (ex. onclick="...").
- Use of unobtrusive scripting to layer on basic page behaviors (ex. Twitter).
Whereas the following are sufficiently complex as to be deemed not trivial:
- Applications that do Ajax requests to a server-side component (ex. GMail).
- Applications where the majority of the initial download is executable code (ex. 280 Slides).
- Applications that are unable to function without the use of JavaScript (ex. Google Maps).
But this brings up the question: What about poorly-designed pages that have a small amount of JavaScript but are unable to function without the use of JavaScript? I'd still deem it trivial.
And what about sites that are somewhere in-between? For example Netflix has a significant amount of unobtrusive JavaScript on their site but I would hardly consider it to be trivial (pop-ups, Ajax-loading, all sorts of unobtrusive interaction).
Is there a tangible line that is crossed on the road to complex JavaScript development? Is it an externality like storing script in a separate file (ex. <script src='...'></script>)? or is it inside the script itself like in using Function prototypes or closures? It feels like the measure should be put upon an external source (as to not make restrictions upon what someone could, or couldn't, write using the language) but what would the proper external measurement be?
Thoughts?
Tags: javascript
25 Comments on 'Trivial JavaScript'
June 10th, 2008
A very cool new utility has just been released by Olav Junker Kjær called Mascara which is an ECMAScript 4 to JavaScript translator (written in Python).
Using this utility you can begin writing ECMAScript 4 code today, receiving its full benefits (such as IDE integration and compile-time type-checking) while still being able to run the resulting code in all modern browsers.
A simple demonstration is up on the Mascara web site which provides a view into the translated source code, along with run-time (and inline) error messages.
A full break-down of the features currently supported are:
- Type verification
- Classes and inheritance, constructors, super initializers
- Static members
- Type inference from initialization
- Parameterized types, Map and Vector
- Union types
- Structural types
- Getters/setters
- Namespaces
- Nullable types
Definitely be aware, however, that while the above feature list is more than enough to get started there are still a a few items left to be implemented.
The most important question, when looking at the above code, should be: How do I begin using this today? Olav went ahead and made it easy to do IDE integration - even setting up instructions on how to integrate with Eclipse on Windows (he currently shows how to integrate using the JScript command-line interface, but it can easily be expanded). I'm quite excited by this prospect - having the ability to do compile-time type-checking and be able to succinctly write classes with inheritance will be a major boon to development.
Additionally, he provides information on how to do automatic CGI translation (naturally, you would want to do this only in a development environment).
He's continuing to provide frequent updates on the Mascara blog - be sure to follow along if you're interested in starting to use ECMAScript 4 sooner, rather than later.
Tags: javascript, ecmascript, python
13 Comments on 'Writing ECMAScript 4, Today'
Next entries » ·
« Previous entries