Welcome to the Jetpack API tutorial. By the end of this tutorial, you'll have learned how to make a Jetpack Feature that removes all embeds — Flash movies, etc — from a particular page or all websites. The code required is never more lines than a polydactylic man can count on both hands.

Chapter 0: Get going

One of the primary goals of Jetpack is to have development be a real-time adventure. We know that tight feedback loops, a good debugger, and instant gratification makes for happy coders. That's why refreshing a Jetpack Feature is literally as simple as refreshing a webpage, and why we try to have all errors be reported sensibly and with line number!

Before we get started, you should know that this tutorial is actually interactive: if you click on one of the code snippets, it'll automatically install itself as a Jetpack feature and become editable, at which point you can tinker with the code to see what it does in real time. If you mess anything up, just reload this page to undo it.

Let's get going. Remember that you can also always check out the API Reference.

Chapter 1: The boom stick

Admit it. Have you always wanted a button in your browser that let's you make things go boom? I know I have. So that's the first thing that we are going to make. Let's begin by adding a widget to the status bar that contains the prophetic message "Boom!":

jetpack.statusBar.append({ html: "Boom!" });

Just click the above code, and there it is, large as life in the status bar. Notice the conspicuous lack of restarts! As you can see, statusBar.append takes an options object. Instead of passing in html, you can use the url keyword and pass it a relative url.

Right now the widget is probably way too wide — that's because we haven't yet added the auto-sizing feature to Jetpack. For now, you'll have to pass in the width.

jetpack.statusBar.append({ html: "Boom!", width: 45 });

That's nice, but just having a "Boom!" in your status bar isn't all that exciting. Let's make it do something.

jetpack.statusBar.append({ html: "Boom!", width: 45, onReady: function(widget){ $(widget).click(function(){ console.log( jetpack.tabs ); }); } });

Now, whenever you click on the widget, it logs the jetpack.tabs object to the Firebug console. Instead of reinventing the wheel, to debug Jetpack Features we've made Firebug the tool of choice. It's easy to introspect to learn more — for instance by delving in, you'll quickly find the jetpack.tabs.focused object, which gives you access to the currently active tab.

You can also see that we've automatically included jQuery by default—if you're unfamiliar with it, that's what the $ function is all about, and you can learn more by reading the jQuery Documentation. In the future, we hope to include other libraries. Feel free to fiddle around with the code, and see what you come up with.

Let's make our little Boom! widget do something more fun:

jetpack.statusBar.append({ html: "Boom!", width: 45, onReady: function(widget){ $(widget).click(function(){ jetpack.notifications.show( "Booming!" ); $(jetpack.tabs.focused.contentDocument) .find("body") .css({backgroundColor:"blue"}) .animate({opacity:.5}); }); } });

Give it a go and see what it does. Every tab object has a wealth of possible event listeners, and properties. Take a look via Firebug or check out the documentation. Just like an iframe, one of the properties is contentDocument, which gives you access to the the equivalent of the document for the page in the specified tab. Alternatively, you can use contentWindow to get access to the object which houses the page's .alert() function, and so forth.

When you want a light-weight way to inform your users of a bit of information, jetpack.notifications.show() may be the way to go. On Windows and Linux, these show up as toast notifications and on OS X as Growl notifications.

Let's turn away from our new-found ability to make pages blue, and instead to the ability to remove embeds from a page. It's one line of jQuery goodness.

jetpack.statusBar.append({ html: "Boom!", width: 45, onReady: function(widget){ $(widget).click(function(){ var doc = jetpack.tabs.focused.contentDocument; $(doc).find("embed").remove(); }); } });

Pretty good, huh? Less than ten lines of code gets us an on-demand embed killer.

Chapter 2: Distributing the boom

So you've got your feature written and you want to release it to the world. It's very easy to do — there's no special build step, or odd file format. All you need to do is drop the code in a file, let's call it "boom.js". Then in any page you want the feature to be installable, you add:

<link rel="jetpack" href="boom.js" name="Boom!"/>

to the header. That's it. When you navigate to the page, a notification bar will drop down with the option to install the feature.

Chapter 3: The automatic boom

We can now get rid of embeds on demand, but that requires clicking the Boom! button on every page. What if we instead wanted to to enable/disable the functionality for all sites? That's where the magic of jetpack.tabs.onReady comes in. It allows you to code on every navigation action, just a new page loads but before iframes, images, and scripts are fetched. To wait until everything is loaded, you can use jetpack.tabs.onLoad. Jetpack takes care of all the difficult edge cases, like dealing with multiple windows and new tabs. Jetpack also handles removing event handlers when you reload a Jetpack Feature, so that you never have to restart Firefox due to errant event handlers.

function removeEmbeds(doc){ $(doc).find("embed").remove(); } jetpack.statusBar.append({ html: 'Boom?', width: 70, onReady: function(widget){ $("input", widget).click(function(){ if( this.checked ){ jetpack.tabs.onReady( removeEmbeds ); removeEmbeds(jetpack.tabs.focused.contentDocument); } else jetpack.tabs.onReady.unbind( removeEmbeds ); }); } });

One of the neat additions we've made is how you remove an event handler. Instead of passing in a string, you just call the unbind function which is a property of the event handling function.

Chapter 4: Libraries

Reusable code is at the heart of any good API. That's why Jetpack includes a "standard library" of common web APIs. At the moment, we've only implemented a Twitter library. In the future, there should be many more, including the ability to import libraries not included with Jetpack by default. (And for developers to contribute their APIs for others to use.)

Here's a simple Jetpack Feature that shows the Twitter library in use. It allows you to be notified of someone's latest Tweet.

var twitter = jetpack.lib.twitter var oldTweet = null; function getTweet() { twitter.statuses.user_timeline({ id: "osunick", success: function (tweets) { var newTweet = tweets[0].text; if( oldTweet != newTweet ) jetpack.notifications.show( newTweet ); oldTweet = newTweet; } }); } getTweet(); setInterval( getTweet, 1000*60 );

Jetpack is smart enough to clear any setInterval's or setTimeout's that you use when you refresh your Jetpack.

For now, the easiest way to get documentation on the Twitter library is to read the commented source.

Chapter 5: Email notifier

Putting it all together, you should now be able to be able to read through the following example, which displays the number of unread emails in your inbox. The only new API calls here are jetpack.tabs.open(url) and tab.focus().

function GmailNotifier(doc){ $(doc).click( this.goToInbox ); this.update( doc ); setInterval( function(){ this.update(doc); }, 60*1000 ); } GmailNotifier.prototype = { goToInbox: function(){ jetpack.tabs.open("http://mail.google.com"); jetpack.tabs[ jetpack.tabs.length-1 ].focus(); }, update: function(doc){ var url = "http://mail.google.com/mail/feed/atom"; doc = $(doc); $.get( url, function(xml){ var el = $(xml).find("fullcount"); // Unread message count if( el ){ var count = el.get(0).textContent; doc.find("#count").text( count ); } else{ doc.find("#count").text( "Login" ); } }); } } jetpack.statusBar.append({ html: '', onReady: function(doc){ var gmail = new GmailNotifier(doc); $("#count", doc).css({ position: "absolute", left: 4, top: 8, fontSize: "10px", cursor: "pointer", backgroundColor: "rgba(255,255,255,.8)" }); }, width: 20 });

Chapter 6: The future

There's a lot more coming with Jetpack, so check back often. For now, make sure to check out the API Reference.