Friday, December 19, 2008

Extending WebKit Web Inspector with Fun!

After being astonished by the code that won the ActionScript contest of 25lines.com I decided to see if it was possible to port it to Javascript. 

I created an html page to hold the game and then worked on the port. After some time, I had the game working on Firefox and Safari, which was more than enough. Then the crazy idea came into my mind... 

Why not to show how to extend WebKit Web Inspector with this game? -I can do a hello world example if you want.

So, to show you how to add a custom Panel to the Web Inspector, in a similar way in how Firebug allows to be extended, we will add the game. 

Here you can see an screenshot of the final project inside Web Inspector:


WebKit Web Inspector is easy to extend. First we need to find where it's installed. If you don't have it already, you can get it from here. In my Mac it resides in the following folder: 

/Applications/WebKit.app/Contents/Frameworks/10.5/WebCore.framework/Versions/A/Resources/inspector

There you will find the following files: inspector.html and inspector.js

Those files are the ones that we will modify to add our custom Panel with the game, but before we need to grab the code from the google project page -you will need to use svn-.

After you get the code, you will find two folders, inside jsport you can find the working HTML/Javascript example. Inside inspector there are the files for the panel. Copy game.css and  game.js to the folder where you have installed Web Inspector. Then edit inspector.html adding the following lines below the inspector.js include line:

 <script type="text/javascript" src="game.js"></script>
 <link rel="stylesheet" type="text/css" href="game.css">

Then open inspector.js and replace the following code:

    this.panels = {
        elements: new WebInspector.ElementsPanel(),
        resources: new WebInspector.ResourcesPanel(),
        scripts: new WebInspector.ScriptsPanel(),
        profiles: new WebInspector.ProfilesPanel(),
        databases: new WebInspector.DatabasesPanel()
    };

with the following one:

    this.panels = {
        elements: new WebInspector.ElementsPanel(),
        resources: new WebInspector.ResourcesPanel(),
        scripts: new WebInspector.ScriptsPanel(),
        profiles: new WebInspector.ProfilesPanel(),
        databases: new WebInspector.DatabasesPanel(),
        game: new WebInspector.GamePanel()
    };

What we did here was add our GamePanel to the hash of panels that Web Inspector will initialize.

Then If you see inside game.js you will find the following -I omitted some code for brevity-:

WebInspector.GamePanel = function()
{
WebInspector.Panel.call(this);
...
};

WebInspector.GamePanel.prototype = {
    toolbarItemClass: "scripts",

    get toolbarItemLabel()
    {
        ...
    },

    show: function()
    {
        WebInspector.Panel.prototype.show.call(this);
        
        ...
    },

    hide: function()
    {
        WebInspector.Panel.prototype.hide.call(this);
    }
};

WebInspector.GamePanel.prototype.__proto__ = WebInspector.Panel.prototype;

Those are the three basic parts of our Panel. First we declare it. Then we implement the interface of WebInspector.Panel and at the end we declare that our panel extends WebInspector.Panel

In the first part what we do is add a container for the game as a pre tag. This element is attached to this.element which is the base element of a WebPanel. By setting the id gameArea, we style the pre with the styles defined in game.css

Then on the second part I set the default css class for our panel as scripts. In this way, our button on the Web Inspector toolbar will have the same icon as the Scripts panel -if you want you can add a new style and define there a background image as you will do with CSS in a normal web page-.

For get toolbarItemLabel() we return Fun!. This will be the label for our Panel in the toolbar.

Then we implement show() where we draw the game. Here we can add the code that will initialize the contents of our Panel. Inside hide() We should implement all the logic to be run when the user switch to another panel, like removing unused objects, etc.

After we have everything in place. We restart WebKit, open the Web Inspector and enjoy our game.

NOTE 1: AFAIK, this technique should work for Google Chrome Web Inspector. The last time I checked the code, it was using the same code of WebKit.

NOTE 2: The drawback of this kind of extensions is that the next time you upgrade the browser, it will erase your Panel. Maybe in the future WebKit allows a more plug and play way of doing it. In this previous post I show some screenshots of  FireSymfony working inside Web Inspector.

NOTE 3: The original author of the ActionScript game is Marius Heil.

4 comments:

Marius Heil said...

Cool!
I love that port, now even those not having Flash installed can play the little ASCII game :-)
Makes me think of adding more Levels and Multiplayer support :D

Alvaro Videla said...

@Marius

Thanks :-)

Just let me know if you add more levels, so I can update the js game.

Pablo Sande said...

La verdad que impecable che... En realidad se que no era necesario el halago, pero queria postear algo en español jejeje...

Saludos desde Uruguay!

Alvaro Videla said...

Gracias Pablo, saludos desde China :-)