Monday, July 2, 2007

More Mashups: Using Greasemonkey to Weave New Features into Web Sites

With this blog entry I am continuing the theme of demonstrating tools to help you build mashups. In this case, I will show how a tool called Greasemonkey can be a powerful approach for building browser side mashups. Greasemonkey is a plugin to Firefox that allows a script developer to inject useful Javascript into any web page. This capability enables you to add new features to sites that you do not own. I will show in this blog how you can add a new feature to the dev2dev website, without having access to the dev2dev code. Later, a follow-up blog will show how this same technique can create a feature on dev2dev that includes data from a different web site, producing a true mashup.

NOTE: this blog entry was originally posted July 2nd, 2007 on my previous blogging system (dev2dev.bea.com). Comments on the old blog were not transferred.

This is part 1 of a series of blog entries on Greasemonkey mashups.

Client side Code Injection with Greasemonkey

Greasemonkey is just cool - and I have been having a lot of fun playing around with it. It operates on a simple principle, but delivers massive power from that simplicity.

Greasemonkey allows you, a Javascript developer, to write a script that gets included into web pages that a user visits with the Firefox browser. This script can do really anything, but usually it will inject/update HTML elements into the page to create entirely new features for that web site. The targeted web site need not have any idea that this is going on - the Greasemonkey script is executed on the browser after the original page comes back from the web server.

To be useful, a Greasemonkey script generally will be targeted towards a specific web site, though a general purpose script is possible. The developer specifies which URLs (with wildcards) are valid for the script. The Greasemonkey plug-in in Firefox will silently watch the user's URLs as they browser, and will inject a script when appropriate.

To be clear, Greasemonkey is not installed by default, nor are the scripts that you write. It is an opt-in activity for the user to both install Greasemonkey and then each script that they want to have. This means that Greasemonkey is not quite as accesible as other mashup solutions that I have written about - the mashup here is not a URL. The user must be skilled enough to install Greasemonkey and your script.

greasemonkey_arch

Greasemonkey Hello World

Installing Greasemonkey is straightforward: you will find the download link at the Greasemonkey Home Page. You will need to use Firefox of course, but otherwise it can't go wrong. After you have it installed, the next step is to install your first Greasemonkey script.

Unlike a lot of cutting edge projects out on the web, Greasemonkey has excellent documentation. Primarily, the best place to go for an introduction, tutorials, and documentation is Mark Pilgrim's online book, Dive Into Greasemonkey. The book is quite comprehensive and is geared towards getting you on your feet quickly.

To that point, the Hello World example for Greasemonkey that I will show is derived directly from Mark's book. The example below has been stripped of comments for brevity, but otherwise is identical to his original found here. This script is offered as a public file named helloworld.user.js. By the file extension, you know that this is nothing but JavaScript. And a closer look will show that it contains some meta-data within the comments, and then a single JavaScript function call to alert().

The meta-data is hopefully self-explanatory: it instructs Greasemonkey to execute it on any (*) site except for a couple of exclusions. If you install Greasemonkey, and then install this script helloworld.user.js by clicking on the link, you will see that it just pops up an alert box for every page view.

// Hello World! example user script
// version 0.1 BETA!
// 2005-04-22
// Copyright (c) 2005, Mark Pilgrim
// Released under the GPL license
// http://www.gnu.org/copyleft/gpl.html
// ==UserScript==
// @name Hello World
// @namespace http://diveintogreasemonkey.org/download/
// @description example script to alert "Hello world!"
// @include *
// @exclude http://diveintogreasemonkey.org/*
// @exclude http://www.diveintogreasemonkey.org/*
// ==/UserScript==

alert('Hello world!');









greasemonkey_install

























Mr. Wong and BEA dev2dev



























If you visit BEA's dev2dev site, you will notice that Jon has helpfully included links to popular tagging services on all articles and blogs. This allows you to quickly tag the article or blog using del.icio.us, Digg, DZone, Furl or Reddit. See the image below to see how the site works today:



























greasemonkey_mrwong_orig



























