<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ashita.org &#187; JavaScript</title>
	<atom:link href="http://www.ashita.org/tag/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ashita.org</link>
	<description></description>
	<lastBuildDate>Wed, 27 Apr 2011 22:37:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Howto: XHR Listening by a Firefox Addon</title>
		<link>http://www.ashita.org/howto-xhr-listening-by-a-firefox-addon/</link>
		<comments>http://www.ashita.org/howto-xhr-listening-by-a-firefox-addon/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 04:00:38 +0000</pubDate>
		<dc:creator>Jon</dc:creator>
				<category><![CDATA[Firefox]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Pirate Questing]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[Firefox Extension]]></category>
		<category><![CDATA[XmlHttpRequest]]></category>

		<guid isPermaLink="false">http://ashita.org/?p=307</guid>
		<description><![CDATA[The following post draws significantly from a post by Jan Odvarko at http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/ but goes a bit further. There are also some sections which were inspired by Firebug, but are heavily modified. What you need to know Before I get into the code, understand that one of the most important things in this process to [...]]]></description>
			<content:encoded><![CDATA[<p>The following post draws significantly from a post by Jan Odvarko at <a href="http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/">http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/</a> but goes a bit further. There are also some sections which were inspired by <a href="http://www.getfirebug.com">Firebug</a>, but are heavily modified.</p>
<ul class='structure'>
<li>
<h3>What you need to know</h3>
<p>Before I get into the code, understand that one of the most important things in this process to understand is that your extension&#8217;s listener is just one in a chain. It is the responsibility of every listener in the chain to pass on the information. Failure to do this has some amusing consequences&#8230;. like nothing loading in the browser.</p>
<p>Just to make it really clear &#8212; <em>Don&#8217;t drop the ball</em>. (Edit: And while you <em>can</em> edit the data in the stream &#8212; don&#8217;t do it unless you have a really good reason.)
</li>
<li>
<h3>Convenience methods and aliases</h3>
<p>A lot of the Firefox internals are accessed using <code>Components.classes</code> and <code>Components.interfaces</code>. While the verbosity makes it clear, it can at times be overly repetitive and, honestly, can take a long time to write out. A fairly common shorthand is in use, <code>Cc</code> and <code>Ci</code> with a few other less common shorthands like <code>CCIN</code> (for creating instances of a class based on a class name and an interface name) and <code>CCSV</code> (similarly creating a service based on a class name and interface name)</p>
<pre><code class='javascript'>
if (typeof Cc == "undefined") {
	var Cc = Components.classes;
}
if (typeof Ci == "undefined") {
        var Ci = Components.interfaces;
}
if (typeof CCIN == "undefined") {
	function CCIN(cName, ifaceName){
		return Cc[cName].createInstance(Ci[ifaceName]);
	}
}
if (typeof CCSV == "undefined") {
	function CCSV(cName, ifaceName){
		if (Cc[cName])
			// if fbs fails to load, the error can be _CC[cName] has no properties
			return Cc[cName].getService(Ci[ifaceName]);
		else
			dumpError("CCSV fails for cName:" + cName);
	};
}</code></pre>
<ul class='structure'>
<li>
<h4>What&#8217;s with all of the <code>typeof</code> checks?</h4>
<p>Firebug, gotta love it, but it declares the same things using <code>const</code>. Inside of an <code>if()</code> block, a <code>const</code> is still seen and conflicts, even when the if condition evaluates to <code>false</code>. The code above is essentially a workaround to satisfy both possibilities. <em>If the user has firebug installed, then carry on; if the user doesn&#8217;t have firebug installed, declare those shorthands</em>
</li>
</ul>
</li>
<li>
<h3>The constructor</h3>
<pre><code class='javascript'>function TracingListener() {
}</code></pre>
<p>Above is a (very) simple constructor function for us to create objects from. The methods and properties on the prototype are below. Note that while I could have changed the structure to accommodate better data-hiding, the method below reduces the number of new functions created by making them all declared only once on the prototype. Functions in the constructor are recreated every time the constructor is called with <code>new yourConstructor()</code> whereas functions on the prototype are shared by all instances.
</li>
<li>
<h3>The prototype definition</h3>
<ul class='structure'>
<li>
<h4>Basic properties</h4>
<pre><code class='javascript'>TracingListener.prototype =
{
    originalListener: null,
    receivedData: null,   //will be an array for incoming data.
</code></pre>
<p>The first part of the prototype definition is setting up some basic properties. Note that both are assigned <code>null</code>. These properties will exist on all instances of <code>TracingListener</code>, and thus not be <code>undefined</code> if/when checking. In the case of <code>receivedData</code>, do not be tempted to make it an array here. Remember that methods and properties on the prototype are shared by <em>all</em> instances of the same type &#8212; and we don&#8217;t want all instances to share the same array for data.</p>
<p>Also worth note is that <code>receivedData</code> is a good candidate for data-hiding and declaring it local to the constructor&#8230; but scope and visibility limitations would mean the functions requiring access to it would either need to be in the constructor as well, or have accessor and mutator methods for it. If you&#8217;re making a Singleton or a small number of instances, declaring functions in the constructor is no big deal, but this listener will be instantiated hundreds or thousands of times and it&#8217;s important to keep the duplication to a minimum.
</li>
<li>
<h4>Methods on the prototype</h4>
<ul class='structure'>
<li>
<h5>Interface Requirements</h5>
<pre><code class='javascript'>    //For the listener this is step 1.
    onStartRequest: function(request, context) {
    	this.receivedData = []; //initialize the array

	//Pass on the onStartRequest call to the next listener in the chain -- VERY IMPORTANT
	this.originalListener.onStartRequest(request, context);
    },</code></pre>
<p><code>onStartRequest</code> is the first thing called when the actual request processing begins. This is also the best opportunity to initialize the array on <em>this</em> listener.</p>
<pre><code class='javascript'>    //This is step 2. This gets called every time additional data is available
    onDataAvailable: function(request, context, inputStream, offset, count)
    {
       var binaryInputStream = CCIN("@mozilla.org/binaryinputstream;1",
                                 "nsIBinaryInputStream");
        binaryInputStream.setInputStream(inputStream);

        var storageStream = CCIN("@mozilla.org/storagestream;1",
                                 "nsIStorageStream");
        //8192 is the segment size in bytes, count is the maximum size of the stream in bytes
        storageStream.init(8192, count, null); 

	var binaryOutputStream = CCIN("@mozilla.org/binaryoutputstream;1",
                                 "nsIBinaryOutputStream");
        binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));

        // Copy received data as they come.
        var data = binaryInputStream.readBytes(count);

        this.receivedData.push(data);

        binaryOutputStream.writeBytes(data, count);

        //Pass it on down the chain
        this.originalListener.onDataAvailable(request,
                                          context,
                                          storageStream.newInputStream(0),
                                          offset,
                                          count);
    },</code></pre>
<p><code>onDataAvailable</code> essentially copies the data from the <a href="http://www.oxymoronical.com/experiments/apidocs/interface/nsIBinaryInputStream"><code>binaryInputStream</code></a> to our <code>receivedData</code> array and to the <a href="http://www.oxymoronical.com/experiments/apidocs/interface/nsIStorageStream"><code>storageStream</code></a> (via the <a href="http://www.oxymoronical.com/experiments/apidocs/interface/nsIBinaryOutputStream"><code>binaryOutputStream</code></a>). Then we pass a new <code>InputStream</code> from our <code>storageStream</code> onto the next listener in the chain.</p>
<pre><code class='javascript'>    onStopRequest: function(request, context, statusCode)
    {
	try
	{
                //QueryInterface into HttpChannel to access originalURI and requestMethod properties
		request.QueryInterface(Ci.nsIHttpChannel);

                //this is specific to the PirateQuesting Add-on, but is left here as an example of how to modify behaviour based on the requested URL
		if (request.originalURI
                    &amp;&amp; piratequesting.baseURL == request.originalURI.prePath
                    &amp;&amp; request.originalURI.path.indexOf("/index.php?ajax=") == 0)
		{

			var data = null;
			if (request.requestMethod.toLowerCase() == "post")
			{
				var postText = this.readPostTextFromRequest(request, context);
				if (postText)
					data = ((String)(postText)).parseQuery();

			}

                        //Combine the response into a single string
			var responseSource = this.receivedData.join('');

			//fix leading spaces bug
			//(FM occasionally adds spaces to the beginning of their ajax responses...
                        //which breaks the XML)
			responseSource = responseSource.replace(/^\s+(\S[\s\S]+)/, "$1");

                        //gets the date from the response headers on the request.
                        //For PirateQuesting this was preferred over the date on the user's machine
			var date = Date.parse(request.getResponseHeader("Date"));

                        //Again a PQ specific function call, but left as an example.
                        //This just passes a string URL, the text of the response,
                        //the date, and the data in the POST request (if applicable)
			piratequesting.ProcessRawResponse(request.originalURI.spec,
                                               responseSource,
                                               date,
                                               data);
		}
	}
	catch (e)
	{
		//standard function to dump a formatted version of the error to console
		dumpError(e);
	}
	//Pass it on down the chain
	this.originalListener.onStopRequest(request,
                                         context,
                                         statusCode);
    },</code></pre>
<p>The <code>onStopRequest</code> above has a few tricky parts. The first is the <code>QueryInterface</code> to <a href="http://www.oxymoronical.com/experiments/apidocs/interface/nsIHttpChannel"><code>nsIHttpChannel</code> </a>&#8211; this is critical to getting the info needed. The second tricky part is to get the posted variables. To do so, you need to check that the <code>requestMethod</code> was indeed post, and then we call <code>readPostTextFromRequest</code> which I&#8217;ll introduce in a bit. The last tricky bit is getting the Date header from the response. <code>Date.parse()</code> plays nicely with those (assuming the server response conforms)</p>
<pre><code class='javascript'>    QueryInterface: function (aIID) {
        if (aIID.equals(Ci.nsIStreamListener) ||
            aIID.equals(Ci.nsISupports)) {
            return this;
        }
        throw Components.results.NS_NOINTERFACE;
    },</code></pre>
<p>This is pretty standard for anything fulfilling an interface contract for Firefox (or other mozilla-based browsers). <code>QueryInterface</code> is part of the <a href="http://www.oxymoronical.com/experiments/apidocs/interface/nsISupports"><code>nsISupports</code></a> interface and is the only part which is scriptable. All interfaces are derived from <code>nsISupports</code>, so it has to be there.
</li>
<li>
<h5>Utility methods</h5>
<p>The following methods are required by our TracingListener but are not part of the interface contract. (It would also have been possible to define them globally or within a pseudo-namespace.)</p>
<pre><code class='javascript'>    readPostTextFromRequest : function(request, context) {
        try
        {
	        var is = request.QueryInterface(Ci.nsIUploadChannel).uploadStream;
	        if (is)
	        {
	            var ss = is.QueryInterface(Ci.nsISeekableStream);
	            var prevOffset;
	            if (ss)
	            {
	                prevOffset = ss.tell();
	                ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
	            }

	            // Read data from the stream..
		    var charset = "UTF-8";
		    var text = this.readFromStream(is, charset, true);

	            if (ss &amp;&amp; prevOffset == 0)
	                ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);

	            return text;
	        }
		else {
			dump("Failed to Query Interface for upload stream.\n");
		}
	    }
	    catch(exc)
	    {
			dumpError(exc);
	    }

	    return null;
	},</code></pre>
<p>I will readily admit that <code>readPostTextFromRequest</code> is mostly taken from Firebug, though there are a few changes. Basically, we have to do the same thing as before and <code>QueryInterface</code> into the appropriate interface. In this case we need <a href="http://www.oxymoronical.com/experiments/apidocs/interface/nsIUploadChannel">nsIUploadChannel</a> to get access to <code>uploadStream</code>. And then we <code>QueryInterface</code> the <code>uploadStream</code> into a <a href="http://www.oxymoronical.com/experiments/apidocs/interface/nsISeekableStream">nsISeekableStream</a> (noticing a pattern, yet? <code>QueryInterface</code> is your best friend.. and worst enemy.). After that we store the original offset in the stream in <code>prevOffset</code>, and then seek to the beginning of the stream. Then we read the data and, if the stream was at position 0 originally, we seek to the beginning again.</p>
<pre><code class='javascript'>	readFromStream : function(stream, charset, noClose)	{

	    var sis = CCSV("@mozilla.org/binaryinputstream;1",
                            "nsIBinaryInputStream");
	    sis.setInputStream(stream);

	    var segments = [];
	    for (var count = stream.available(); count; count = stream.available())
	        segments.push(sis.readBytes(count));

	    if (!noClose)
	        sis.close();

	    var text = segments.join("");
	    return text;
	}

}</code></pre>
<p><code>readFromStream</code> is also largely from Firebug with a few modifications. It is however remarkably similar to what is done in <code>onDataAvailable</code> and <code>onStopRequest</code>. Basically, we get a <code>BinaryInputStream</code> to work with the stream given. Then we loop through the segments of the stream (size provided by <code>available()</code>) and add them to an array. When finished with that, we join the segments and return the text.</p>
<pre><code class='javascript'>httpRequestObserver = {

	observe: function(request, aTopic, aData){
		if (typeof Cc == "undefined") {
			var Cc = Components.classes;
		}
		if (typeof Ci == "undefined") {
			var Ci = Components.interfaces;
		}
	    	if (aTopic == "http-on-examine-response") {
	    		request.QueryInterface(Ci.nsIHttpChannel);

			if (request.originalURI
                            &amp;&amp; piratequesting.baseURL == request.originalURI.prePath
                            &amp;&amp; request.originalURI.path.indexOf("/index.php?ajax=") == 0) {
				var newListener = new TracingListener();
    				request.QueryInterface(Ci.nsITraceableChannel);
    				newListener.originalListener = request.setNewListener(newListener);
			}
		}
	},

	QueryInterface: function(aIID){
		if (typeof Cc == "undefined") {
			var Cc = Components.classes;
		}
		if (typeof Ci == "undefined") {
			var Ci = Components.interfaces;
		}
		if (aIID.equals(Ci.nsIObserver) ||
		aIID.equals(Ci.nsISupports)) {
			return this;
		}

		throw Components.results.NS_NOINTERFACE;

	},
};</code></pre>
<p>This part is fairly straightforward. The object httpRequestObserver has to fulfill the contract for the nsIObserver interface &#8212; which only has two methods: observe and QueryInterface.
</li>
</ul>
</li>
</ul>
</li>
<li>
<h3>Observer registration</h3>
<p>Finally, we need to register the observer:</p>
<pre><code class='javascript'>var observerService = Cc["@mozilla.org/observer-service;1"]
    .getService(Ci.nsIObserverService);

