<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;A08NQXo5fip7ImA9WxFaGEw.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728</id><updated>2010-07-22T10:31:30.426-07:00</updated><title>TECHHEAD Development Blog</title><subtitle type="html">Mostly about programming and web development.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://devblog.techhead.biz/" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>16</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/TECHHEADDevelopmentBlog" /><feedburner:info uri="techheaddevelopmentblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;Ak8MRXs-eSp7ImA9WxJTGEo.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-8108819513345019914</id><published>2009-04-27T17:34:00.000-07:00</published><updated>2009-04-27T17:34:44.551-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-27T17:34:44.551-07:00</app:edited><title>Google Voice Click-to-call Widget</title><content type="html">&lt;p&gt;I'll keep this short. I was lucky enough to get in on the Google Voice closed beta (back when it was Grand Central). It offers a free click-to-call widget that you can embed in your web pages. But it didn't offer quite enough "pizzaz" for my taste, so I enhanced it a bit using some Javascript. I'm making the &lt;a href="http://code.google.com/p/blogcode/source/browse/trunk/click2call/click2call.js" target="_blank"&gt;code&lt;/a&gt; freely available. (It should be an interesting read.)&lt;/p&gt;&lt;p&gt;It works in IE 6 through 8 as well as Firefox 3 and Safari 3. I didn't test it in anything else. To see it in action, use one of the aforementioned browsers and go to &lt;a href="http://techhead.biz" target="_blank"&gt;http://techhead.biz&lt;/a&gt;.&lt;p&gt;&lt;p&gt;Feel free to use it, improve it, etc. As always, a little credit here would be appreciated. If you do use it, please leave a comment here and drop a link so I can find you.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-8108819513345019914?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/P8Ly7Y6iXEA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/8108819513345019914/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2009/04/google-voice-click-to-call-widget.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/8108819513345019914?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/8108819513345019914?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/P8Ly7Y6iXEA/google-voice-click-to-call-widget.html" title="Google Voice Click-to-call Widget" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>1</thr:total><feedburner:origLink>http://devblog.techhead.biz/2009/04/google-voice-click-to-call-widget.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUFQ3c7fCp7ImA9WxJTFU8.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-4577625471857357392</id><published>2009-04-23T15:30:00.000-07:00</published><updated>2009-04-23T15:36:52.904-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-23T15:36:52.904-07:00</app:edited><title>DOMContentLoaded and ondocumentready and onreadystatechange! Oh my!</title><content type="html">&lt;p&gt;How do you determine when your document is ready to be manipulated by the javascript in your web application? In the course of a recent project, I discovered that the answer is perhaps not so simple as the question. In fact, the conclusion I've come to is that "it depends".&lt;/p&gt;&lt;p&gt;The most elegant solution I've come across (in my opinion) is the &lt;code&gt;DOMContentLoaded&lt;/code&gt; event. This event has been hidden in Mozilla browsers since I don't know when (???) but has now been adopted in recent versions of WebKit and Opera as well. As the name suggests, this event fires when the document tree (DOM) is completely loaded. This may fire before images and other external objects are loaded. The only problem is that IE 6, 7 and 8 don't support it, so there goes the market share. The rest of this article is about various "hacks" which attempt to emulate this behavior in IE.&lt;/p&gt;&lt;p&gt;The current most popular workaround (and newest I believe) is a &lt;a href="http://javascript.nwbox.com/IEContentLoaded/" target="_blank"&gt;"hack"&lt;/a&gt; discovered by &lt;a href="http://javascript.nwbox.com/"&gt;Diego Perini&lt;/a&gt;. It is based on the &lt;code&gt;ondocumentready&lt;/code&gt; event that is available only to Behaviors in IE. Diego discovered a paragraph in an &lt;a href="http://msdn.microsoft.com/en-us/library/ms531426(VS.85).aspx" target="_blank"&gt;MSDN document&lt;/a&gt; and ran with it.&lt;/p&gt;&lt;blockquote&gt;A few methods, such as &lt;a href="http://msdn.microsoft.com/en-us/library/ms536414(VS.85).aspx" target="_blank"&gt;doScroll&lt;/a&gt;, require the primary document to be completely loaded. If these methods are part of an initialization function, they should be handled when the &lt;a href="http://msdn.microsoft.com/en-us/library/ms531024(VS.85).aspx" target="_blank"&gt;ondocumentready&lt;/a&gt; event fires. &lt;/blockquote&gt;&lt;p&gt;Taking the reverse of this statement, Diego tried polling &lt;code&gt;doScroll&lt;/code&gt; until there were no more errors as a means to achieve a "poor man's" &lt;code&gt;ondocumentready&lt;/code&gt;. And guess what? It works! ...Sort of. If the loading document's window is not top level (ie. if in an iframe), &lt;code&gt;doScroll&lt;/code&gt; never errors and the hack falls apart.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;// Should return true only if the document is ready, false otherwise
// Works unless in an IFRAME
function documentready() {
  try {
    window.doScroll('top');
    return true;
  } catch (e) {
    return false;
  }
}

function init() {
}

// Poll until documentready
(function() {
  if (documentready()) return init();
  setTimeout(arguments.callee, 0);
})();

&lt;/pre&gt;&lt;p&gt;Another popular method of &lt;code&gt;DOMContentLoaded&lt;/code&gt; emulation in IE is the &lt;a href="http://dean.edwards.name/weblog/2005/09/busted/" target="_blank"&gt;deferred SCRIPT method&lt;/a&gt; made popular by &lt;a href="http://dean.edwards.name/" target="_blank"&gt;Dean Edwards&lt;/a&gt;.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;function firedomload() {
}

// A deferred, external script is executed after the DOM is available in IE.
// I know of no formal specification for this behavior.
// However, it appears consistent across IE 6 through 8.
// MUST use a document.write to emit the SCRIPT (if being placed dynamically)
//   or readyState never reaches 'complete'.
//   (I don't know why, but that's just the way it is.)
document.write('&lt;' + 'SCRIPT src="//:" defer&gt;&lt;' + '/SCRIPT&gt;');
var script = document.documentElement.lastChild.lastChild;
script.onreadystatechange = function() {
  if (this.readyState == 'complete') {
    this.onreadystatechange = null;
    this.parentNode.removeChild(this);
    firedomload();
  }
};
&lt;/pre&gt;&lt;p&gt;The problem with this method is, of course, is that it requires a call to &lt;code&gt;document.write&lt;/code&gt; which will obliterate the current document if called too late.&lt;/p&gt;&lt;p&gt;Dean also shows us how to take advantage of the &lt;code&gt;ondocumentready&lt;/code&gt; event directly, but &lt;a href="http://dean.edwards.name/weblog/2005/09/busted2/" target="_blank"&gt;this method&lt;/a&gt; requires an external HTC Behavior file, making it less friendly for inclusion within libraries.&lt;/p&gt;&lt;p&gt;Lastly is the most obvious option. Place a script after all of the content in the BODY of your document and use it to bootstrap the initialization calls.&lt;/p&gt;&lt;pre class="prettyprint html code"&gt;&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;script type="text/javascript"&amp;gt;
if (typeof ondomload == 'undefined') ondomload = [];
ondomload.push(function() {
  alert('This will execute on DOM load');
});
&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
... some content ...
&amp;lt;script src="firedomload.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;p&gt;And the &lt;a href="http://code.google.com/p/blogcode/source/browse/trunk/domload/firedomload.js" target="_blank"&gt;firedomload.js&lt;/a&gt; script looks like this...&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;/**
 * This SCRIPT should be placed just before the close of the BODY element
 * in your (X)HTML document. It may be deferred.
 *
 * Scripts that take advantage of 'ondomload' may come before or after
 * this SCRIPT and may be either deferred or not deferred.
 *
 * USAGE:
 * if (typeof ondomload == 'undefined') ondomload = [];
 * ondomload.push(function() {
 *   alert('This will execute on DOM load');
 * });
 */