However, what if that list is not sufficient for your needs? That is my problem - there is one tagging site that I use that is not listed. As an aside, I have been doing research into the spread of Web 2.0 in China. In doing that work, I have been tagging chinese articles that I find, and some english ones just to be helpful. I am not using an english language tagging site, I am using Mr. Wong, which is a Chinese language tagging site. I would like to have Mr. Wong as one of my tagging options when browsing dev2dev. But since I don't have access to the dev2dev code, I cannot add it.



























Weaving Mr. Wong into BEA dev2dev Using Greasemonkey


















Enter Greasemonkey.









The process for developing a Mr. Wong feature on dev2dev is as follows:













  • Navigate to dev2dev, and View Source on the HTML for blogs and articles






  • Note that the tagging links box is easily found in both by looking for the last div tag with class box_gray







  • The div tag contains a simple HTML table, all we need to do is add a new row






  • Formulating the link to Mr. Wong is easy: we just need the document title and url. Both are easily available in JavaScript






  • Write the JavaScript!
















Before I show the code for the script, here is the result:



























greasemonkey_mrwong


















As you can see, even though I did not have access to dev2dev code, I was able to easily add a brand new feature to it!









The Mr. Wong Script








The script used to add this feature to dev2dev is below. But if you would like to try it out, or view the live version, navigate to my script repository for Greasemonkey (or here if that link does not work). Install the script named dev2dv Mr Wong. The code roughly follows this path:













  • Find the last box_gray div tag on the page, this is the tagging box







  • Find the inner table in that div







  • Add a new row to that table







  • Populate the row with a link and image for Mr. Wong
















// ==UserScript==
// @name dev2dev Mr Wong
// @namespace http://dev2dev.bea.com
// @description Injects a link to Mr Wong on each blog/article link
// @include http://dev2dev.bea.com/blog/*
// @include http://dev2dev.bea.com/pub/*
// ==/UserScript==

var divTagsWithClass, taggingDiv;
GM_log('Running dev2dev Mr Wong script');

// get the existing tagging div box
// by looking for the class (box_gray)
divTagsWithClass = document.evaluate(
"//div[@class='box_gray']",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null);
// the tagging div appears last
taggingDiv = divTagsWithClass.snapshotItem(divTagsWithClass.snapshotLength-1);

if (taggingDiv)
{
// find the table
tableTag = taggingDiv.getElementsByTagName('table')[0];
if (tableTag)
{
// create the new row
var lastIndex = tableTag.rows.length;
newLinkTR = tableTag.insertRow(lastIndex);

// create the td for image and set styles
var newLinkTD = newLinkTR.insertCell(0);
newLinkTD.valign = 'bottom';
newLinkTD.width = '20';

// build the HTML
newLinkTD.innerHTML = '<img src='+
'"http://www.mister-wong.cn/favicon.ico"'+
' alt="Mr. Wong" border="0" height="18" '+
'hspace="8" width="18">';

// create the td for the image
var newLinkTD = newLinkTR.insertCell(1);

// set the styles
newLinkTD.nowrap = 'nowrap';
newLinkTD.valign = 'bottom';

// build the HTML
newLinkTD.innerHTML =
'<a href="http://www.mister-wong.cn/index.php?'+
'action=addurl&v=1&bm_url='+
window.location+
'&bm_description='+
document.title+
'">'+
'Mr. Wong</a>';
}
else {
GM_log(' Error: did not find the tagging inner table');
}
}
else {
GM_log(' Error: did not find a tagging div');
}








Pros and Cons









Hopefully you can see the power and simplicity of the Greasemonkey plugin. In a follow up blog I will show how you can take this technique further by injecting data from other sites to create a true mashup. Here is what I see as the pros and cons of this tool:













  • Pro: it is easy for a developer to install both the plugin and scripts







  • Pro: a seasoned JavaScript developer can crank out features in little time







  • Pro: you do not need access to the web site's code to add new features







  • Pro: the documentation and developer community around Greasemonkey are superb







  • Con: mashups created with Greasemonkey aren't exactly URL accessible, it requires install steps







  • Con: Greasemonkey is not supported on IE or any browser other than Firefox







  • Con: there is a significant security issue that I will cover in my next blog entry






































References


































Technorati Tags: ,










No comments: