Include a JavaScript Source File into Google’s CodeRunner or OpenSocialDevApp

OpenSocialDevApp or Google’s CodeRunner is a great tool for testing code snippets using OpenSocial API. It allows you to easily test code by cutting and pasting your JavaScript code into a textbox. You don’t need to load a gadget XML file into the server to test out something which can be a tedious process.

This works out really well when your code is small. However, once your code gets bigger, cutting and pasting starts to get painful. Wouldn’t it be nice if you can simply save your JavaScript code into a file, say mytestcode.js, and then just cut and paste a neat single line into the textbox like this?

<script type="text/javascript" 
    src="http://myserver.com/mytestcode.js"></script>

To test changes in mytestcode.js, all you need to do is re-execute CodeRunner every time you make an update to the file. No need for cutting-and-pasting.

However, this OpenSocial application only accepts raw JavaScript code, so the code above won’t work since it’s an HTML code.

To fix this problem, what we need is a way to convert the HTML code above into a JavaScript code. This is where the technique of dynamically including a JavaScript file comes to the rescue.

The code below is the script-src-tag converted into a JavaScript code. If you are not familiar with this technique, see this posting for details.

function includeJavascript(src) {
  if (document.createElement && document.getElementsByTagName) {
    var head_tag = document.getElementsByTagName('head')[0];
    var script_tag = document.createElement('script');
    script_tag.setAttribute('type', 'text/javascript');
    script_tag.setAttribute('src', src);
    head_tag.appendChild(script_tag);
  }
}
includeJavascript("http://myserver.com/mytestcode.js");

Instead of cutting-and-pasting the entire mytestcode.js into the CodeRunner’s textbox, just use the code above and make your changes directly to the mytestcode.js file on your server.

Furthermore, you don’t need to put all your code in a single file. You can break them up into multiple files and call out the include function for each.

includeJavascript("http://myserver.com/mytestcode1.js");
includeJavascript("http://myserver.com/mytestcode2.js");
includeJavascript("http://myserver.com/mytestcode3.js");
includeJavascript("http://myserver.com/mytestcode4.js");

With this technique, you can even run your entire OpenSocial application in CoderRunner!

Alvin Abad

Advertisements

When Firebug’s Console Object Cannot be Overridden

In my previous blog post, I’ve shown how to use Firebug’s console object to log debug messages. I’ve also shown how to perform graceful degradation if the console object is not available like when using a non-Firefox browser or if Firebug’s console is not enabled. This way, one can still retain the calls to console.log() without generating any error messages. However, there were still some issues I failed to address.

Production deployment

Normally, when you deploy code into production, you don’t want your debug calls to be included. You don’t want users to be getting those debug messages. There are two ways to fix this problem: 1) Add a step to your deployment process to search and remove all the debug calls in your code; or 2) Add some kind of a switch, say a global variable DEBUG, to decide whether to use Firebug’s console logger or redirect the call to a dummy console.log() that will not do anything. This functionality is similar to loggers like log4j in Java where you can set different settings (info, debug, etc.) to control logging without modifying the code.

Let’s say we wanted #2 above. The code below illustrates how this can be done.

    if (!window.DEBUG || typeof(console) == 'undefined') {
        console = {};
        console.log = function(msg) {
            return false;
        };
    }

If DEBUG is off (false), e.g., production, it will create the console object and implement a no-operation log() method. If the browser is Firefox, this will effectively override its console object, therefore, …

Wait, that is not correct. As of this writing (Firebug-v1.3.3), Firebug’s console object cannot be overridden! If you attempt to do so, you will get an error message of something like, “setting a property that has only a getter.”

Programming to an Interface and not an implementation

To fix this problem, what we should do instead is not use the Firebug console object directly to log messages. This is like the design pattern where one programs to an Interface and not an implementation.

Following this principle, we create our own implementation of the console object, let’s say mylogger. With this object, we can then control if we want to use Firebug’s console.log() or the dummy one depending on our DEBUG setting. Below is the modified version of the HTML page using mylogger.log().

<html>
  <head>
    <script type="text/javascript">
        DEBUG = true;

        // by default, set mylogger to do nothing
        mylogger = {};
        mylogger.log = function(msg) {
            return false;
        };

        // if DEBUG is true and Firebug console is available, use it for logging
        if (window.DEBUG && typeof(console) !== 'undefined') {
            mylogger = console;
	}
	    	    
        function demo() {
            // I did lots of things here          
            mylogger.log("I'm here!");
            // and a lot more          
        }
    </script>
  </head>
<body>
  <h1>Firebug's console.log() Demo</h1>
  <button onclick="demo();">Firebug console.log() demo</button>
</body>
</html>

The code above has a DEBUG switch that we set on the server side to true or false depending if we want to log messages or not. Instead of using the console.log() method directly in the demo() function, we use mylogger.log(). Since we cannot override Firebug’s console object, what we can do instead is make the decision whether to use it or not at runtime.

Debugging JavaScript Using Firebug’s Console Logger

Thanks to Firebug, debugging JavaScript has never been easier. Firebug is an add-on to the FireFox browser. It has many wonderful features. One of my favorite is the console logger. This is where you can call the function console.log() in your code to write log messages to the Firebug console. This is definitely much better than using the alert() function. It’s unobtrusive and transparent to the execution of your JavaScript program.

Below is a sample HTML page with JavaScript code demonstrating how to use this function.

<html>
  <head>
    <script type="text/javascript">
    function demo() {
        // do something          
        console.log("I'm here!");
        // do something          
    }
    </script>
  </head>
<body>
  <h1>Firebug's console.log() Demo</h1>
  <button onclick="demo();">Firebug console.log() demo</button>
</body>
</html>

The code above has a button element that will print out the message “I’m here!” to the Firebug console.

Graceful Degradation

Of course, console.log() only works with the Firefox browser, with Firebug installed, and the console is enabled. Otherwise, you’ll get an error saying the console object is not defined.

For browsers other than Firefox or if Firebug is not installed, you can still retain the console.log() calls in your code and avoid getting any error messages by redirecting this call to a no-operation. To do this, create a console object and an implementation of the log() method that does not do anything. Below is a sample implementation.

// if console is not defined, e.g., Firebug console is not enabled or Non-Firefox browser
if (typeof console == 'undefined') {
    var console = {};
    console.log = function(msg) {
        return;
    };
}

The code above shows that if the console object is not defined, like when using a browser other than FireFox, a console object will be created together with a method named log() that does not do anything. That console object will then be the one that will be used by your log() calls in non-Firefox browser or when Firebug console is not enabled, which will just fail silently.

The console.log() method also supports formatted messages similar to C or Perl’s printf function. For example:

console.log("This is loop %s", loop_counter);

Firebug’s console object is not limited to the log() method. It can do other cool things. You can learn more about them here – http://getfirebug.com/console.html

Many sites have discussed this topic with great examples and illustrations. Here’s a nice one – http://ajax.phpmagazine.net/2006/05/firebug_the_future_of_javascri.html.

Note: The solution presented here is not without problems. See my other post for details.
Alvin Abad

Send a Twitter Message from the Unix Command Line

If you are a fan of Twitter and also a Unix user who spends most of your waking hours on the command line, wouldn’t it be nice if you can send your Twitter update from the Unix command line? Twitter has an API that makes sending from the Unix command line easy. All you need is the curl command (which should be available nowadays on most Unix systems) and you can fire up your Twitter message like this:

    curl -u mytwitterusername:mypassword -d status="the server is up!" \
                  http://twitter.com/statuses/update.json

Note: The command above should be all in one line.

Easy, isn’t it?

But you might say, “Wow, that’s a lot of typing to do. BTW, is that my password in clear text?”

Well, this is where Unix scripting comes to the rescue. You can easily wrap this in a shell script and your usage could be as simple as this:

        twitter.sh "the server is up!"

The rest are inside the script where you can hide your username and password by making sure that only you can read it. For example:

#!/bin/sh
curl -u mytwitterusername:mypassword -d status="$*" \
      http://twitter.com/statuses/update.json

If you are not comfortable putting your password and username in the script, you can always make the script prompt for them. For example:

#!/bin/sh

echo -n "Enter username: "
read USERNAME

echo -n "Enter password: "
stty -echo
read PASSWORD
stty echo
echo

MESSAGE="$*"

curl -u $USERNAME:$PASSWORD -d status="$MESSAGE" \
     http://twitter.com/statuses/update.json
echo

For details about this API, see Twitter documentation: http://apiwiki.twitter.com/REST+API+Documentation

Alvin Abad