if (typeof ondomload == 'undefined') {
  ondomload = {};
} else {
  while (ondomload.length)
    setTimeout(ondomload.shift(), 0);
}
ondomload.push = function(cb) { return cb() };
&lt;/pre&gt;&lt;p&gt;In summary, each method has its pros and cons. Even the library authors can't agree on what is best. At the time of this writing, jQuery uses the &lt;code&gt;doScroll&lt;/code&gt; method and Prototype uses the deferred SCRIPT method. I've written a &lt;a href="http://code.google.com/p/blogcode/source/browse/trunk/domload/ondomload.js" target="_blank"&gt;small function using the deferred SCRIPT method&lt;/a&gt;. You can find it &lt;a href="http://code.google.com/p/blogcode/source/browse/trunk/domload/ondomload.js" target="_blank"&gt;here&lt;/a&gt;. The source code for the tests is also available &lt;a href="http://code.google.com/p/blogcode/source/browse/#svn/trunk/domload" target="_blank"&gt;here&lt;/a&gt;. And there is a live test &lt;a href="http://techhead.biz/domload/test.php"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;What you use may depend on your needs.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-4577625471857357392?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/15EFmmCp5tc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/4577625471857357392/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2009/04/domcontentloaded-ondocumentready.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/4577625471857357392?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/4577625471857357392?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/15EFmmCp5tc/domcontentloaded-ondocumentready.html" title="DOMContentLoaded and ondocumentready and onreadystatechange! Oh my!" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>0</thr:total><feedburner:origLink>http://devblog.techhead.biz/2009/04/domcontentloaded-ondocumentready.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UBQHcyfip7ImA9WxVaFks.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-5775273445094315411</id><published>2009-04-13T16:23:00.000-07:00</published><updated>2009-04-13T16:27:31.996-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-13T16:27:31.996-07:00</app:edited><title>Running IE6, IE7 and IE8 on your Mac (reloaded)</title><content type="html">&lt;p&gt;The original article is here: &lt;a href="http://blog.mozmonkey.com/2008/vpc-ie6-ie7-ie8-on-mac-os-x/" target="_blank"&gt;http://blog.mozmonkey.com/2008/vpc-ie6-ie7-ie8-on-mac-os-x/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I came across the above article a while ago when looking for a good way to test my web sites in Internet Explorer without having to resort to using a PC. Microsoft releases Virtual PC images of Windows containing various versions of the Internet Explorer web browser. These expire and are re-released periodically. At the time of this writing, they are about to expire again. I do hope that Microsoft will continue this valuable service. (It's the least they can do.) You can download the images here: &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=21EABB90-958F-4B64-B5F1-73D0A413C8EF" target="_blank"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyId=21EABB90-958F-4B64-B5F1-73D0A413C8EF&lt;/a&gt;&lt;/p&gt;&lt;p&gt;If you are using Windows, then you may download the free Virtual PC from Microsoft. Otherwise, download the free, open source &lt;a href="http://www.virtualbox.org/wiki/Downloads" target="_blank"&gt;VirtualBox&lt;/a&gt;. At the time of the article noted above, it was necessary to first convert the Virtual PC images before they could be used on VirtualBox. This is no longer the case.&lt;/p&gt;&lt;p&gt;The Virtual PC images available from Microsoft come packed in self-expanding archive files. This is a small problem if on a Mac. You cannot run the self expander, but I find that the free &lt;a href="http://my.smithmicro.com/mac/stuffit/expander.html" target="_blank"&gt;Stuffit Expander&lt;/a&gt; works fine to extract the image file.&lt;/p&gt;&lt;p&gt;Once you set up your virtual machine, Windows will boot, show you the EULA and attempt (and fail) to install a bunch of "new hardware". Just skip past all of this and then choose "Devices -&gt; Install Guest Additions..." from the menu bar. This allows better integration with your system. It also makes folder sharing with your Mac possible.&lt;/p&gt;&lt;p&gt;Of all those hardware installation dialogs you clicked past earlier, one of them was to install a network device. Without this, you can't access the internet. At the time of this writing, VirtualBox emulates an AMD PCnet-FAST III NIC by default. You will need to download the driver for it &lt;a href="http://www.amd.com/us-en/assets/content_type/utilities/V4.51.zip" target="_blank"&gt;here&lt;/a&gt;. Then you'll need to setup a shared folder and put the driver in it so that you may install the driver from Windows.&lt;/p&gt;&lt;p&gt;If you're a more visual person, just watch the video &lt;a href="http://www.screencast.com/t/HuL0DG7X" target="_blank"&gt;here&lt;/a&gt; (or inline below).&lt;/p&gt;&lt;object width="700" height="525"&gt; &lt;param name="movie" value="http://content.screencast.com/users/techheadinfo/folders/Jing/media/3c8eff57-9dc3-420d-ac5c-854a295bfee8/jingswfplayer.swf"&gt;&lt;/param&gt;&lt;param name="quality" value="high"&gt;&lt;/param&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;/param&gt;&lt;param name="flashVars" value="thumb=http://content.screencast.com/users/techheadinfo/folders/Jing/media/3c8eff57-9dc3-420d-ac5c-854a295bfee8/FirstFrame.jpg&amp;containerwidth=800&amp;containerheight=600&amp;loaderstyle=jing&amp;content=http://content.screencast.com/users/techheadinfo/folders/Jing/media/3c8eff57-9dc3-420d-ac5c-854a295bfee8/00000002.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="scale" value="showall"&gt;&lt;/param&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt;&lt;param name="base" value="http://content.screencast.com/users/techheadinfo/folders/Jing/media/3c8eff57-9dc3-420d-ac5c-854a295bfee8/"&gt;&lt;/param&gt;&lt;embed src="http://content.screencast.com/users/techheadinfo/folders/Jing/media/3c8eff57-9dc3-420d-ac5c-854a295bfee8/jingswfplayer.swf" quality="high" bgcolor="#FFFFFF" width="700" height="525" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/users/techheadinfo/folders/Jing/media/3c8eff57-9dc3-420d-ac5c-854a295bfee8/FirstFrame.jpg&amp;containerwidth=800&amp;containerheight=600&amp;loaderstyle=jing&amp;content=http://content.screencast.com/users/techheadinfo/folders/Jing/media/3c8eff57-9dc3-420d-ac5c-854a295bfee8/00000002.swf" allowFullScreen="true" base="http://content.screencast.com/users/techheadinfo/folders/Jing/media/3c8eff57-9dc3-420d-ac5c-854a295bfee8/" scale="showall"&gt;&lt;/embed&gt; &lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-5775273445094315411?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/ZI_-ZhWBSyU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/5775273445094315411/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2009/04/running-ie6-ie7-and-ie8-on-your-mac.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/5775273445094315411?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/5775273445094315411?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/ZI_-ZhWBSyU/running-ie6-ie7-and-ie8-on-your-mac.html" title="Running IE6, IE7 and IE8 on your Mac (reloaded)" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>1</thr:total><feedburner:origLink>http://devblog.techhead.biz/2009/04/running-ie6-ie7-and-ie8-on-your-mac.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUFQnY8cSp7ImA9WxVaE0w.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-2038431134562851458</id><published>2009-04-09T14:40:00.000-07:00</published><updated>2009-04-09T14:40:13.879-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-09T14:40:13.879-07:00</app:edited><title>Google App Engine is available for Java developers</title><content type="html">&lt;p&gt;I'm sure that you've heard &lt;a href="http://googleappengine.blogspot.com/2009/04/seriously-this-time-new-language-on-app.html" target="_blank"&gt;the news&lt;/a&gt; by now, but I couldn't let it pass without a comment. Hooray!&lt;/p&gt;&lt;p&gt;I am a Java developer. That is to say, Java is the language I have done most of my development in over the past 10 years. But my interest lately has been less in Java actual and more in the JVM and all the &lt;a href="http://groovy.codehaus.org/" target="_blank"&gt;Groovy&lt;/a&gt; new languages you can get to run on it.&lt;/p&gt;&lt;p&gt;That's why I'm particularly excited that the App Engine will support such alternate languages. I was lucky enough be get in on the developer preview, so you can expect to see me posting more on this topic in the new few weeks.&lt;/p&gt;&lt;p&gt;Stay tuned.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-2038431134562851458?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/iyILs7HmcKE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/2038431134562851458/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2009/04/google-app-engine-is-available-for-java.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/2038431134562851458?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/2038431134562851458?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/iyILs7HmcKE/google-app-engine-is-available-for-java.html" title="Google App Engine is available for Java developers" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>0</thr:total><feedburner:origLink>http://devblog.techhead.biz/2009/04/google-app-engine-is-available-for-java.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0AMSXsyfCp7ImA9WxVbGUs.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-7781473614484740816</id><published>2009-04-04T02:06:00.000-07:00</published><updated>2009-04-05T14:09:48.594-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-05T14:09:48.594-07:00</app:edited><title>Prototype-based programming in Javascript (part 2)</title><content type="html">&lt;p&gt;This is part 2 of the subject. For a primer on prototype-based inheritance in Javascript, see the &lt;a href="http://devblog.techhead.biz/2009/04/prototype-based-programming-in.html"&gt;previous article&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Javascript is a prototype-based language, but sometimes it pretends not to be. Constructors, types, the &lt;code&gt;new&lt;/code&gt; and &lt;code&gt;instanceof&lt;/code&gt; operators -- these are all an additional layer built on top of the core model. And they make it a little difficult to tell what is really going on... So we're going to take them out of the picture. Here's a summary of the last article in SpiderMonkey Javascript.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;// Prototype inheritance
A = { foo: true }; // new A
B = {}; // new B
B.__proto__ = A; // If a property is not found in B, look in A
alert(B.foo); // true
B.foo = false;
alert(A.foo); // still true

// the 'new' operator can be reproduced in SpiderMonkey Javascript
function nuevo (constructor) {
  var newObject = {}; // new object with its own properties
  newObject.constructor = constructor; // this is the new object 'type'
  newObject.__proto__ = constructor.prototype; // desired prototype obtained here
  // call the constructor on the newly created object
  constructor.apply(newObject, Array.prototype.slice.call(arguments, 1));
  return newObject;
}
&lt;/pre&gt;&lt;p&gt;Ok, so now that you know how prototype inheritance works, lets make it a little easier to use. There are already many good libraries that make "classical" or class-based inheritance easier in Javascript. (My favorite is the &lt;a href="http://ejohn.org/blog/simple-javascript-inheritance/" target="_blank"&gt;simple one&lt;/a&gt; provided by John Resig on his blog.) But I'm not yet aware (I'm sure you'll help me here) of any that make prototype-based programming simpler. Douglas Crockford, Javascript god, has a &lt;a href="http://javascript.crockford.com/prototypal.html" target="_blank"&gt;simple function&lt;/a&gt; posted on his site. We'll start with that.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;Object.create = function (o) {
  function F() {}
  F.prototype = o;
  return new F();
};
&lt;/pre&gt;&lt;p&gt;You should know by now what this is doing. The constructor function &lt;code&gt;F&lt;/code&gt; is necessary because there is no universal way to set a prototype chain directly, other than specifying it on a constructor. The type &lt;code&gt;F&lt;/code&gt; is a throwaway. You don't need it anymore. You won't be using the &lt;code&gt;new&lt;/code&gt; operator, and the &lt;code&gt;instanceof&lt;/code&gt; operator makes no sense for pure prototype-based programming anyway. (Instead, you would use the &lt;code&gt;&lt;a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/isPrototypeOf" target="_blank"&gt;Object.prototype.isPrototypeOf&lt;/a&gt;&lt;/code&gt; method found on every object.)&lt;/p&gt;&lt;p&gt;Using Crockford's function, our first code example now looks like this.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;// Prototype inheritance
A = { foo: true }; // new A
B = Object.create(A); // new B
&lt;/pre&gt;&lt;p&gt;Pretty simple, and it's &lt;em&gt;almost&lt;/em&gt; all you need. But I find that in practice, some additional features are useful. Here's a first iteration of my version.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;var Proto = {

  __proto__: Object.prototype,

  clone: function(init) {
    var Clone = function(init) {
      this.__proto__ = Clone.prototype;
      this.constructor = Clone;
      if (init) this.assign(init);
    }
    Clone.prototype = this;
    return new Clone(init);
  },
  
  assign: function(props) {
    for (var key in props) {
      var value = props[key];
      if (this[key] != value)
        this[key] = value;
    }
    return this;
  }
  
}
&lt;/pre&gt;&lt;p&gt;There's not a whole lot of difference between my own and Crockford's here besides naming, but there are some significant things going on. For one, Crockford attaches his function as a property of the &lt;code&gt;Object&lt;/code&gt; constructor. This makes perfect sense, unless you consider that the whole reason he scrapped his first iteration (in which the function was simply named &lt;code&gt;object&lt;/code&gt;) was that "globals are clearly problematic". But you actually have all the same problems (namespace issues, etc) here.&lt;/p&gt;&lt;p&gt;On another of his iterations, he attached the method &lt;code&gt;begetObject&lt;/code&gt; to the &lt;code&gt;Object.prototype&lt;/code&gt;. The problem here is that adding anything to &lt;code&gt;Object.prototype&lt;/code&gt; will cause it to be inherited by every single object in the global namespace, whether or not it's actually part of &lt;em&gt;your&lt;/em&gt; program. I made a compromise and added my &lt;code&gt;clone&lt;/code&gt; method to the prototype of the &lt;code&gt;Proto&lt;/code&gt; object. So only objects which inherit from &lt;code&gt;Proto&lt;/code&gt; will be affected. Of course, there are still no guarantees that other code in the global namespace will not interact with the name &lt;code&gt;Proto&lt;/code&gt;, but you can name this whatever you will (eg. &lt;code&gt;biz$techhead$Proto&lt;/code&gt; if you like). &lt;/p&gt;&lt;p&gt;Another thing you'll notice about my "improvements" is that I explicitly set the &lt;code&gt;__proto__&lt;/code&gt; property of the new object. The &lt;code&gt;__proto__&lt;/code&gt; property really only means anything in Mozilla's Javascript, and I simply set it to what it was already. The reason I set it is because it is a useful relationship to preserve, and now I have read access to it even in Internet Explorer. I also set the &lt;code&gt;constructor&lt;/code&gt; property for the sake of correctness.&lt;/p&gt;&lt;p&gt;Lastly, you'll notice that I added an optional initializer to assign properties to the newly constructed object. This is merely a shortcut.&lt;/p&gt;&lt;p&gt;But I'm not quite done. For one, it is useful on occasion, even when using prototypes, to be able to call a method on a super prototype. A naive attempt and its correction is shown below.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;A a = Proto.clone({
  create: function(name) { return this.clone({ name: name }) }
});