observerService.addObserver(httpRequestObserver,
    "http-on-examine-response", false);</code></pre>
<p>Now the <a href="http://www.oxymoronical.com/experiments/apidocs/interface/nsIObserverService"><code>observerService</code></a> will call the <code>observe</code> method on <code>httpRequestObserver</code> whenever it notifies observers with the <code>http-on-examine-response</code> topic.</p>
<p>When you want to unregister the observer, use:</p>
<pre><code class='javascript'>observerService.removeObserver(httpRequestObserver,
    "http-on-examine-response");</code></pre>
<p>As you can see, getting the text and post variables from an http request is non-trivial.
</li>
</ul>
<p>Note, though, that this code does not check the context to determine whether the http request is <em>for</em> a browser window, or <em>from</em> a browser window so depending on the complexity of your situation, you may want to do that as well. Perhaps, I&#8217;ll add that in another post.</p>
<p>(See Firebug license <a href="http://code.google.com/p/fbug/source/browse/branches/firebug1.5/license.txt">here</a>. Special thanks to the Firebug team and to Jon Odvarko for providing so much useful material. The interface docs at <a href="http://www.oxymoronical.com/experiments/apidocs/platform/1.9.2a1pre">oxymoronical</a> are a great resource. The <a href="https://developer.mozilla.org">Mozilla Developer Center</a> also deserves special credit for great documentation. )</p>
<p><strong>Update (Jan 17, 2010):</strong> Corrected a small bug in <code>onStopRequest</code> (Thanks Broady!). See <a href="http://www.ashita.org/howto-xhr-listening-by-a-firefox-addon/#comment-419">below</a> for details.</p>
<p><strong>Update (April 22, 2010):</strong> Corrected a bug which doesn&#8217;t occur if Firebug is installed (Thanks Harini!). See <a href="http://www.ashita.org/howto-xhr-listening-by-a-firefox-addon/#comment-1125">below</a> for details.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ashita.org/howto-xhr-listening-by-a-firefox-addon/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>Implementing an XPCOM Firefox Interface and Creating Observers</title>
		<link>http://www.ashita.org/implementing-an-xpcom-firefox-interface-and-creating-observers/</link>
		<comments>http://www.ashita.org/implementing-an-xpcom-firefox-interface-and-creating-observers/#comments</comments>
		<pubDate>Thu, 08 Oct 2009 19:05:25 +0000</pubDate>
		<dc:creator>Jon</dc:creator>
				<category><![CDATA[Firefox]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Firefox Extension]]></category>
		<category><![CDATA[XPCOM]]></category>

		<guid isPermaLink="false">http://ashita.org/?p=314</guid>
		<description><![CDATA[There are lots of cases when it is desirable to implement one of the XPCOM interfaces in use by Firefox, or other mozilla-based browsers. There are three cases where PirateQuesting does so, but once you see the concept, it should be easy to adapt to your situation. You must have a QueryInterface to enjoy this [...]]]></description>
			<content:encoded><![CDATA[<p>There are lots of cases when it is desirable to implement one of the XPCOM interfaces in use by Firefox, or other mozilla-based browsers. There are three cases where PirateQuesting does so, but once you see the concept, it should be easy to adapt to your situation.</p>
<ul class='structure'>
<li>
<h3>You must have a QueryInterface to enjoy this ride</h3>
<p>First off, all XPCOM interfaces in Firefox inherit from <a href="https://developer.mozilla.org/en/nsISupports"><code>nsISupports</code></a> (Also see details on oxymoronical.com <a href="http://www.oxymoronical.com/experiments/apidocs/platform/1.9.2a1pre/interface/nsISupports">here</a>). Only one method is scriptable and part of XPCOM &#8212; <a href="https://developer.mozilla.org/en/NsISupports/QueryInterface"><code>QueryInterface</code></a> &#8212; and it <em>must</em> be present in all implementations of XPCOM interfaces. </p>
<pre><code class='javascript'>
//"implements" nsISupports
var InterfaceImplementation = function() {
  QueryInterface: function (aIID) {
      if (aIID.equals(Components.interfaces.nsISupports))
      {
         return this;
      }
      throw Components.results.NS_NOINTERFACE;
  }
}
</code></pre>
<p>The above is an example of the very minimum required to support any interface. <code>QueryInterface</code> requires a first parameter which is an aIID from <code>Components.interfaces.*</code>. There is also a second, optional, parameter, but as I have never come across this in use, it&#8217;s not worth pursuing here.
</li>
<li>
<h3>Now what?</h3>
<p>A very common (and useful) use of XPCOM interface implementation is creating your own observers, for example:</p>
<pre><code class='javascript'>
var myObserver = {

  observe: function(request, aTopic, aData){
    if (aTopic == "http-on-examine-response")
    {
      //response has come back, now what?
    }
    else if (aTopic == "http-on-modify-request")
    {
      //opportunity to modify headers on request
    }
  },

  QueryInterface: function(aIID){
     if (aIID.equals(Components.interfaces.nsIObserver) ||
         aIID.equals(Components.interfaces.nsISupports))
    {
      return this;
    }
    throw Components.results.NS_NOINTERFACE;
  },
};
</code></pre>
<p>The <a href="http://www.oxymoronical.com/experiments/apidocs/interface/nsIObserverService">nsIObserver</a> interface is fairly simple as it only adds one new method. As you can see now, though, <code>QueryInterface</code> now checks for both <code>nsIObserver</code> and <code>nsISupports</code>. Remember: any interface you implement must have a <code>QueryInterface</code> supporting all interfaces in the inheritance chain.
</li>
<li>
<h3>Observer registration</h3>
<p>If you then wanted to register your observer, it&#8217;s as easy as:</p>
<pre><code class='javascript'>
var observerService = Components.classes["@mozilla.org/observer-service;1"]
                               .getService(Components.interfaces.nsIObserverService);

observerService.addObserver(myObserver,"http-on-examine-response", false);
observerService.addObserver(myObserver,"http-on-modify-request", false);
</code></pre>
<p>Then to unregister, you do:</p>
<pre><code class='javascript'>
observerService.removeObserver(myObserver, "http-on-examine-response");
observerService.removeObserver(myObserver, "http-on-modify-request");
</code></pre>
<p>When I have a chance, I&#8217;ll add a more complete example of using observers to watch http requests, but in the meantime check out the list of <a href="https://developer.mozilla.org/en/Observer_Notifications">Observer Notifications</a> at MDC.
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ashita.org/implementing-an-xpcom-firefox-interface-and-creating-observers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Singletons in JavaScript</title>
		<link>http://www.ashita.org/singletons-in-javascript/</link>
		<comments>http://www.ashita.org/singletons-in-javascript/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 07:13:57 +0000</pubDate>
		<dc:creator>Jon</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[closures]]></category>
		<category><![CDATA[Singleton]]></category>

		<guid isPermaLink="false">http://ashita.org/?p=329</guid>
		<description><![CDATA[I use singletons all over the PirateQuesting code, but I&#8217;ve never explained the idea here, nor how they are different from singletons in other languages. Anyone familiar with common design patterns knows how singletons work in the vast majority of languages. For a PHP example, see this post. In JavaScript there are basically two main [...]]]></description>
			<content:encoded><![CDATA[<p>I use singletons all over the <a href="http://pq.ashita.org">PirateQuesting</a> code, but I&#8217;ve never explained the idea here, nor how they are different from singletons in other languages.</p>
<p>Anyone familiar with common design patterns knows how singletons work in the vast majority of languages.  For a PHP example, see <a href="http://www.ashita.org/singletons-in-php/">this post</a>. </p>
<p>In JavaScript there are basically two main ways to create a singleton. One is use immediate instantiation so that the class may not be instantiated again. The second is closer to the traditional singleton pattern, however, since there are no private members or constructors, we can get around this by using a nested &#8216;class&#8217; constructor &#8212; and there are two ways to accomplish this.</p>
<p>The first way is done as follows:</p>
<pre>
var singleton = new (function Singleton() {
                               this.value = 12;
                             } )();

alert(singleton.value); // alerts 12;

var singly = new Singleton(); // Singleton is not defined.

alert(singleton instanceof Singleton); // Singleton is not defined
</pre>
<p>In the above, the constructor name, Singleton, isn&#8217;t really necessary. While it can&#8217;t be used to instantiate the Singleton again, it also can&#8217;t be used with <code>instanceof </code>or <code>typeof</code> so feel free to leave it out if you want; leaving it in, does make it more obvious what is happening though.</p>
<p>And the second way (version 1):</p>
<pre>
var Singleton = (function () {
  var instance = null;

  function Singleton() {
    this.value = 12;
  }

  this.getInstance = function () {
    if (instance === null) {
      instance = new Singleton();
    }
    return instance;
  }
})();

var singleton = Singleton.getInstance();
alert(singleton.value); // alerts 12;

var singly = new Singleton(); // Singleton is not a construct

alert(singleton instanceof Singleton); //invalid 'instanceof' operand Singleton
</pre>
<p>The above is just an anonymous function being called immediately (note the <code>()</code> after the function declaration). Inside the function it declares a pseudo-private member called <code>instance</code>, a pseudo-private constructor, <code>Singleton</code>, and a <code>getInstance</code> method. The <code>getInstance</code> method can see <code>instance</code> due to closure, while the outside world has no idea that it exists.</p>
<p>And finally, the second way (version 2):</p>
<pre>
var Singleton = {

  getInstance : (function() {

    var instance;
    function Singleton() {
      this.value = 12;
    }

    return function () {
      if (instance == null) {
	    instance = new Singleton();
      }
      return instance;

    }

  })()
}

var singleton = Singleton.getInstance();
alert(singleton.value);

var singly = new Singleton(); // Singleton is not a constructor

alert(singleton instanceof Singleton); //invalid 'instanceof' operand Singleton
</pre>
<p>In this final example, all of the logic is put into the <code>getInstance</code> function which is the result of a self-calling function which itself returns a function. Yeah, it&#8217;s a little hard to follow, but basically the returned function has visibility of <code>instance </code>and the <code>Singleton </code>constructor due to closure.</p>
<p>As a closing note, it&#8217;s worth pointing out that although all of the above methods do not permit a second instance construction, they also do not allow use of <code>typeof </code>or <code>instanceof </code>for type verification.</p>
<h3>Update</h3>
<p>Based on a comment below by Peter Robinett, I&#8217;ve come up with a different way to do this, which allows for <code>instanceof</code> and <code>typeof</code> and seems to be an all-round good solution to the problem. It does not, however use the classical <code>getInstance</code> method, but works well all the same.</p>
<pre>
var Singleton = function () {
  var instantiated = false;

  return function () {
    if (instantiated) {
      throw "Singleton already instantiated";
    }
    instantiated = true;
    this.value=12;
    }
}()

var singleton = new Singleton();
alert(singleton.value);    //alerts 12
alert(singleton instanceof Singleton);  alerts true 

var singly = new Singelton(); //throws exception and cannot be instantiated
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ashita.org/singletons-in-javascript/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Functions in Closures</title>
		<link>http://www.ashita.org/functions-in-closures/</link>
		<comments>http://www.ashita.org/functions-in-closures/#comments</comments>
		<pubDate>Mon, 01 Dec 2008 07:47:25 +0000</pubDate>
		<dc:creator>Jon</dc:creator>
				<category><![CDATA[DOM]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[closures]]></category>

		<guid isPermaLink="false">http://ashita.org/?p=304</guid>
		<description><![CDATA[I last wrote about closures and how this affects the visibility of variables and functions. This time I&#8217;m going to introduce returning functions from a closure and how it can be useful in the first part. First off, lets say you have a strange need to create functions to consistently add a value like addFive, [...]]]></description>
			<content:encoded><![CDATA[<p>I last wrote about <a href="http://ashita.org/javascript-closures/">closures</a> and how this affects the visibility of variables and functions. This time I&#8217;m going to introduce returning functions from a closure and how it can be useful in the first part. </p>
<p>First off, lets say you have a strange need to create functions to consistently add a value like addFive, addTen, etc. Well this is one way to go about it.</p>
<pre><code class="javascript">
function createAdder(addition_size) {
      return function (value) {
            return value + addition_size;
      }
}

var addFive = createAdder(5);
var addTen = createAdder(10);

alert(addFive(3));
alert(addTen(-10));
</code></pre>
<p>The code above will alert 8 and 0. While this isn&#8217;t the most natural use of the technique, hopefully it is clear enough. <code>addition_size</code> is retained by the <code>addFive</code> and <code>addTen</code> functions because the function had visibility when it was declared. </p>
<p>One handy way to use this is when creating event handlers that need to take parameters. When adding a handler, you pass the function itself, which doesn&#8217;t provide an opportunity to add extra parameters, we can get around this by doing:</p>
<pre><code class="javascript">
function getValuePlusFiveDisplayer(value) {
  return function (event) {
    var sum = addFive(value);
    alert(value + " + 5 = " + sum);
  }
}

var number_1 = document.getElementById("number_1");
number_1.addEventListener("click",getValuePlusFiveDisplayer(1),false);

var number_2 = document.getElementById("number_2");
number_2.addEventListener("click",getValuePlusFiveDisplayer(2),false);
</code></pre>
<p>And HTML like:</p>
<pre><code class="html">
&lt;span id="number_1" class="number_button"&gt;1&lt;/span&gt;
&lt;span id="number_2" class="number_button"&gt;2&lt;/span&gt;
</code></pre>
<p>Which would work like this:</p>
<p><span id="number_1" style="margin:5px;display:inline-block;background-color:cornsilk; padding:3px;border:1px solid black;" >1</span><span id="number_2" style="display:inline-block; margin:5px;background-color:cornsilk;padding:3px;border:1px solid black;">2</span></p>
<p><script>
function createAdder(addition_size) {
      return function (value) {
                     return value + addition_size;
               }
}
var addFive = createAdder(5);
function getValuePlusFiveDisplayer(value) {
  return function (event) {
    var sum = addFive(value);
    alert(value + " + 5 = " + sum);
  }
}
var number_1 = document.getElementById("number_1");
number_1.addEventListener("click",getValuePlusFiveDisplayer(1),false);
var number_2 = document.getElementById("number_2");
number_2.addEventListener("click",getValuePlusFiveDisplayer(2),false);
</script></p>
<p>Even though you&#8217;re unlikely to need this exact example, hopefully it gives you some ideas, or helps solve some problems </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ashita.org/functions-in-closures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Passing parameters into a created dialog, and retrieving them on exit</title>
		<link>http://www.ashita.org/passing-parameters-into-a-created-dialog-and-retrieving-them-on-exit/</link>
		<comments>http://www.ashita.org/passing-parameters-into-a-created-dialog-and-retrieving-them-on-exit/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 07:50:05 +0000</pubDate>
		<dc:creator>Jon</dc:creator>
				<category><![CDATA[DOM]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Pirate Questing]]></category>
		<category><![CDATA[XUL]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Firefox Extension]]></category>

		<guid isPermaLink="false">http://ashita.org/?p=251</guid>
		<description><![CDATA[This is going to be a pretty short tutorial today to help explain how to pass information to an window when opening it. The following is taken from PirateQuesting. First, here is the function for entering the code when PirateQuest asks the user for verification. function enterCode(url,imgsrc, func) { var params = {in:imgsrc, out:null}; window.openDialog("chrome://piratequesting/content/codeDialog.xul", [...]]]></description>
			<content:encoded><![CDATA[<p>This is going to be a pretty short tutorial today to help explain how to pass information to an window when opening it. The following is taken from PirateQuesting.</p>
<p>First, here is the function for entering the code when PirateQuest asks the user for verification.</p>
<pre>function enterCode(url,imgsrc, func) {
	var params = {in:imgsrc, out:null};
	window.openDialog("chrome://piratequesting/content/codeDialog.xul", "",
		"chrome, dialog, modal, resizable=no, status=no,
		height=250, width=400", params).focus();
	if (params.out) {
		piratequesting.Code.submit(url,params.out,imgsrc,func);
	}
	else {
	    // User clicked cancel. stop here
	}
}</pre>
<p>So, as we can see in the first line the params variable stores a hash. A has is useful here as it allows us to easily pass more than one variable in without goign to the work of creating an object. There are actually much more significant differences between a hash and an object but, for this tutorial, know that it stores values in name:value pairs separated by commas and all of it enclosed by curly braces. The last element must not be followed by a comma.</p>
<p>Next, when we use openDialog we pass params into the dialog.</p>
<p>After the user has clicked OK, the value of params.out is checked. The condition will be true unless the value is still null or by some strange miracle taken on a value like &#8216;false&#8217;.</p>
<p>Now, let&#8217;s look at the code behind the dialog itself</p>
<pre>function codeDialogOnLoad() {

    // Use the arguments passed to us by the caller
    document.getElementById("codeImage").setAttribute('src',
            window.arguments[0].in);
}

// Called once if and only if the user clicks OK
function onOK() {
    window.arguments[0].out = document.getElementById("codeValue").value;
    return true;
}</pre>
<p>Ok, so what do we have here? well, when the dialog first loads we call codeDialogOnLoad which then sets the image source on the dialog based on the value passed in params.in. Note that it is now referred to as window.arguments[0].in.</p>
<p>When the user presses OK, the value of an input box, codeValue, is assigned to params.out (a.k.a. window.arguments[0].out).</p>
<p>Last thing to look at is the codeDialog.xul</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?&gt;
&lt;dialog
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
  id="codeDialog"
  title="Enter the Code"
  ondialogaccept="return onOK();"
  buttonlabelaccept="Submit"
  onload="codeDialogOnLoad();"
  persist="screenX screenY width height"&gt;

	&lt;script type="application/x-javascript" src="chrome://piratequesting/content/codeDialog.js"/&gt;
	&lt;vbox&gt;
		&lt;label value="Enter the code shown below" /&gt;
		&lt;image id="codeImage" /&gt;
		&lt;textbox width="50" id="codeValue" /&gt;
	&lt;/vbox&gt;
&lt;/dialog&gt;</pre>
<p>As you can see, codeDialog.xul is very simple and contains only three elements inside a vbox. This is really one of the simplest examples you could use and was chosen to illustrate how to simply and easily pass information into and out of a dialog</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ashita.org/passing-parameters-into-a-created-dialog-and-retrieving-them-on-exit/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Dynamically Generated and Updated Table</title>
		<link>http://www.ashita.org/dynamically-generated-and-updated-table/</link>
		<comments>http://www.ashita.org/dynamically-generated-and-updated-table/#comments</comments>
		<pubDate>Thu, 14 Aug 2008 00:21:09 +0000</pubDate>
		<dc:creator>Jon</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Dynamic]]></category>
		<category><![CDATA[Opacity]]></category>
		<category><![CDATA[Positioning]]></category>
		<category><![CDATA[Table]]></category>

		<guid isPermaLink="false">http://ashita.org/?p=12</guid>
		<description><![CDATA[Although the page itself is pretty bare bones, the script itself is even simpler.  The bandanna guide is another piece I wrote to accompany the game Pirate Quest. This article attempts to demonstrate how we can use dynamically generated DOM objects to update table data on the fly.  In this case it&#8217;s fairly simple as [...]]]></description>
			<content:encoded><![CDATA[<p>Although the page itself is pretty bare bones, the script itself is even simpler.  The <a href="http://pq.ashita.org/bandannaguide.php">bandanna guide</a> is another piece I wrote to accompany the game <a href="http://www.piratequest.net/index.php?r=60051 ">Pirate Quest</a>.</p>
<p>This article attempts to demonstrate how we can use dynamically generated DOM objects to update table data on the fly.  In this case it&#8217;s fairly simple as only one value is changing and we&#8217;re only changing the cell text. There are some other ideas demonstrated here, such as using opacity and alternating row styles to create a colourful and easy to read table.</p>
<p>The following is the table we&#8217;ll be updating. It&#8217;s pretty simple &#8211; just the column headings.  <span style="color: #ff0000;">EDIT: added thead and tbody tags. IE would append rows to the table unless they were in the tbody tag.</span></p>
<pre id="line175">&lt;table id="tbl_guide" border="1"&gt;
	&lt;thead&gt;
		&lt;tr&gt;
			&lt;td rowspan="2"&gt;Level&lt;/td&gt;
			&lt;td rowspan="2"&gt;Energy&lt;/td&gt;
			&lt;td colspan="2"&gt;No Bandanna&lt;/td&gt;
			&lt;td colspan="2"&gt;Bandanna of Vigor&lt;/td&gt;
			&lt;td colspan="2"&gt;Bandanna of Vitality&lt;/td&gt;
			&lt;td colspan="2"&gt;Bafunda de la Cabeza&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;min&lt;/td&gt;
			&lt;td&gt;max&lt;/td&gt;
			&lt;td&gt;min&lt;/td&gt;
			&lt;td&gt;max&lt;/td&gt;
			&lt;td&gt;min&lt;/td&gt;
			&lt;td&gt;max&lt;/td&gt;
			&lt;td&gt;min&lt;/td&gt;
			&lt;td&gt;max&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody id="tbl_body"/&gt;
&lt;/table&gt;</pre>
<p>You can use whatever you want to start the update process. In this case I used the onchange event on a drop down list</p>
<pre>&lt;<span class="start-tag">select</span><span class="attribute-name"> id</span>=<span class="attribute-value">"hideout" </span><span class="attribute-name">onchange</span>=<span class="attribute-value">"update(Number(this.options[this.selectedIndex].value));"</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"100"</span>&gt;homeless (100)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"105"</span>&gt;Wretched Alcove (105)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"110"</span>&gt;Abandoned Outhouse (110)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"115"</span>&gt;Festering Swamp (115)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"120"</span>&gt;Swamp with a View (120)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"130"</span>&gt;Desolate Beach (130)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"140"</span>&gt;Rundown Shanty (140)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"150"</span>&gt;Rusted Roof Shack (150)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"160"</span>&gt;Shanty with a Fence (160)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"170"</span>&gt;Deserted Manor (170)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"180"</span>&gt;Ruined Castle (180)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"185"</span>&gt;Rundown Castle (185)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"190"</span>&gt;Stronghold (190)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"195"</span>&gt;Fortified Stronghold (195)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"200"</span>&gt;Shack on Skull Island (200)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"220"</span>&gt;Cavern on Skull Island (220)&lt;/<span class="end-tag">option</span>&gt;
  &lt;<span class="start-tag">option</span><span class="attribute-name"> value</span>=<span class="attribute-value">"230"</span>&gt;Stronghold on Skull Island (230)&lt;/<span class="end-tag">option</span>&gt;
&lt;/<span class="end-tag">select&gt;

</span></pre>
<p>Next, on to the script itself. First we define the number of rows and columns, and we create a 2D array for our cells.</p>
<pre>//2D array of table cells
var cells = new Array();

var numcols = 10;
var numrows = 600;</pre>
<p>I used the body onload event to set up the table rows. <span style="color: #ff0000;">EDIT: Because IE doesn&#8217;t seem to recognize a class or style change made with setAttribute(), I had to fall back on an alternative</span></p>
<pre>function onLoad() {
	//get our table and our select box
	var table = document.getElementById("tbl_guide");
	var select = document.getElementById("hideout");
	var row; //tr DOM object
	var cell; //td DOM object
	var celltext; //createTextNode DOM object
	var row_arr; //array of cells for each row
	//for the opacity overlay we use three divs. one on the outside, one for the
	//background color and one for the text
	var out_div, in_div1, in_div2; 

	//loop through the number of rows we want
	for (var i = 0; i&lt;numrows; i++) {

		//create this row and set the style for even or odd.
		row = document.createElement("tr");
		row.setAttribute("class",(i%2 == 0)? "even":"odd");
		row.className = (i%2 == 0)? "even":"odd"; //for IE

		//get a new, clean array to work with
		row_arr = new Array();

		//loop through each cell for the number of columns we have
		for (var j=0; j&lt;numcols;j++) {

			//create our table cell and div arrangement for our opacity trick
			cell = document.createElement("td");
			out_div = document.createElement("div");
			in_div1 = document.createElement("div");
			in_div2 = document.createElement("div");

			//set the styles for the div objects
			out_div.setAttribute("class","outer");
			in_div2.setAttribute("class","text");
			in_div1.setAttribute("class","bg");

			//for IE (up to 7) since it appears to lack proper support for setAttribute
			out_div.className = "outer";
			in_div1.className = "bg";
			in_div2.className = "text";

			//depending on what cell we're in we should do different things. mostly this affects the styles
			switch(j) {
				case 0:
					//level
					celltext = document.createTextNode(String(i+1));
					in_div1.setAttribute("style","background-color:yellow;");
					in_div1.style.background = "yellow"; //for IE again
					break;
				case 1:
					//Energy
					celltext = document.createTextNode(String(i+10));
					in_div1.setAttribute("style","background-color:yellow;");
					in_div1.style.background = "yellow";
					break;
				case 2:
					celltext = document.createTextNode("");
					in_div1.setAttribute("style","background-color:red;");
					in_div1.style.background = "red";
					break;
				case 3:
					celltext = document.createTextNode("");
					in_div1.setAttribute("style","background-color:red;");
					in_div1.style.background = "red";
					break;
				case 4:
					celltext = document.createTextNode("");
					in_div1.setAttribute("style","background-color:blue;");
					in_div1.style.background = "blue";
					break;
				case 5:
					celltext = document.createTextNode("");
					in_div1.setAttribute("style","background-color:blue;");
					in_div1.style.background = "blue";
					break;
				case 6:
					celltext = document.createTextNode("");
					in_div1.setAttribute("style","background-color:green;");
					in_div1.style.background = "green";
					break;
				case 7:
					celltext = document.createTextNode("");
					in_div1.setAttribute("style","background-color:green;");
					in_div1.style.background = "green";
					break;
				case 8:
					celltext = document.createTextNode("");
					in_div1.setAttribute("style","background-color:purple;");
					in_div1.style.background = "purple";
					break;
				case 9:
					celltext = document.createTextNode("");
					in_div1.setAttribute("style","background-color:purple;");
					in_div1.style.background = "purple";
					break;
			}

			//add our text to the second inner div
			in_div2.appendChild(celltext);

			//append the two inner divs to the outer div, then append the outer div to the cell
			out_div.appendChild(in_div1);
			out_div.appendChild(in_div2);
			cell.appendChild(out_div);

			//append the cell to the row
			row.appendChild(cell);

			/* finally add this celltext to the row array.
			 * NOTE: you could just as easily append one of the divs or the td tag. In this case
			 * I'm only changing the text. If you wanted to change the colors, for example, you'd
			 * need to push in_div1 onto the array. To change both the color and the text\, you'd
			 * need to push out_div onto the array and later access the children
			 */
			row_arr.push(celltext);
		}

		//add the row to the table, and push the row array onto our 2d cell array
		table.appendChild(row);
		cells.push(row_arr);
	}
	/* then update the values. The operation performed in update() could have been included
	 * in the switch-case above, but then if I changed it, I'd need to change it in two places.
	 * Casts the value from the select box to Number. for *, / , etc. the value is interpreted as
	 * a number anyways, but for +, it assumes it's a string value.... so we have to cast it.
	 */
	update(Number(select.options[select.selectedIndex].value));
}</pre>
<p>The onLoad function only assigns values to level and energy.  Hopefully the comments in the code are clear enough to see what I&#8217;ve done.</p>
<p>Next up, the update function</p>
<pre>function update(value) {
	//loop through each row
	for (var i = 0; i&lt;numrows; i++) {
		//loop through each cell in a row but ignore the first two
		//(values were set up in the onLoad and don't change now)
		for (var j=2; j&lt;numcols;j++) {
			//again switch-case, this time for the different formulas in each cell
			switch(j) {
				case 2:
					//no bandanna min
					cells[i][j].nodeValue = tp((value/150) * ((i+10)/20));
					break;
				case 3:
					//no bandanna max
					cells[i][j].nodeValue = tp((value/75) * ((i+10)/20));
					break;
				case 4:
					//vigor min
					cells[i][j].nodeValue = tp((value/150) * ((i+20)/20));
					break;
				case 5:
					//vigor max
					cells[i][j].nodeValue = tp((value/75) * ((i+20)/20));
					break;
				case 6:
					//vitality min
					cells[i][j].nodeValue = tp(((value + 20)/150) * ((i+10)/20));
					break;
				case 7:
					//vitality max
					cells[i][j].nodeValue = tp(((value + 20)/75) * ((i+10)/20));
					break;
				case 8:
					//bafunda min
					cells[i][j].nodeValue = tp(((value + 25)/150) * ((i+25)/20));
					break;
				case 9:
					//bafunda max
					cells[i][j].nodeValue = tp(((value + 25)/75) * ((i+25)/20));
					break;
			}
		}
	}
}</pre>
<p>The update function, as you can see, is very simple. we use .nodeValue to change the text content of our text nodes. As noted in the comments of the onLoad, you could also use the cell itself or one of the containing divs. Your cases would look more like <code>cells[i][j].childNodes[1].childNodes[0].nodeValue</code> if you used <code>out_div</code> in your cells array.</p>
<p>I suppose the last thing to look at is the style section.</p>
<pre>table { border-collapse:collapse; border-width:3px; border-style:double; border-color:black; }
td { border-color:black; border-width:1px; }
thead tr td {  padding-left:.5em; }
tbody tr td { padding: 0px 0px 0px 0px; height:1em; width:5em; }
div.outer { position:relative;}
div.bg { opacity: 0.3; height:1em; filter: alpha(opacity=30); padding: 5px 10px 5px 10px; }
div.text { position: absolute; top: 0; bottom: 0; color: black; padding: 5px 10px 5px 10px; }
tbody tr.even { background-color:#d0d0d0; }
tbody tr.odd { background-color:#ffffff; }</pre>
<p>It&#8217;s pretty short. True, I could have done more to pretty up the page.. and I may yet. but for now, it works well enough and demonstrates the dynamic generation and update technique.</p>
<p>As you can see the code is far from complicated and this would have been far messier in the old pre-DOM days *shudder*.</p>
<p><span style="color: #ff0000;"><br />
</span></p>
<p><span style="color: #ff0000;">EDIT: Also, please note that in IE the page is so slow to generate and update that I develop a whole new loathing for Ie every time I open it. In firefox, the generation takes a little time, but not too bad. The updating in Firefox is quite quick. For a small set of rows, IE is fine&#8230; 600 rows seemsto kill it though.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ashita.org/dynamically-generated-and-updated-table/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Pirate Questing</title>
		<link>http://www.ashita.org/pirate-questing/</link>
		<comments>http://www.ashita.org/pirate-questing/#comments</comments>
		<pubDate>Wed, 13 Aug 2008 05:24:58 +0000</pubDate>
		<dc:creator>Jon</dc:creator>
				<category><![CDATA[DOM]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Pirate Questing]]></category>
		<category><![CDATA[XUL]]></category>

		<guid isPermaLink="false">http://ashita.org/?p=3</guid>
		<description><![CDATA[Pirate Questing is a firefox addon thatI&#8217;ve been devloping for a while. It&#8217;s available at AMO here I&#8217;ll mostly be using this space to document interesting solutions I come across.]]></description>
			<content:encoded><![CDATA[<p>Pirate Questing is a firefox addon thatI&#8217;ve been devloping for a while. It&#8217;s available at AMO <a href="http://addons.mozilla.org/en-US/firefox/addon/6801">here</a></p>
<p>I&#8217;ll mostly be using this space to document interesting solutions I come across.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ashita.org/pirate-questing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