B b = A.clone({
  create: function(name, gender) {
    // this may look right at first glance
    // but will quite often end up in an endless loop
    // see if you can figure out why
    // var o = this.__proto__.create.call(this, name);
    // instead, this is correct
    var o = A.create.call(this, name);
    o.gender = gender;
    return o;
  }
});
&lt;/pre&gt;&lt;p&gt;But I don't really like having to refer to the super prototype by name. If I decide to change the name from A to something else, I've got to change B also. Not a disaster but it is still annoying. So I provided a way to access the super prototype through a generic name.&lt;/p&gt;&lt;p&gt;A bigger issue I've found is that sometimes a prototype needs to be able to control exactly how it is "copied". Sure, it could override the &lt;code&gt;clone&lt;/code&gt; method each time, but that is a lot of extra work for a common task, so I set up an event instead. Behold the next iteration.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;var Proto = {

  __proto__: Object.prototype,

  clone: function(init) {
    var Clone = function(init) {
      this.__proto__ = Clone.prototype;
      this.constructor = Clone;
      this.onclone();
      if (init) init.call(this, this.__proto__);
    }
    Clone.prototype = this;
    return new Clone(init);
  },
  
  onclone: function() {}
  
}
&lt;/pre&gt;&lt;p&gt;Notice that on my last iteration, you could provide an object to the &lt;code&gt;clone&lt;/code&gt; method and it would copy its properties onto the new object. In this iteration, you may provide an initialization function (much like a constructor) to set up the new object. This provides a couple of new advantages. See the example below.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;Animal = Proto.clone(function() {
  this.eat = function(food) {}
  this.sleep = function() {}
  this.poop = function() {}
  this.breed = function(animal) {}
});

Human = Animal.clone(function(_super) {
  var ate = [];  // now I get a new private scope
  this.eat = function(betterfood) {
    _super.eat.call(this, betterfood); // can use _super instead of Animal
    // do something else
    ate.push(betterfood);
    // sorry about the lame example
  }
});
&lt;/pre&gt;&lt;p&gt;So, with the latest and greatest iteration, I get access to a &lt;code&gt;_super&lt;/code&gt; keyword and the ability to easily add private members to an object. But wait! The private member &lt;code&gt;ate&lt;/code&gt; is now shared by all humankind. This is probably not what the programmer had in mind. Instead, this probably was...&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;Human = Animal.clone(function(_super) {
  var init = function() {
    var ate = [];  // now I get a new private scope
    this.eat = function(betterfood) {
      _super.eat.call(this, betterfood);
      ate.push(betterfood);
    };
  };
  this.onclone = function() {
    _super.onclone.call(this);
    init();
  };
  init();
});
&lt;/pre&gt;&lt;p&gt;Now each Human keeps his own menu to himself. But that's a lot of extra typing for something that should be simple, so I'll add one last bit of magic...&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;/**
 * The prototype of all objects in this small
 * prototype framework.
 */
var biz$techhead$Proto = {

  __proto__: Object.prototype,

  /**
   * Clone this object and (optionally) invoke an initializer.
   * Should NOT be overriden.
   * Override 'onclone' instead.
   */
  clone: function(init) {
    var Clone = function(init) {
      this.__proto__ = Clone.prototype;
      this.constructor = Clone;
      this.onclone();
      if (init) {
        if (init instanceof Function)
          this.init(init);
        else
          this.assign(init);
      }
    }
    Clone.prototype = this;
    return new Clone(init);
  },
  
  /**
   * This event fires on the new child of this object
   * whenever 'clone' is called.
   * It is analagous to a constructor.
   */
  onclone: function() {},
  
  /**
   * Invokes an initializer function on this object.
   * It supplies this object's super prototype as the
   * first argument, and provides an optional second
   * argument to those initializers that declare
   * two or more parameters. The second argument is a
   * function that will install the initializer 'onclone'
   * when invoked.
   */
  init: function(init) {
    var _this = this,
        _super = this.__proto__;
    if (init.length &gt; 1) {
      init.call(this, _super,
        function() {
          var hasonclone = _this.hasOwnProperty('onclone'),
              onclone = _this.onclone;
          _this.onclone = function() {
            var _this = this;
            var f = hasonclone ?
              function() { onclone.call(_this) } :
              function() { _super.onclone.call(_this) };
            init.call(this, _super, f);
          };
        });
    } else {
      init.call(this, _super);
    }
  },

  /**
   * Shallow copies the given properties onto this object,
   * excluding those already owned by this object
   * (eg. those inherited through Object.prototype).
   */
  assign: function(props) {
    for (var key in props) {
      var value = props[key];
      if (this[key] != value)
        this[key] = value;
    }
    return this;
  }
  
}
&lt;/pre&gt;&lt;p&gt;I just added a bit of sugar that allows you to set the 'onclone' event handler to the initializer in one step. Now the following is possible.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;Human = Animal.clone(function(_super, install) {

  install(); // This initializer method will run 'onclone' also.
             // install() will automagically be replaced with a call
             // to _super.onclone when called from the 'onclone' event
  var ate = [];
  this.eat = function(betterfood) {
    _super.eat.call(this, betterfood);
    ate.push(betterfood);
  }
});
&lt;/pre&gt;&lt;p&gt;You can find the "finished" framework &lt;a href="http://code.google.com/p/blogcode/source/browse/trunk/Proto/proto.js" target="_blank"&gt;here&lt;/a&gt;. I hope you enjoyed this journey as much as I did. Please comment, and let me know your thoughts on prototype-based program design.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-7781473614484740816?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/ArytKZHbDzo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/7781473614484740816/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2009/04/prototype-based-programming-in_04.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/7781473614484740816?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/7781473614484740816?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/ArytKZHbDzo/prototype-based-programming-in_04.html" title="Prototype-based programming in Javascript (part 2)" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>1</thr:total><feedburner:origLink>http://devblog.techhead.biz/2009/04/prototype-based-programming-in_04.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cDSXk_fCp7ImA9WxVaEEk.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-149811356406414067</id><published>2009-04-03T15:55:00.000-07:00</published><updated>2009-04-06T12:11:18.744-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-06T12:11:18.744-07:00</app:edited><title>Prototype-based programming in Javascript</title><content type="html">&lt;p&gt;You may have heard that Javascript is a &lt;a href="http://en.wikipedia.org/wiki/Prototype-based_programming" target="_blank"&gt;prototype-based programming&lt;/a&gt; language, but chances are that you've never used it that way -- not really. Maybe that's because prototype-based programming is kind of... well... different.&lt;/p&gt;&lt;p&gt;Now, I must admit that &lt;em&gt;I think&lt;/em&gt; prototype-based programming makes sense to me, but I haven't ever actually used it in a project. (Until now.) In fact, you might be hard pressed to find any projects in which this programming model is being used, and I am curious to know why. Is it because it is awkward, or is it a hidden gem?&lt;/p&gt;&lt;p&gt;My interest is both academic and practical, in the sense that I love to explore programming language methodologies but I also actually write code. It seems, other than Javascript, the prototype model exists largely in academia. You'll hear a lot about Self, a Smalltalk derivative, but I am unaware of any projects actually written in Self. My favorite example of a prototype-based programming language is &lt;a href="http://iolanguage.com" target="_blank"&gt;Io&lt;/a&gt; -- in which I have never written a single line of code. But its &lt;a href="http://iolanguage.com/scm/git/checkout/Io/docs/IoGuide.html" target="_blank"&gt;documentation&lt;/a&gt; helps to illustrate the point. I will translate one such example into how Javascript would look if it were more straightforwardly prototypal (and then we'll work on making it so).&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;Account = Object.clone();
Account.balance = 0;
Account.deposit = function(amount) {
  this.balance += amount;
}

account = Account.clone();
account.deposit(10.00);
alert(account.balance);
&lt;/pre&gt;&lt;p&gt;In the above example, notice that there are no classes nor constructors. Account is an object. It has a balance. You can even call the deposit method to change that balance. But the Account object was not likely created to be used directly. Instead it is intended to be more of a rubber stamp, a model which can be cloned.&lt;/p&gt;&lt;p&gt;And under the hood, Javascript works this way too. The confusion comes largely from the adhoc type system that is built on top of the prototype model. Take away the &lt;code&gt;new&lt;/code&gt; and &lt;code&gt;instanceof&lt;/code&gt; operators and using prototype inheritance in Javascript might be more straightforward. (I am not suggesting this, however. I love the flexibility that Javascript provides.)&lt;/p&gt;&lt;p&gt;The previous Javascript example does not work, of course. There is no &lt;code&gt;Object.clone()&lt;/code&gt; method. But that is essentially what the &lt;code&gt;new&lt;/code&gt; operator does. (More on that later.) In SpiderMonkey Javascript (Mozilla's implementation), the above code could be rewritten as:&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;Account = {
  balance: 0,
  deposit: function(amount) {
    this.balance += amount;
  }
}
Account.__proto__ = Object.prototype; // Object itself is a constructor,
                                      // not an 'instance'

account = {};
account.__proto__ = Account;
account.deposit(10.00);
alert(account.balance);
&lt;/pre&gt;&lt;p&gt;And this more clearly shows what is actually going on and the relationship between objects in prototype-based models. &lt;code&gt;Account&lt;/code&gt; defines two properties, &lt;code&gt;balance&lt;/code&gt; and &lt;code&gt;deposit&lt;/code&gt;, but it also declares that it inherits properties from &lt;code&gt;Object.prototype&lt;/code&gt; by setting &lt;code&gt;Account.__proto__ = Object.prototype&lt;/code&gt;. Thus if you attempt to access a property that does not exist for Account, &lt;code&gt;Object.prototype&lt;/code&gt; will also be searched. However, it is important to remember that each object has its own properties (or slots). In the above example, setting &lt;code&gt;account.balance = 1000&lt;/code&gt; does not change &lt;code&gt;Account.balance&lt;/code&gt;. This is a good thing.&lt;/p&gt;&lt;p&gt;It is worth mentioning also that in some major Javascript implementations (most notably IE), you cannot set an object's prototype chain directly as we did in the prior example. It must be set on object "construction".&lt;/p&gt;&lt;p&gt;Constructors are the adhoc type system of which I spoke earlier. They are nothing more than simple initializer functions, but they also are responsible for setting the prototype chain by way of their &lt;code&gt;prototype&lt;/code&gt; property. As always, code speaks louder than words. Below is what the new operator might look like in SpiderMonkey.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;function neww (constructor) {
  var newObject = {}; // new object with its own properties
  newObject.constructor = constructor; // this is the new object 'type'
  newObject.__proto__ = constructor.prototype; // desired prototype obtained here
  // call the constructor on the newly created object
  constructor.apply(newObject, Array.prototype.slice.call(arguments, 1));
  return newObject;
}

function FauxAccountClass() {
}
FauxAccountClass.prototype = Account;

account = neww(FauxAccountClass);
// or, same thing...
account = new FauxAccountClass();

alert(account instanceof FauxAccountClass); // will alert 'true'
&lt;/pre&gt;&lt;p&gt;Please let me know if something is not clear. To summarize, a constructor is simply a function. The &lt;code&gt;prototype&lt;/code&gt; property of that function (eg. &lt;code&gt;FauxAccountClass.prototype&lt;/code&gt;) decides what the "parent" object of the new object will be. Constructors are the basis of the Javascript type system. However, if you "forget" about constructors and the operators designed to work with them, you still have Javascript ...and an entirely different way of using it. That's where I'm going to take you next. But this article is already quite long, so I'll continue in a follow-up post.&lt;/p&gt;&lt;p&gt;The follow up is now online here: &lt;a href="http://devblog.techhead.biz/2009/04/prototype-based-programming-in_04.html"&gt;http://devblog.techhead.biz/2009/04/prototype-based-programming-in_04.html&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-149811356406414067?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/-fD3e2eLqyQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/149811356406414067/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2009/04/prototype-based-programming-in.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/149811356406414067?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/149811356406414067?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/-fD3e2eLqyQ/prototype-based-programming-in.html" title="Prototype-based programming in Javascript" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>0</thr:total><feedburner:origLink>http://devblog.techhead.biz/2009/04/prototype-based-programming-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkAEQHg9eSp7ImA9WxVbF04.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-1389715827847155908</id><published>2009-04-02T23:05:00.000-07:00</published><updated>2009-04-02T23:05:01.661-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-02T23:05:01.661-07:00</app:edited><title>Dynamically load external Javascript in a cross-browser way</title><content type="html">&lt;p&gt;If you've done any significant Javascript development, I'm sure that you've run into the need to dynamically include an external javascript library. There are many existing libraries that will do this for you quite easily. But what if you are not able to take advantage of such a library? What if that library is precisely the javascript you wish to dynamically load?&lt;/p&gt;&lt;p&gt;Hmm. In that case you can use the following code snippet to bootstrap the process.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;function loadScript(src, callback) {
  var head = document.getElementsByTagName('head')[0];
  var script = document.createElement('script');
  var loaded = false;
  script.setAttribute('src', src);
  script.onload = script.onreadystatechange = function() {
    if (!loaded &amp;&amp; (!this.readyState || this.readyState == 'complete'
                                     || this.readyState == 'loaded') ) {
      loaded = true;
      callback();
      script.onload = script.onreadystatechange = null;
      head.removeChild(script);
    }
  }
  head.appendChild(script);
}
&lt;/pre&gt;&lt;p&gt;For example, here's how I used it to bootstrap jQuery in a bookmarklet I wrote.&lt;/p&gt;&lt;pre class="prettyprint javascript code"&gt;(function() {

function loadScript(src, callback) {
  var head = document.getElementsByTagName('head')[0];
  var script = document.createElement('script');
  var loaded = false;
  script.setAttribute('src', src);
  script.onload = script.onreadystatechange = function() {
    if (!loaded &amp;&amp; (!this.readyState || this.readyState == 'complete'
                                     || this.readyState == 'loaded') ) {
      loaded = true;
      callback();
      script.onload = script.onreadystatechange = null;
      head.removeChild(script);
    }
  }
  head.appendChild(script);
}

function withJQuery(cb) {
  loadScript('http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js',
    function() {
      cb(jQuery.noConflict(true));
    }
  );
}

withJQuery(function($) {
  // do something with jQuery
});

})();
&lt;/pre&gt;&lt;p&gt;Notice that the above code adds nothing to the global namespace. The code is localized within an anonymous function and &lt;code&gt;jQuery.noConflict(true)&lt;/code&gt; is called so that jQuery cleans up after itself and resets the &lt;code&gt;$&lt;/code&gt; and &lt;code&gt;jQuery&lt;/code&gt; globals to whatever they were prior to the script being loaded. Nice, but admittedly a lot of bootstrap code.&lt;/p&gt;&lt;p&gt;I've been thinking a lot lately about how a robust javascript packaging system would look. But even then, a nice library wouldn't help a lot here. It would have to be part of the language, and I am not anxious for &lt;em&gt;any&lt;/em&gt; additions to the language that have not been very well vetted.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-1389715827847155908?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/-VM00MkYSmQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/1389715827847155908/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2009/04/dynamically-load-external-javascript-in.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/1389715827847155908?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/1389715827847155908?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/-VM00MkYSmQ/dynamically-load-external-javascript-in.html" title="Dynamically load external Javascript in a cross-browser way" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>0</thr:total><feedburner:origLink>http://devblog.techhead.biz/2009/04/dynamically-load-external-javascript-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUDQ34zeip7ImA9WxVbF04.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-3715206010797281191</id><published>2009-04-02T22:24:00.000-07:00</published><updated>2009-04-02T22:24:32.082-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-02T22:24:32.082-07:00</app:edited><title>Welcome to the shiny new TECHHEAD Development Blog</title><content type="html">&lt;p&gt;The &lt;em&gt;other&lt;/em&gt; &lt;a href="http://blog.techhead.biz" target="_blank"&gt;TECHHEAD blog&lt;/a&gt; has existed (and been largely neglected) for some time now. However, its core audience has always been the technologically challenged, which made my occasional programming or web-development-related article all the more absurd.&lt;/p&gt;&lt;p&gt;But I've needed an outlet. Programming (and web development in particular) is my passion. It is my intention to share that with you here. But be forwarned; I am not a natural blogger. The necessary regularity and dedication has not yet been developed. I'd rather write code than English. So we'll see what happens. Be sure to subscribe to the feed before you go.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-3715206010797281191?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/2MPlB1UuoBE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/3715206010797281191/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2009/04/welcome-to-shiny-new-techhead.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/3715206010797281191?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/3715206010797281191?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/2MPlB1UuoBE/welcome-to-shiny-new-techhead.html" title="Welcome to the shiny new TECHHEAD Development Blog" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>0</thr:total><feedburner:origLink>http://devblog.techhead.biz/2009/04/welcome-to-shiny-new-techhead.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAHQHY4eip7ImA9WxVbF0w.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-5865875030551484397</id><published>2009-01-06T15:17:00.001-08:00</published><updated>2009-04-02T16:25:31.832-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-02T16:25:31.832-07:00</app:edited><title>Simple bookmarklet for creating Amazon Affiliate links</title><content type="html">&lt;p style="clear: both;"&gt;For those who don't know, a &lt;a href="http://en.wikipedia.org/wiki/Bookmarklet" target="_blank"&gt;bookmarklet&lt;/a&gt; is just a "fancy" link that you install in your web-browser toolbar, usually by dragging it there. (In IE you must right click it, select "Add to Favorites" and then save it in the "Links" folder.) When clicked, bookmarklets &lt;i&gt;do something&lt;/i&gt; with the currently viewed document.&lt;/p&gt;&lt;p style="clear: both;"&gt;Got it? Good. Moving on...&lt;/p&gt;&lt;p style="clear: both;"&gt;I am an &lt;a href="https://affiliate-program.amazon.com/gp/associates/join?tag=techhead-20" target="_blank"&gt;Amazon Affiliate&lt;/a&gt;, and I wanted a simple way to create affiliate links to Amazon products. I found a &lt;a href="http://crazybob.org/2008/10/how-to-create-simple-amazon-affiliate.html" target="_blank"&gt;very straightforward tutorial over at crazybob.org&lt;/a&gt;. But I'm still too lazy. I want to be able to browse &lt;a href="http://www.amazon.com/?tag=techhead-20" target="_blank"&gt;Amazon.com&lt;/a&gt; and when I find what I am looking for, I want to be able to simply click a button to generate the appropriate HTML.&lt;/p&gt;&lt;p style="clear: both;"&gt;So I made the following bookmarklet:&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;a href="javascript:void(prompt('Copy%20Affiliate%20Link','&amp;lt;a%20href=&amp;quot;http://www.amazon.com/dp/'+document.handleBuy.ASIN.value+'/?tag=techhead-20&amp;quot;&amp;gt;'+document.getElementById('btAsinTitle').innerHTML+'&amp;lt;/a&amp;gt;'))"&gt;Amazon Affiliate Link&lt;/a&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;Install it, and head over to &lt;a href="http://www.amazon.com/?tag=techhead-20" target="_blank"&gt;Amazon.com&lt;/a&gt; to try it out. Of course, you'll want to make sure that the affiliate links it creates refer to &lt;i&gt;your&lt;/i&gt; Amazon Associate ID and not mine.&lt;/p&gt;&lt;p style="clear: both;"&gt;To create your own customized bookmarklet, use this &lt;a href="http://techhead.biz/aalink/generator.html" target="_blank"&gt;tool here&lt;/a&gt;.&lt;/p&gt;&lt;p style="clear: both;"&gt;Happy linking! And remember, &lt;a href="http://tipjoy.com/u/techhead" onclick="if (window.tipjoyOpenLightbox) {tipjoyOpenLightbox();return false} else return true" target="_blank"&gt;tipping is easy with Tipjoy&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-5865875030551484397?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/xEdZD-Rfl4Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/5865875030551484397/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2009/01/simple-bookmarklet-for-creating-amazon_06.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/5865875030551484397?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/5865875030551484397?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/xEdZD-Rfl4Q/simple-bookmarklet-for-creating-amazon_06.html" title="Simple bookmarklet for creating Amazon Affiliate links" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>0</thr:total><feedburner:origLink>http://devblog.techhead.biz/2009/01/simple-bookmarklet-for-creating-amazon_06.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAGQ3s8eyp7ImA9WxVbFkQ.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-1642826621263427198</id><published>2008-12-31T13:15:00.000-08:00</published><updated>2009-04-02T11:25:22.573-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-02T11:25:22.573-07:00</app:edited><title>jQuery vs Dojo Toolkit vs Prototype vs MooTools</title><content type="html">&lt;p style="clear: both"&gt;This is a very quick, unthorough rundown of the most popular Javascript frameworks at the time, and why I currently favor &lt;a href="http://jquery.org" target="_blank"&gt;jQuery&lt;/a&gt;.&lt;/p&gt;&lt;p style="clear: both"&gt;I did not make a significant time investment in my investigation, but there were a couple of factors I was interested in:&lt;/p&gt;&lt;p style="clear: both"&gt;&lt;ul style="clear: both"&gt;&lt;li&gt;I wanted a framework that &lt;em&gt;did not&lt;/em&gt; include a faux class-based object framework. Javascript is prototype based and very powerful that way. (I'll write my Javascript in Javascript, thank you.)&lt;/li&gt;&lt;li&gt;I wanted a framework that imposed minimal littering of the current window's global namespace.&lt;/li&gt;&lt;li&gt;I wanted a framework that was simple to learn and easy to use.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p style="clear: both"&gt;jQuery best fit the bill. There are no false classes in jQuery; it leaves coding style up to you (not so in Prototype or MooTools). In jQuery, there is minimal littering of the global namespace -- the only exported symbols are &lt;em&gt;jQuery&lt;/em&gt; and the optional &lt;em&gt;$&lt;/em&gt;. (Again, this is not the case with Prototype and MooTools.) Lastly, jQuery wins hands down on ease of use. You could pick it up in five minutes if you are a seasoned web developer. The Dojo Toolkit looks promising -- I especially like its module packaging framework -- but it will require a more significant time investment than the elegant jQuery.&lt;/p&gt;&lt;p style="clear: both"&gt;Here's a closing thought: I would like to see an entirely independent module packaging framework for Javascript. Anyone know of one?&lt;/p&gt;&lt;p style="clear: both"&gt;I'm sure that this post will be controversial to some of you MooTools and Prototype zealots. Tell me why I'm wrong! I'd love to hear your take.&lt;/p&gt;&lt;br class='final-break' style='clear: both' /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-1642826621263427198?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/VgtK3tmY9NA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/1642826621263427198/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2008/12/jquery-vs-dojo-toolkit-vs-prototype-vs.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/1642826621263427198?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/1642826621263427198?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/VgtK3tmY9NA/jquery-vs-dojo-toolkit-vs-prototype-vs.html" title="jQuery vs Dojo Toolkit vs Prototype vs MooTools" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>0</thr:total><feedburner:origLink>http://devblog.techhead.biz/2008/12/jquery-vs-dojo-toolkit-vs-prototype-vs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAHQHY4eip7ImA9WxVbF0w.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-5162751956578794236</id><published>2008-12-27T13:38:00.001-08:00</published><updated>2009-04-02T16:25:31.832-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-02T16:25:31.832-07:00</app:edited><title>Tipjoy post-icon widget for Blogger</title><content type="html">&lt;p&gt;After my &lt;a href="http://blog.techhead.biz/2008/12/panhandling-20-money-goes-social.html" target="_blank"&gt;last post&lt;/a&gt; about micropayments (and &lt;a href="http://tipjoy.com/" target="_blank"&gt;Tipjoy&lt;/a&gt; in particular), I had several inquiries as to how I added the "Tip 25 cents" icon below each blog entry.&lt;/p&gt;&lt;p&gt;It's pretty simple really.&amp;nbsp; First go to &lt;a href="http://tipjoy.com/banners/custom/" target="_blank"&gt;http://tipjoy.com/banners/custom/&lt;/a&gt; to create your custom Tipjoy button. You can then place it anywhere you want on your site and even style it with custom CSS... Or you can forget the default button and CSS and just make your own (like on &lt;a href="http://flyingpizzakitty.com/" target="_blank"&gt;flyingpizzakitty.com&lt;/a&gt; and &lt;a href="http://blog.techhead.biz/" target="_blank"&gt;this website&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;My button code looks like this.&lt;/p&gt;&lt;pre class="prettyprint code xml"&gt;&amp;lt;script language="javascript" src="http://tipjoy.com/socnet/widget?username=techhead&amp;amp;url=blog.techhead.biz&amp;amp;message=Thank's%20for%20your%20support!&amp;amp;amount=0.25"&amp;gt;script&amp;gt;&lt;/pre&gt;&lt;p&gt;And I didn't bother copying the CSS portion because I didn't really want to show the default button. So to avoid showing the button, I wrapped the button code in...&lt;/p&gt;&lt;pre class="prettyprint code xml"&gt;&amp;lt;div style="display:none"&amp;gt;...&amp;lt;/div&amp;gt;&lt;/pre&gt;&lt;p&gt;To add a Tipjoy icon to the bottom of each entry, I wrote a short &lt;a href="http://jquery.org/" target="_blank"&gt;jQuery&lt;/a&gt; script, so you'll need to make sure that jQuery gets loaded sometime prior to the script being executed.&lt;/p&gt;&lt;p&gt;Your blog may be loading jQuery already. If not, add the following to the  section of your template or just directly above the icon script:&lt;/p&gt;&lt;pre class="prettyprint xml code"&gt;&amp;lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;p&gt;Once you have jQuery available, you can add a "tip reminder" icon to each blog entry by copying the below script either directly into your blog template or by adding an HTML/Javascript Page Element to your Layout.&lt;/p&gt;&lt;pre class="prettyprint xml code"&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;(function($) {&lt;br /&gt;&amp;nbsp; $(function() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $('.hentry').each(function() { // for each blog entry&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var icon = $('&amp;lt;span&amp;gt;&amp;lt;a href="javascript:tipjoyOpenLightbox()"&amp;gt;Tip 25&amp;amp;#162;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;');&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; $('a', icon).css({&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; 'padding':'1px 5px 5px 22px',&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; 'background':'url(http://techhead.biz/tipjoy/tipjoystar.gif) no-repeat scroll 0 0'});&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(this).find('.post-icons').append(icon); // add the Tipjoy icon&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;br /&gt;&amp;nbsp; });&lt;br /&gt;})(jQuery);&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;p&gt;And that should do the trick! Of course, you may want to change the figure from "25 cents" to something else. If you do, just remember to change it in both the Tipjoy button script and in the icon script.&lt;/p&gt;&lt;p&gt;If you would like to place an additional tip reminder in the text of your blog post itself, here is another little formula.&lt;/p&gt;&lt;pre class="prettyprint xml code"&gt;&amp;lt;a href="http://tipjoy.com/u/myusername" onclick="if (window.tipjoyOpenLightbox) {tipjoyOpenLightbox();return false} else return true"&amp;gt;TEXT OR IMAGE HERE&amp;lt;/a&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://tipjoy.com/u/techhead" onclick="if (window.tipjoyOpenLightbox) {tipjoyOpenLightbox();return false} else return true" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank"&gt;&lt;img alt="Mariachi Monkey" border="0" src="http://techhead.biz/images/el_monkeyachi_md_wht.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;Speaking of which, if you found this article helpful, please help keep the monkey playing.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-5162751956578794236?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/ifJX-OI10cY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/5162751956578794236/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2008/12/tipjoy-post-icon-widget-for-blogger_27.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/5162751956578794236?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/5162751956578794236?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/ifJX-OI10cY/tipjoy-post-icon-widget-for-blogger_27.html" title="Tipjoy post-icon widget for Blogger" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>0</thr:total><feedburner:origLink>http://devblog.techhead.biz/2008/12/tipjoy-post-icon-widget-for-blogger_27.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAGQ3s8eyp7ImA9WxVbFkQ.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-2669770842303290331</id><published>2008-07-16T20:05:00.000-07:00</published><updated>2009-04-02T11:25:22.573-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-02T11:25:22.573-07:00</app:edited><title>Place a context-sensitive search on your website or blog</title><content type="html">&lt;p&gt;Google is making it too easy for the modern web developer.  I remember writing a brute-force search engine in Perl for a small web site about 11 years ago.  It was slow, resource intensive, and would not scale well with a site of any size.&lt;/p&gt;&lt;p&gt;Skip forward a bit. Google now provides the ability to add a custom search to your site at no cost.  Unless yours is for a non-profit organization, displaying ads is mandatory, but you do have the option to share in the profit (or pay to have the ads removed).&lt;/p&gt;&lt;p&gt;Google Custom Search is really quite flexible.  You can tell it what sites to include or exclude.  You can have it boost the ranking of a given number or sites or simply filter out all the sites that don't meet your criteria.  Custom Search even gives you the ability to generate these rules on the fly so that results can be tailored to a particular user or a particular page of the site.&lt;/p&gt;&lt;p&gt;This article is not intended to be an in-depth tutorial on Custom Search.  For documentation, see here: &lt;a href="http://www.google.com/coop/docs/cse/" target="_blank"&gt;http://www.google.com/coop/docs/cse/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The definition of your search engine can either be Google hosted or you can host it yourself (This is termed a Linked CSE).  For context-sensitive search, yours must be a Linked CSE.&lt;/p&gt;&lt;p&gt;Custom Search Engines (CSEs) are defined by a simple &lt;a href="http://www.google.com/coop/docs/cse/cse_file.html" target="_blank"&gt;XML specification&lt;/a&gt;.  This specification may be generated dynamically for interesting results.  Below is a very simple example of a dynamically generated CSE which parses all of the links out of the referring page in order to include only those sites within the search results.  The code snippet is written in PHP.&lt;/p&gt;&lt;pre class="prettyprint code lang-php"&gt;&amp;lt;?php&lt;br /&gt;  header('Content-type: text/xml');&lt;br /&gt;  $url = $_SERVER['QUERY_STRING'];&lt;br /&gt;  if (!$url) $url = $_SERVER['HTTP_REFERER'];&lt;br /&gt;  echo &amp;lt;&amp;lt;&amp;lt;CSE&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;GoogleCustomizations&amp;gt;&lt;br /&gt;&amp;lt;CustomSearchEngine keywords="" language="en"&amp;gt;&lt;br /&gt;  &amp;lt;Title&amp;gt;TECHHEAD&amp;lt;/Title&amp;gt;&lt;br /&gt;  &amp;lt;Description&amp;gt;The search for All Things Tech&amp;lt;/Description&amp;gt;&lt;br /&gt;  &amp;lt;Context&amp;gt;&lt;br /&gt;    &amp;lt;BackgroundLabels&amp;gt;&lt;br /&gt;      &amp;lt;Label name="techhead_site" mode="FILTER"/&amp;gt;&lt;br /&gt;    &amp;lt;/BackgroundLabels&amp;gt;&lt;br /&gt;  &amp;lt;/Context&amp;gt;&lt;br /&gt;&amp;lt;/CustomSearchEngine&amp;gt;&lt;br /&gt;CSE;&lt;br /&gt;  if ($url) {&lt;br /&gt;    $url = urlencode(urldecode($url));&lt;br /&gt;    echo &amp;lt;&amp;lt;&amp;lt;CSE&lt;br /&gt;&amp;lt;Include type="Annotations"&lt;br /&gt;href="http://www.google.com/cse/tools/makeannotations?url=$url&amp;amp;label=techhead_site"/&amp;gt;&lt;br /&gt;CSE;&lt;br /&gt;  }&lt;br /&gt;  echo &amp;lt;&amp;lt;&amp;lt;CSE&lt;br /&gt;&amp;lt;Annotations&amp;gt;&lt;br /&gt;  &amp;lt;Annotation about="*.techhead.biz/*"&amp;gt;&lt;br /&gt;    &amp;lt;Label name="techhead_site"/&amp;gt;&lt;br /&gt;  &amp;lt;/Annotation&amp;gt;&lt;br /&gt;&amp;lt;/Annotations&amp;gt;&lt;br /&gt;&amp;lt;/GoogleCustomizations&amp;gt;&lt;br /&gt;CSE;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Notice how certain annotations are included dynamically based on $url (which is simply the HTTP referer of the script).  Annotations are for matching URL patterns with labels.  The CSE is set to FILTER out any site that isn't part of "techhead_site".  So the annotations define what is to be considered for inclusion in the search results.&lt;/p&gt;&lt;p&gt;Now we have a dynamic CSE definition.  To use it, paste the appropriate HTML code snippets (&lt;a href="http://www.google.com/coop/docs/cse/cref.html" target="_blank"&gt;http://www.google.com/coop/docs/cse/cref.html&lt;/a&gt;) into your web page or blog template.  You will need to substitute the value of the hidden form parameter "cref" for whatever the URL to your PHP program is.  For a more concrete example, simply look at the page source of this blog at &lt;a href="http://blog.techhead.biz" target="_blank"&gt;http://blog.techhead.biz&lt;/a&gt;&lt;/p&gt;&lt;p&gt;For a much better Google Custom Search tutorial, see here: &lt;a href="http://www.free-your-mind.info/" target="_blank"&gt;http://www.free-your-mind.info/&lt;/a&gt;  Then come back to fill in the blanks and make your search engine context-sensitive.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-2669770842303290331?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/0P0cbMpNw0M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/2669770842303290331/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2008/07/place-context-sensitive-search-on-your.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/2669770842303290331?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/2669770842303290331?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/0P0cbMpNw0M/place-context-sensitive-search-on-your.html" title="Place a context-sensitive search on your website or blog" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>0</thr:total><feedburner:origLink>http://devblog.techhead.biz/2008/07/place-context-sensitive-search-on-your.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAGQ3s8eyp7ImA9WxVbFkQ.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-610709332241618177</id><published>2008-07-15T15:13:00.000-07:00</published><updated>2009-04-02T11:25:22.573-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-02T11:25:22.573-07:00</app:edited><title>Building a true object-oriented system for Common Lisp</title><content type="html">&lt;p&gt;While the title of this post may be seen as inflammatory, allow me to elaborate before dashing off to the comment link and turning your flamethrower loose.&lt;/p&gt;&lt;p&gt;As you have probably been taught, &lt;a href="http://en.wikipedia.org/wiki/Alan_Kay" target="_blank"&gt;Dr. Alan Kay&lt;/a&gt; coined the term "object oriented" (OO).  His term, his rules (Which can be found here: &lt;a href="http://www.purl.org/stefan_ram/pub/doc_kay_oop_en" target="_blank"&gt;http://www.purl.org/stefan_ram/pub/doc_kay_oop_en&lt;/a&gt;).  The &lt;a href="http://en.wikipedia.org/wiki/CLOS" target="_blank"&gt;Common Lisp Object System&lt;/a&gt; (CLOS) does not fit the bill to be called object oriented, although it still arrives at many of the benefits of object-oriented principle (and perhaps more -- I will expound on this later).  But as Dr. Kay mentions in the above link, OO &lt;i&gt;can be done in Lisp&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;I have been exploring programming languages a great deal as of late.  One language in particular, &lt;a href="http://www.erlang.org" target="_blank"&gt;Erlang&lt;/a&gt;, has caught my attention because of its much hyped nothing-is-shared model of concurrency.  Erlang accomplishes scalability by breaking tasks into many lightweight processes that communicate with each other in the form of messages.  (Hmm. Where have I seen that before?)  There was something very OO looking about some of the code samples I saw.  Only instead of method names being "invoked" on an object, a process listens for messages of different types and those message types are represented by "atoms", which are essentially strings that contain some meaning to the program.  Communication between processes in Erlang fits with Dr. Kay's requirements for an OO language (messaging, late binding, etc).  It also fits the &lt;a href="http://en.wikipedia.org/wiki/Actor_model" target="_blank"&gt;Actor model&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;It can be quite confusing to distinguish between the Actor model and that of OO programming.  The reason?  (And this will likely be a point of some dispute.)  There isn't really any difference.  The term "Actor model", I believe, just had to be invented because the term "object oriented" had come to represent something other than the original meaning.  OO programming has now become synonymous with stack-based models where messages are passed up and down the stack and "messages" are really just function calls conceptualized as messages.  Actors on the other hand are discrete (messages and responses don't traverse a call stack) and are therefore inherently concurrent.  Erlang processes and web services are good examples of the Actor model.&lt;/p&gt;&lt;p&gt;Now back to CL.  CLOS uses multi-methods instead of message passing, so it is not strictly OO.  However, as promised earlier, I'm going to stroke the CL users a little bit here and propose that perhaps the CLOS model is more appropriate to be called "object oriented" than Dr. Kay's model.  Why?  Because OO programming is (supposed to be) all about the encapsulation of behaviors, and objects don't &lt;em&gt;do&lt;/em&gt; anything.  But functions do.&lt;/p&gt;&lt;p&gt;What do you mean, "An object can't do anything"?  Well, in real life, an object (I think of a rock or a piece of wood) does not do anything.  A rock cannot skip itself, change its location, size, or color, or tell you any of these things about itself if you send it a message.  A rock is simply a rock.  If you think in procedural terms, it would be a data structure.&lt;/p&gt;&lt;p&gt;A data structure? Wha? I thought that "everything is an object?"  OO languages assign a sort of anthropomorphic view to objects (Objects are people too) which makes perfect sense if you look at the &lt;a href="http://users.ipa.net/~dwighth/smalltalk/byte_aug81/design_principles_behind_smalltalk.html" target="_blank"&gt;design principles behind Smalltalk&lt;/a&gt; (the language Dr. Kay invented to go along with the term).  One of the major design goals was to create a &lt;i&gt;human&lt;/i&gt; interface with the machine, to allow the programmer to think in an (arguably) more human way.&lt;/p&gt;&lt;p&gt;Along those lines (thinking like a human), I like the term Actor better than Object because it can be explained in a way that makes sense.  A rock cannot tell you anything about itself.  However, an actor portraying a rock can. (I'm not a rock. I just play one on TV.)  This way, everything can be an actor and the model stays coherent.  There is no data, only actors that portray it.  (Again, refer to Dr. Kay's letter above and where he talks about dataless programming.)&lt;/p&gt;&lt;p&gt;This makes sense to me as I often equate programming language models to models of the universe.  But the question remains how to best model the universe.  What is the essential building block of the universe?  Is there one?&lt;/p&gt;&lt;p&gt;So what is the building block of a program?  An object?  And what about not only modeling what an object can do but what can be done to it?  What rules?  What forces apply?&lt;/p&gt;&lt;p&gt;Enter functions.  In CLOS, a function (or group of functions called multi-methods) defines a behavior for an object.  And these behaviors govern object interactions.  Just as a rock has no knowledge of everything that can be done to it, the behaviors do not belong explicitly to the rock, but rather to the context in which the rock is to be used.&lt;/p&gt;&lt;p&gt;And this model is more coherent for "objects" (as I described them earlier).  But for our anthropomorphic figures, objects that DO, it makes more sense to just ask them (as in the messaging model).&lt;/p&gt;&lt;p&gt;Most modern programming languages have lost coherency in their model.  So when I ask what the building block of a program is, it's not simply rhetoric.  The answer will, of course, vary by model, but then is it even possible to introduce a model where there is a single coherent answer?  Well, of course it is possible.  But perhaps a better question should be, is it practical?  Is it a viable way to model our universe?&lt;/p&gt;&lt;p&gt;The question came to me when I realized that an object could be implemented as a function and vise versa, so it's sort of a chicken-and-egg problem.&lt;/p&gt;&lt;p&gt;In some languages (one of them is CL), a function may be curried with a particular parameter or live within an enclosing scope.  These functions are essentially just objects as we know them.  Here's a short example:&lt;/p&gt;&lt;script src="http://google-code-prettify.googlecode.com/svn/trunk/src/lang-lisp.js"&gt;&lt;/script&gt;&lt;pre class="prettyprint code lang-lisp"&gt;(let* ((privateVar 2)&lt;br /&gt;       (methodDictionary&lt;br /&gt;         `((set . ,(lambda (x) (setf privateVar x)))&lt;br /&gt;           (+   . ,(lambda (x) (+ x privateVar)))&lt;br /&gt;           (-   . ,(lambda (x) (- x privateVar))))))&lt;br /&gt;  (defun simple-object (methodName &amp;rest args)&lt;br /&gt;    (apply (cdr (assoc methodName methodDictionary)) args)))&lt;br /&gt;&lt;br /&gt;(simple-object '+ 2) ; equals 4&lt;br /&gt;(simple-object 'set 40)&lt;br /&gt;(simple-object '+ 2) ; equals 42&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;A whole object system can be created using such closures.  In fact, that's exactly what I've done.  It may not have been the most practical exercise. (I'm certainly not advocating using it over CLOS.)  But for someone interested in language design, as I am, you may find it enlightening.  It is &lt;a href="http://en.wikipedia.org/wiki/Prototype-based_programming" target="_blank"&gt;prototype based&lt;/a&gt;, and state is kept private.  You can find it &lt;a href="http://code.google.com/p/blogcode/source/browse/trunk/YACLOS/L-object.lisp" target="_blank"&gt;here&lt;/a&gt; or on Wikipedia as &lt;a href="http://en.wikipedia.org/wiki/YACLOS" target="_blank"&gt;YACLOS&lt;/a&gt;, so feel free to improve on the code if you are so inclined.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-610709332241618177?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/_6_FeEdweEU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/610709332241618177/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2008/07/building-true-object-oriented-system.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/610709332241618177?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/610709332241618177?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/_6_FeEdweEU/building-true-object-oriented-system.html" title="Building a true object-oriented system for Common Lisp" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>3</thr:total><feedburner:origLink>http://devblog.techhead.biz/2008/07/building-true-object-oriented-system.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAGQ3s8fCp7ImA9WxVbFkQ.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-5746739648268703146</id><published>2008-07-12T12:28:00.000-07:00</published><updated>2009-04-02T11:25:22.574-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-02T11:25:22.574-07:00</app:edited><title>Beust Coding Challenge</title><content type="html">&lt;p&gt;Once again I am late to the party.  Cedric posted a &lt;a href="http://beust.com/weblog/archives/000491.html" target="_blank"&gt;coding challenge&lt;/a&gt; on his blog.  It looks like &lt;a href="http://crazybob.org" target="_blank"&gt;Crazy Bob&lt;/a&gt; took the prize for most creative (and fastest) &lt;a href="http://crazybob.org/FastBeustSequence.java.html" target="_blank"&gt;implementation&lt;/a&gt;.  I would like to think that I could have come up with a similar solution, but then again, I also like to think that I could look like Schwarzenegger if I ever started working out.&lt;/p&gt;&lt;p&gt;However, Cedric posted a follow up, &amp;#8220;Port Bob's code to your language.&amp;#8221;  Bob&amp;#8217;s code was in Java.  However, I am a Java programmer, so that sort of rules out a port.  But I was able to make a few performance enhancements.  Instead of a doubly linked list, I used a singly linked list and thus was able to prevent a few unnecessary assignments and eliminate a few checks.  In addition, once the max has been found, I use a Throwable to unwind the stack.  On my Intel MacBook, I see performance enhancements of 10-20%.  The code can be found here: &lt;a href="http://code.google.com/p/blogcode/source/browse/trunk/BeustChallenge0708/src/beust/ModifiedBeustSequence.java" target="_blank"&gt;ModifiedBeustSequence&lt;/a&gt;. Or for the comparison, see here: &lt;a href="http://code.google.com/p/blogcode/source/browse/trunk/BeustChallenge0708/src/beust/CompareBeustSequence.java" target="_blank"&gt;CompareBeustSequence&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;But sticking to the assignment, I did do a straight port of my modified version into Common Lisp, which I have been toying with lately (The port can be found here: &lt;a href="http://code.google.com/p/blogcode/source/browse/trunk/BeustChallenge0708/beust.lisp" target="_blank"&gt;beust.lisp&lt;/a&gt;). I&amp;#8217;m sure that any respectable Lisp programmer could come up with a much more Lisp-like solution.  If you go to the trouble, I would love to see it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-5746739648268703146?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/2BNiKlKt_3I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/5746739648268703146/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2008/07/beust-coding-challenge.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/5746739648268703146?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/5746739648268703146?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/2BNiKlKt_3I/beust-coding-challenge.html" title="Beust Coding Challenge" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>2</thr:total><feedburner:origLink>http://devblog.techhead.biz/2008/07/beust-coding-challenge.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAGQ3s8fCp7ImA9WxVbFkQ.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-7490839069447106286</id><published>2008-07-09T09:28:00.000-07:00</published><updated>2009-04-02T11:25:22.574-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-02T11:25:22.574-07:00</app:edited><title>The Groovy Programming Language</title><content type="html">&lt;p&gt;Long before &lt;a href="http://en.wikipedia.org/wiki/Guice" target="_blank"&gt;Guice&lt;/a&gt;, there was &lt;a href="http://www.picocontainer.org/" target="_blank"&gt;PicoContainer&lt;/a&gt;.  I used to lurk the mailing lists of PicoContainer and the &lt;a href="http://en.wikipedia.org/wiki/Apache_Avalon" target="_blank"&gt;Avalon Framework&lt;/a&gt; project back in the day when &lt;a href="http://en.wikipedia.org/wiki/Inversion_of_Control" target="_blank"&gt;Inversion of Control&lt;/a&gt; (IoC) was a relatively hot topic. (In fact, if you &lt;a href="http://www.google.com/search?hl=en&amp;q=Jonathan+Hawkes" target="_blank"&gt;Google &amp;#8220;Jonathan Hawkes&amp;#8221;&lt;/a&gt; at this time, one of the very few mentions of me is one of my very few posts on the Avalon list.)  However, this article is not intended to be an introduction to IoC.&lt;/p&gt;&lt;p&gt;PicoContainer is how I discovered Groovy.&lt;/p&gt;&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Apache_Ant" target="_blank"&gt;Ant&lt;/a&gt; was at its hayday.  XML was still somewhat of a buzzword (if it is not now).  The folks at the NanoContainer project (PicoContainer&amp;#8217;s big brother) made the (gasp) startling realization that all of the configuration files required by Avalon and the &lt;a href="http://en.wikipedia.org/wiki/Spring_Framework" target="_blank"&gt;Spring framework&lt;/a&gt; &lt;span style="font-style: italic;"&gt;were actually code&lt;/span&gt;.  XML configuration files can be large and unwieldy.  Learning all of the correct tags and attributes can be a more daunting task for a programmer than simply learning a new API. So why not just write configuration code in&amp;#8230; well&amp;#8230; code?&lt;/p&gt;&lt;p&gt;One reason is that it&amp;#8217;s nice to be able to change configuration on the fly, or at least without a recompile.  This is where Groovy comes in.&lt;/p&gt;&lt;p&gt;Groovy is a language for the Java VM.  To call it a scripting language would be somewhat of a misnomer.  Groovy produces Java bytecodes.  It can call Java classes and be called by Java classes.  However, like a scripting language, you can change it.  You don't have to build it. (Unless you want your vanilla Java code to call it in a typesafe manner.)&lt;/p&gt;&lt;p&gt;Groovy essentially extends the syntax of Java.  In most cases, valid Java code will be valid Groovy code.  However, like a scripting language, Groovy does not force you to know the type of an object at &amp;#8220;compile time&amp;#8221;.  It supports closures and lots of other little goodies.&lt;/p&gt;&lt;p&gt;Go check it out.  If you are a Java programmer, you owe it to yourself.&lt;/p&gt;&lt;p&gt;&lt;a href="http://groovy.codehaus.org" target="_blank"&gt;http://groovy.codehaus.org&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-7490839069447106286?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/hr-0wYhK9bM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/7490839069447106286/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2008/07/groovy-programming-language.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/7490839069447106286?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/7490839069447106286?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/hr-0wYhK9bM/groovy-programming-language.html" title="The Groovy Programming Language" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>0</thr:total><feedburner:origLink>http://devblog.techhead.biz/2008/07/groovy-programming-language.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAGQ3s8fCp7ImA9WxVbFkQ.&quot;"><id>tag:blogger.com,1999:blog-4801421103496978728.post-4483064829066735891</id><published>2008-07-09T00:01:00.000-07:00</published><updated>2009-04-02T11:25:22.574-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-02T11:25:22.574-07:00</app:edited><title>What is a TECHHEAD?</title><content type="html">&lt;p id="lq96"&gt;&amp;#8220;When I was a child, I was quite adept at taking things apart.  Putting them back together on the other hand...&amp;#8221;&lt;/p&gt;&lt;p id="lq961"&gt;This is a story I casually tell clients as I have their notebook computer splayed out all over the room.  They think that I am teasing them, and I am in part, but as with most jesting, there lies a kernel of truth.  And the truth is, in my life I have taken apart many more things than I have put back together, caused myself more problems than I have fixed, and started more projects than I have finished.  I find that learning is bold, messy, and full of unforeseen consequences.  Mine is a tale of learning. &lt;/p&gt;&lt;p id="en6.1"&gt;My name is Jonathan Hawkes, and I am a TECHHEAD.&lt;/p&gt;&lt;p id="a..61"&gt;I began my odyssey into computer programming when I was seven years old. I started out by writing simple games in &lt;a title="BASIC" target="_blank" href="http://en.wikipedia.org/wiki/BASIC_programming_language" id="m2ds"&gt;BASIC&lt;/a&gt; on my friend&amp;#8217;s &lt;a title="Commodore 64" target="_blank" href="http://en.wikipedia.org/wiki/Commodore_64" id="vpb4"&gt;Commodore 64&lt;/a&gt;. We would spend the better hours of the day punching away at the integrated keyboard, testing, modifying and testing again. We would draw out &lt;a title="sprites" href="http://en.wikipedia.org/wiki/Sprite_%28computer_graphics%29" id="j9gn"&gt;sprites&lt;/a&gt; onto graph paper, convert our makeshift bitmap into hexadecimal, input the figures into our program and enjoy the fruits of our hard-earned artistic labor. Then long after sundown, we would give a simple salute, power down the machine, and say a solemn goodbye to our wasted day&amp;#8217;s effort. (At that time, my friend had no &lt;a title="floppy drive" href="http://en.wikipedia.org/wiki/Floppy_drive" id="gqyv"&gt;floppy drive&lt;/a&gt;.)&lt;/p&gt;&lt;p id="qdvr1"&gt;The subsequent years passed in similar fashion.  Games, robots, lasers, etc. &amp;#8212; Some were built; all were taken apart; few survived.  &lt;a title="BBS" target="_blank" href="http://en.wikipedia.org/wiki/Bulletin_board_system" id="n-7s"&gt;BBS&lt;/a&gt;s were the primary mode of communication. &lt;a title="L.O.R.D." target="_blank" href="http://en.wikipedia.org/wiki/Legend_of_the_Red_Dragon" id="k.zg"&gt;L.O.R.D.&lt;/a&gt; and &lt;a title="TradeWars" target="_blank" href="http://en.wikipedia.org/wiki/Trade_Wars" id="mtz3"&gt;TradeWars&lt;/a&gt; rocked. &lt;a title="Apogee" target="_blank" href="http://en.wikipedia.org/wiki/Apogee_Software" id="hf2k"&gt;Apogee&lt;/a&gt; was the coolest company &lt;i id="jzlk"&gt;ever&lt;/i&gt;.&lt;/p&gt;&lt;p id="c3yo1"&gt;Then Al Gore said, &amp;#8220;Let there be internet.&amp;#8221; And there was internet. The local college had a dial-up gateway that would allow terminal-based access to &lt;a title="Gopher" target="_blank" href="http://en.wikipedia.org/wiki/Gopher_%28protocol%29" id="ppqr"&gt;Gopher&lt;/a&gt;, &lt;a title="Usenet" target="_blank" href="http://en.wikipedia.org/wiki/Usenet" id="pfeu"&gt;Usenet&lt;/a&gt; and the WWW (through the &lt;a title="Lynx" target="_blank" href="http://en.wikipedia.org/wiki/Lynx_%28web_browser%29" id="eh9y"&gt;Lynx&lt;/a&gt; browser). Way cool.  I would page through binary Usenet groups while capturing output to a text file within HyperTerminal.  I wrote a &lt;a title="UUEncoder" target="_blank" href="http://en.wikipedia.org/wiki/UUEncode" id="myg1"&gt;UUEncoder&lt;/a&gt;/Decoder in &lt;a title="C" target="_blank" href="http://en.wikipedia.org/wiki/C_%28programming_language%29" id="oy72"&gt;C&lt;/a&gt; and had instant access to a far larger range of games and other content than any BBS to which I had been a member.&lt;/p&gt;&lt;p id="pl2g1"&gt;More years passed. My family subscribed to a &amp;#8220;real&amp;#8221; dial-up account.  It came with a finite amount of hosted web space and &lt;a title="CGI" target="_blank" href="http://en.wikipedia.org/wiki/Common_Gateway_Interface" id="d4.7"&gt;CGI&lt;/a&gt; access.  Bingo.  I soon discovered that &lt;a title="Perl" target="_blank" href="http://en.wikipedia.org/wiki/Perl" id="hpik"&gt;Perl&lt;/a&gt; was more suited to the challenge of building web applications than C, and my first Perl project was a sort of simple &lt;a title="wiki" target="_blank" href="http://en.wikipedia.org/wiki/Wiki" id="h703"&gt;wiki&lt;/a&gt; (circa 1995) called the ScrawlWall (which was just a text box that anyone could modify and save to leave a short note or &lt;a title="ASCII art" target="_blank" href="http://en.wikipedia.org/wiki/ASCII_art" id="vhs."&gt;ASCII art&lt;/a&gt;).  That same year, I also developed an &lt;a title="AJAX" target="_blank" href="http://en.wikipedia.org/wiki/Ajax_%28programming%29" id="in.2"&gt;AJAX&lt;/a&gt; precursor, the &lt;a title="JavaScript" target="_blank" href="http://en.wikipedia.org/wiki/JavaScript" id="d6xw"&gt;JavaScript&lt;/a&gt; ScrawlWall, which could be saved and loaded without ever leaving the page.  Before shutting the project down in 1998, I hosted over 8,000 ScrawlWalls.&lt;/p&gt;&lt;p id="e13e0"&gt;After that began my career.  As an independent contractor, I developed numerous web sites as well as a (then impressive) cross-browser &lt;a title="DHTML" target="_blank" href="http://en.wikipedia.org/wiki/DHTML" id="r3hk"&gt;DHTML&lt;/a&gt; library called Pane DOM.  This was back when &lt;a title="Netscape Navigator" target="_blank" href="http://en.wikipedia.org/wiki/Netscape_Navigator" id="r5ji"&gt;Netscape Navigator&lt;/a&gt; only allowed manipulation of content through &amp;#8220;layers&amp;#8221; and &lt;a title="Internet Explorer" target="_blank" href="http://en.wikipedia.org/wiki/Internet_Explorer" id="in_:"&gt;Internet Explorer&lt;/a&gt; had much of the same limited capabilities that it does now.  Being as impressive of a (still) teenager as I was, I was offered a full-time job by one of my clients. I was newly married (Yikes! Kids these days), so I jumped at the opportunity.  This was near the time the first dot com bubble burst.  My company proceeded to sink over 3 million dollars into advertising and not a tenth of that into development.  Though we had an economic development grant of over a half a million, the plug was pulled on our project before we ever had a finished product (or spent the money). Brilliant!&lt;/p&gt;&lt;p id="j5_41"&gt;However my boss, who was one of those really great guys you work for once in a lifetime, managed to keep the team working for a while on various other projects (with remarkably similar outcomes).  In the end, we did manage a &lt;a title="Cobol" target="_blank" href="http://en.wikipedia.org/wiki/Cobol" id="h0ur"&gt;Cobol&lt;/a&gt;-to-&lt;a title="Java" target="_blank" href="http://en.wikipedia.org/wiki/Java_%28programming_language%29" id="fe4h"&gt;Java&lt;/a&gt; rewrite of a popular online commodity futures and options trading platform.  And I led the development and maintenance for a number of years.&lt;/p&gt;&lt;p id="smpm0"&gt;&lt;i id="jhhq1"&gt;Salute. Power down. Say goodbye. &lt;/i&gt;&lt;/p&gt;&lt;p id="smpm3"&gt;The problem with having a job that requires your mind is that when you lose your mind, your job will soon follow.  So once my project no longer required my guardianship, and I could no longer stand the sight of it, I did what any reasonable person would do.  I quit my well-paying job and became a professional ski patroller. &lt;/p&gt;&lt;p id="h9sw1"&gt;For any other kind of person, this may have been the end of the story.  But for a select few there will always be a draw, an inexplicable force that compels one to the soft glow of a computer display and the distinctly stale aroma of the great indoors.  So a number of years later, I traded in my ski boots for house shoes and returned to the home office.  Thus TECHHEAD was (re)born. &lt;/p&gt;&lt;p id="uusc4"&gt;Are you seeing a pattern here?  I am a firm believer in reincarnation.  I just believe that we have one lifetime in which to accomplish it.  So now I am back where I started.  But I am learning.  I am building.  And starting with this, my first blog post, I am sharing.  Today I hope to build something truly great, scrap it, and start again tomorrow with the same enthusiasm and perhaps just a little bit wiser.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4801421103496978728-4483064829066735891?l=devblog.techhead.biz' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TECHHEADDevelopmentBlog/~4/ly9Q3ja_YiI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://devblog.techhead.biz/feeds/4483064829066735891/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://devblog.techhead.biz/2008/07/what-is-techhead.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/4483064829066735891?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4801421103496978728/posts/default/4483064829066735891?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TECHHEADDevelopmentBlog/~3/ly9Q3ja_YiI/what-is-techhead.html" title="What is a TECHHEAD?" /><author><name>TECHHEAD</name><uri>http://www.blogger.com/profile/18441232171642024472</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="06887737144991222694" /></author><thr:total>1</thr:total><feedburner:origLink>http://devblog.techhead.biz/2008/07/what-is-techhead.html</feedburner:origLink></entry></feed>
