<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Joe McCann - Interaction, Interface, &amp; Web Designer</title>
	
	<link>http://www.subprint.com/blog</link>
	<description>User Interface Extraordinaire Without The Ego</description>
	<lastBuildDate>Fri, 23 Apr 2010 16:48:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/subPrintBlog" /><feedburner:info uri="subprintblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Why jQTouch is Rad, But Won’t Last</title>
		<link>http://feedproxy.google.com/~r/subPrintBlog/~3/PbvvfJczx-o/</link>
		<comments>http://www.subprint.com/blog/why-jqtouch-is-rad-but-won%e2%80%99t-last/#comments</comments>
		<pubDate>Fri, 23 Apr 2010 03:20:07 +0000</pubDate>
		<dc:creator>joemccann</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Posts]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[webapp]]></category>

		<guid isPermaLink="false">http://www.subprint.com/blog/?p=339</guid>
		<description><![CDATA[Recently at jsConf, @sintaxi (of @phonegap fame) said in a Track B talk (and I’m paraphrasing here), “the best thing you can do now for mobile development is to make a mobile website or webapp.” Now, these words were intended not so much as for what the title of this article implies, but more for [...]]]></description>
			<content:encoded><![CDATA[<p>Recently at <a href="http://jsconf.us/2010/">jsConf</a>, <a href="http://twitter.com/sintaxi">@sintaxi</a> (of <a href="http://twitter.com/phonegap">@phonegap</a> fame) said in a Track B talk (and I’m paraphrasing here), “the best thing you can do now for mobile development is to make a mobile website or webapp.” Now, these words were intended not so much as for what the title of this article implies, but more for the whole issue surrounding the changes to the <a href="http://daringfireball.net/2010/04/iphone_agreement_bans_flash_compiler">ToS that Apple recently announced</a> in regards to using other means for creating iPhone apps.  Regardless of the context of why he was making this recommendation, it still is something with which I totally agree, but for a different reason, and that is wherein jQTouch comes.</p>
<p><a href="http://www.jqtouch.com/">jQTouch</a> is an amazing project spearheaded by <a href="http://twitter.com/davidkaneda">@davidkaneda</a> and has been promoted by many people including <a href="http://twitter.com/jonathanstark">@jonathanstark</a>.  jQTouch, if you ain’t know, is a JavaScript library dependent on jQuery and is intended for making mobile webapps targetted for the iPhone.  jQTouch is an absolutely brilliant piece of work where one can take the default project, modify the index.html with their markup, change some simple JavaScript, and within minutes one has a mobile webapp that looks like a native iPhone app.  I have used jQTouch for rapid prototyping efforts and have been repeatedly blown away at how fast I can take a concept and have it “working” on an iPhone in such a short amount of time.</p>
<p>However, jQTouch, is only for building something that is specifically targeted for the iPhone.  That approach, in my opinion, is flawed.  The browsing experience of a jQTouch webapp on an Android device is awkward at best and crashes the browser altogether at worst.  jQTouch will be similar to the problem that arose when people were building webapps where Internet Explorer was required and was “best viewed in a 1024px x 768px” screen resolution.  We all know how successful that approach was.</p>
<p>In my opinion, one needs to design, architect, and develop sites, apps, and experiences, universally.  That is not to say you can’t take advantage of some of the cool things the iPhone browser has over some of the other devices’ browsers (hardware accelerated transitions FTMFW), but note that creating a mobile webapp that is supposed to simulate a native iPhone experience creates at best, a lackluster experience for (almost) all the other internet friendly mobile devices.</p>
<p>Moreover, Android’s market share is <a href="http://arstechnica.com/apple/news/2010/03/iphone-still-second-place-us-smartphone-while-android-grows.ars">rising</a>&#8230;<a href="http://www.wirefresh.com/android-scores-huge-gains-in-the-us-iphone-stalls/">fast</a>.  iPhone’s market share is not that safe. Why? iPhone is a device.  Android is a platform for devices.  There will be thousands of Android devices by this time next year. There will still only be one iPhone.  Moreover, Palm, Blackberry, and Nokia appear to be moving to webkit as well.  Do you really want your mobile webapp to look like an iPhone app on a Blackberry Curve?</p>
<p>And if you needed more proof that providing a &#8220;native iPhone mobile app experience&#8221; for all mobile apps is the wrong approach, look no further than a <a href="http://www.readwriteweb.com/archives/mobile_app_or_browser-based_site.php">recent article</a> on ReadWriteWeb where mobile stat guru, <a href="http://www.taptu.com/corp/">Taptu</a>, explains the future of the web is to be dominated by cross-platform based mobile websites that are &#8220;mobile web touch-friendly&#8221;.  So while it currently may be trendy to design and develop strictly for the iPhone (because it dominates in <a href="http://connect.icrossing.co.uk/wp-content/uploads/2010/02/mobile-market-share.gif">mobile browsing market share</a>), one may be shooting one&#8217;s self in the foot in the process.  Moreover, with so many various touch screen devices coming to market from the iPad to Archos, Acer, the HP Slate, and various Android and Chrome OS tablets, doesn&#8217;t it make sense to design and develop for various mobile platforms that support touch events?  Why limit yourself to the experience that is only on the iPhone? </p>
<p>But Joe, I only want to design for the iPhone.  Great!  Meanwhile me and the rest of the world will be designing for iPhone and everybody else.  But Joe, jQTouch makes it so easy!  I know, suck it up and build your own framework.  Get smarter, get better, design something, destroy it, start all over, and then do that again.  Now you are ready for the mobile web. </p>
<img src="http://feeds.feedburner.com/~r/subPrintBlog/~4/PbvvfJczx-o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.subprint.com/blog/why-jqtouch-is-rad-but-won%e2%80%99t-last/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.subprint.com/blog/why-jqtouch-is-rad-but-won%e2%80%99t-last/</feedburner:origLink></item>
		<item>
		<title>Nexus One Review From a Programmer and UI Engineer’s Perspective</title>
		<link>http://feedproxy.google.com/~r/subPrintBlog/~3/Eoo3UtNHVVw/</link>
		<comments>http://www.subprint.com/blog/nexus-one-review-from-a-programmer-and-ui-engineers-perspective/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 15:22:03 +0000</pubDate>
		<dc:creator>joemccann</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Posts]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[N1]]></category>
		<category><![CDATA[Nexus]]></category>
		<category><![CDATA[Nexus1]]></category>
		<category><![CDATA[One]]></category>

		<guid isPermaLink="false">http://www.subprint.com/blog/?p=298</guid>
		<description><![CDATA[Ahh, the Nexus One, the gadget the interweb is all aflutter about. There have been countless reviews at this time but you won&#8217;t find the typical &#8220;former iPhone 3G-S user switching to Android-based Nexus One&#8221; review here, where in my opinion, they don&#8217;t &#8220;get it&#8221; from a developer or UI engineer&#8217;s perspective. If you want [...]]]></description>
			<content:encoded><![CDATA[<p>Ahh, the Nexus One, the gadget the interweb is all aflutter about.  There have been countless reviews at this time but you won&#8217;t find the typical &#8220;former iPhone 3G-S user switching to Android-based Nexus One&#8221; review here, where in my opinion, they don&#8217;t &#8220;get it&#8221; from a developer or UI engineer&#8217;s perspective.  If you want to read something like that head over to <a href="http://gizmodo.com/5443835/nexus-one-review?skyline=true&amp;s=i">Gizmodo</a>.  The following post is not a review about the sleekness of the phone&#8217;s chassis or any comparisons to the iPhone (I think one is missing it entirely if they are trying to compare the Nexus One to iPhone, but that&#8217;s a separate blog post), no, the following review is what I think is good and bad about the Nexus One from a programmer&#8217;s perspective and a UI engineer&#8217;s perspective as I like to think of myself as both.</p>
<p>Disclaimer:  I have had a G1 since October 2008 and have developed a few Android apps (none publicly released yet, but soon will be).  The majority of my bias may come from the upgrade to the Android source (2.1 as of this writing) coupled with a number of hardware related upgrades.</p>
<h2>Pros</h2>
<ul class="padTopTen inside">
<li><a href="http://www.qualcomm.com/products_services/chipsets/snapdragon.html">Snapdragon</a> 1Ghz processer&#8217;s snappy-ness</li>
<li>The orientation change&#8217;s (switching from landscape to portrait and vice versa) responsiveness</li>
<li>The screen&#8217;s clarity and fidelity</li>
<li>Five pages/screens of &#8220;home desktop&#8221; real estate</li>
<li>Voice commands for nearly everything</li>
<li>5MP Camera with LED Flash</li>
<li>Video recording in MPEG-4 quality</li>
<li>Navigation mode with Street View</li>
<li>Live Wallpapers</li>
<li>Auto-adjusting display brightness</li>
</ul>
<h2>Cons</h2>
<ul class="padTopTen inside">
<li>Haptic response keys&#8217; awkward experience</li>
<li>No orientation change on home screen(s) plus a bug when attempting to do so</li>
<li>Power button only means of &#8220;awaking&#8221; the device</li>
<li>Gallery application interaction issues</li>
<li>Unlock screen&#8217;s awkward &#8220;slide&#8221; gesture</li>
<li>Text input in landscape mode&#8217;s poor experience</li>
</ul>
<h2>Programmer&#8217;s Perspective</h2>
<p>By seeing such features as the Navigation and even the street views available in Google Maps, I have become motivated to start utilizing those APIs or consider using some of the additional features of the Android SDK that I did not consider before, mainly because the phone itself is fast enough at rendering something like Streetview in a rather seamless fashion.  Seeing what Google has done with some of their own apps, coupled with the overall speed improvements between orientation changes inspires me no longer worry about programming against a poor experience. However, the speech-to-text feature, and its inclusion in nearly all of the input fields on the device, gave me glimpse into the future of Google&#8217;s approach to allowing that faster mobile processor to remain just that:  fast.</p>
<p>The speech-to-text feature processes all its data in the cloud.  This concept is not something that should be taken lightly.  The processing power needed to handle something as complex as speech-to-text recognition would bring the 1Ghz Snapdragon chip to a crawl.  However, Android, and more importantly Google is relying on this processing to take place elsewhere (the cloud) and instead rely on the data transfer (and the subsequent data networks) and ultimately the speed of the transfer to create a seamless and pleasant user experience.</p>
<p>The text-to-speech feature is not unique to the Nexus One, but its pervasiveness across input types is (so far).  Furthermore, the front and back microphones (for improved noise cancellation) installed on the Nexus One shows a commitment of sorts toward the idea of &#8220;more speaking, less typing&#8221;.  This is inspiring from a programmer&#8217;s perspective for if Google does in fact adapt this model for let&#8217;s say something like, potentially the managing, streaming, or recording of 3-D camera data, and <em>they</em> handle the intensive processing, but <em>we</em> simply receive back data, then the sky (or cloud) is the limit.  The services provided by Google (or potentially other cloud-processing/SaaS vendors) would offload the heavy lifting for programmers so the programmers can focus on creating bleeding edge apps without worrying about the processor&#8217;s ability to crunch loads of data.  This, from my perspective, is huge.</p>
<h2>UI Engineer&#8217;s Perspective</h2>
<p>Where to begin.  The richness and clarity of the screen is enough to make any UI engineer anxious to create an app that simply cycles through RGB values.  The <a href="http://en.wikipedia.org/wiki/Active-matrix_OLED">AMOLED</a> screen is now more like a canvas.  This not only provides obvious benefits for the visual designer but can also pose a problem in regards to fragmentation across devices&#8217; screen resolutions.  I think we&#8217;ve dealt with issues like this <a href="http://russharvey.bc.ca/resources/pixels.html">before</a>.</p>
<p>The new animations and simulated 3-D environments across many of the apps including the &#8220;Starwars&#8221; rollover effect for the Home screen lend to the notion of more animations coming available to the UI designer.  The Android SDK comes packaged with some <a title="Android Animation API Demos" href="http://developer.android.com/resources/samples/ApiDemos/index.html" target="_self">preset animations</a>, but it is interesting to see how Google is using some of the newer animations/transitions on the Nexus One running Android 2.1.</p>
<p>Google has also paid attention to even subtle improvements at interactions with the UI at the application level.  For example, the browser <em>renders</em> pages much faster and if the page is a standard site, not a mobile version, it shows the page in nearly in full with the ability of double-tapping to zoom in to the area you wish to see at a more granular level.  The double-tap is <em>way</em> more intuitive than the earlier quasi-magnifying glass click then drag and release awkward interaction.  Note, this interaction is an Android 2.0 version improvement, not unique to the Nexus One (Motorola Droid).</p>
<p>I would be remiss not discuss the newest bit of eye candy for the UI engineers:  Live Wallpapers.  The live, moving, seemingly breathing wallpapers that shipped with the Nexus One are definitely the first thing one notices when you turn on the Nexus One.  Not only are the wallpapers animated and full of color, but that are fully interactive as well.  For example, the &#8220;rippling water&#8221; live wallpaper not only has leaves falling onto the pool of water thus causing a rippling effect, but a tap anywhere on the desktop of the home screen not occupied by an app or widget shortcut triggers the same rippling effect as if you had actually touched the water.  How <em>practical</em> and useful is something like this?  Well not so much.  What is important is the fact the the animation library <a title="Processing's Website" href="http://processing.org/" target="_self">Processing</a> was used on a couple of the early prototypes (<a title="Live Wallpapers Created with Processing Java Class" href="http://www.curious-creature.org/2010/01/07/nexus-one-live-wallpapers/" target="_self">according to Romain Guy</a>) and an API for developing live wallpapers is <a title="Diane Hackborn's Response on 2.1 Release" href="http://groups.google.com/group/android-developers/browse_thread/thread/4361cc5e2ca44969?pli=1" target="_self">due out</a> in the Android 2.1 SDK release.  The potential for using Google&#8217;s version of a Processing-like class for <em>other </em>uses than actually making live wallpapers is really inspiring.</p>
<h2>Final Analysis</h2>
<p>Most of what the Nexus One offers as a mobile smart/superphone is not anything game-changing for the device itself or the mobile smart/superphone market.  Yet, the Nexus One is not just another smartphone, but more of a showcase of what the Android platform is <strong>capable of doing</strong>.  Given the right hardware and knowledge of the Android platform (and potentially C and/or Linux), vendors and developers can create <em>Android-based devices </em>with the ability of being game-changing or even create new categories for devices altogether.  A touchscreen tablet for web browsing?  E-readers?  Live TV-streaming devices that fit in your pocket?  All of these are possible.  However, to simply compare the Nexus One next to an iPhone, Palm Pre, or any other slew of mobile smartphone devices, is not, in my opinion the correct comparison.  Android is to mobile what Windows is to desktop PCs.  The Nexus One just happens to have a telephony as a feature of this mobile device.</p>
<img src="http://feeds.feedburner.com/~r/subPrintBlog/~4/Eoo3UtNHVVw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.subprint.com/blog/nexus-one-review-from-a-programmer-and-ui-engineers-perspective/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.subprint.com/blog/nexus-one-review-from-a-programmer-and-ui-engineers-perspective/</feedburner:origLink></item>
		<item>
		<title>Viewing Web Pages Locally on Android’s Emulator</title>
		<link>http://feedproxy.google.com/~r/subPrintBlog/~3/V1HiBygRuDE/</link>
		<comments>http://www.subprint.com/blog/viewing-web-pages-locally-on-androids-emulator/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 00:37:03 +0000</pubDate>
		<dc:creator>joemccann</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Posts]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[lawnchair]]></category>
		<category><![CDATA[titanium]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[windows7]]></category>
		<category><![CDATA[xui]]></category>

		<guid isPermaLink="false">http://www.subprint.com/blog/?p=290</guid>
		<description><![CDATA[I am doing some hacking with Android and building an app using various open source technologies such as lawnchair, xui, and Titanium and came to a point where I needed to simply view a web page that was running locally on my development machine, in my case on the localhost .  So after launching the [...]]]></description>
			<content:encoded><![CDATA[<p>I am doing some hacking with Android and building an app using various open source technologies such as <a title="Lawnchair" href="http://brianleroux.github.com/lawnchair/" target="_self">lawnchair</a>, <a title="XUI" href="http://xuijs.com" target="_self">xui</a>, and <a title="Titanium" href="http://www.appcelerator.com/" target="_self">Titanium</a> and came to a point where I needed to simply view a web page that was running locally on my development machine, in my case on the <code>localhost</code> .  So after launching the Android emulator and opening the browser, I tried typing in <code>http://localhost</code>, <code>http://localhost:8000</code>, and even the IP address <code>http://127.0.0.1</code> but all to no avail.</p>
<p>So after doing some digging I found an <a title="Android Hosts File" href="http://sacoskun.blogspot.com/2009/06/configure-hosts-file-in-android.html" target="_self">article</a> somewhat related that called for modifying your hosts file.  However, this didn&#8217;t work for me either.</p>
<p>So it was onto Android&#8217;s online documentation.  Yikes, I know.  Nonetheless, I found EXACTLY what I was looking for almost immediately.  According to the authors of <a title="Android Networking Limitations on Emulator" href="http://developer.android.com/guide/developing/tools/emulator.html#networkinglimitations" target="_self">this section</a> of the documentation<a title="Android Networking Limitations on Emulator" href="http://developer.android.com/guide/developing/tools/emulator.html#networkinglimitations" target="_self"><br />
</a></p>
<blockquote><p>Each instance of the emulator runs behind a virtual router/firewall service that isolates it from your development machine&#8217;s network interfaces and settings and from the internet. <strong>An emulated device can not see your development machine or other emulator instances on the network.</strong> Instead, it sees only that it is connected through Ethernet to a router/firewall.</p></blockquote>
<p>As it turns out the virtual router that is running actually has its own internal loopback interface which is the same as the loopback interface address on my development machine, <code>127.0.0.1</code>.  However, the key is the special alias that the virtual router provides to your localhost&#8217;s loopback interface, that address is <code>10.0.2.2</code>.</p>
<p>So just type <code>http://10.0.2.2</code> into the browser from the Android emulator and you&#8217;ll be requesting from <code>http://127.0.0.1</code> on your development machine.</p>
<img src="http://feeds.feedburner.com/~r/subPrintBlog/~4/V1HiBygRuDE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.subprint.com/blog/viewing-web-pages-locally-on-androids-emulator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.subprint.com/blog/viewing-web-pages-locally-on-androids-emulator/</feedburner:origLink></item>
		<item>
		<title>Distributed Collaboration – Building a Website Remotely</title>
		<link>http://feedproxy.google.com/~r/subPrintBlog/~3/Hgg01o3Mb7Y/</link>
		<comments>http://www.subprint.com/blog/distributed-collaboration-building-a-website-remotely/#comments</comments>
		<pubDate>Mon, 31 Aug 2009 20:05:56 +0000</pubDate>
		<dc:creator>joemccann</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[collaboration]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[distributed]]></category>
		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://www.subprint.com/blog/?p=153</guid>
		<description><![CDATA[Just recently, a great friend, and an even better visual designer, Brendan Finlayson (@brendanfin) and I have been working on helping each other out with some side projects we both have to complete. Namely, I would like him to skin me a new UI for my site and he would like me to assist in [...]]]></description>
			<content:encoded><![CDATA[<p>Just recently, a great friend, and an even better visual designer, <a href="http://www.refunktion.com">Brendan Finlayson</a> (<a href="http://twitter.com/brendanfin">@brendanfin</a>) and I have been working on helping each other out with some side projects we both have to complete.  Namely, I would like him to skin me a new UI for my site and he would like me to assist in developing his online portfolio.  <a href="http://en.wikipedia.org/wiki/Nothing%27s_Shocking">Nothing Shocking</a> there except that I live in Austin and he lives in Oakland.  Before the days of high-speed connections and standards-compliant browsers this sort of scenario could take weeks to complete.</p>
<p>Not anymore, with applications like <a href="https://www.getdropbox.com/referrals/NTQwOTQyOTk">Dropbox</a>, <a href="http://xampp.org">XAMPP</a>, <a href="http://www.digsby.com">Digsby</a>, and <a href="http://www.skype.com">Skype</a>, and using them together in methods that exploit their awesome utility when combined.</p>
<h2>Dropbox</h2>
<p>For those of you that aren&#8217;t familiar with Dropbox, in a nutshell, Dropbox is the easiest way to share and store your files online.  It works on any platform as well.  Brendan has a Mac and I have a PC and it works flawlessly on both of our machines.  Let&#8217;s say you have a home desktop computer, a personal laptop, a work laptop, and a work desktop computer.  Once you install Dropbox&#8217;s application on each of those computers, you will have access to any files you store in your &#8220;My Dropbox&#8221; folder on any of the computers.  For example, say you have a TPS Report that you save in your &#8220;My Dropbox&#8221; folder on your work desktop computer.  With Dropbox running on each of the other three computers, they each will automagically have that same file stored in their &#8220;My Dropbox&#8221; folder as well.  Moreover, say you get home and on your personal laptop you make a change to the file.  The delta (the difference or change to the file) is the only thing uploaded to your Dropbox account and a revision is created for that save (or in subversion terms &#8220;commit&#8221;).  Now, that file on every other computer is automagically updated with the new version of the file.  If you need to revert back to a previous file version, just open up the revision that you need.  Simply brilliant.</p>
<p>Now, one of the coolest features for Dropbox is that you can create a folder and share that entire folder with anyone you invite.  For example, I created a folder called &#8220;joe_paddy&#8221; (Paddy is Brendan&#8217;s nickname), right-clicked on the folder and under the Dropbox menu selected &#8220;Sharing Options&#8221;.</p>
<div id="attachment_167" class="wp-caption alignleft" style="width: 610px"><a href="http://www.subprint.com/blog/wp-content/uploads/2009/05/dc_sharing_folder_dropbox.jpg"><img class="size-full wp-image-167" title="dc_sharing_folder_dropbox" src="http://www.subprint.com/blog/wp-content/uploads/2009/05/dc_sharing_folder_dropbox.jpg" alt="Sharing Options with Dropbox" width="600" height="380" /></a><p class="wp-caption-text">Sharing Options with Dropbox</p></div>
<p>My browser then immediately opened up my Dropbox account page where this folder, &#8220;joe_paddy&#8221;, resides.  On this page, there is a box where I simply add Brendan&#8217;s email address to invite him, but, I could have invited as many people as I wanted to have access to the folder, granted they each have a Dropbox account.  Upon accepting my invitation, the folder &#8220;joe_paddy&#8221; was instantly created on his computer.</p>
<div id="attachment_168" class="wp-caption alignleft" style="width: 610px"><a href="http://www.subprint.com/blog/wp-content/uploads/2009/05/dc_sharing_folder_dropbox_email.jpg"><img class="size-full wp-image-168" title="dc_sharing_folder_dropbox_email" src="http://www.subprint.com/blog/wp-content/uploads/2009/05/dc_sharing_folder_dropbox_email.jpg" alt="Sharing Folder via Email Address in Dropbox" width="600" height="467" /></a><p class="wp-caption-text">Sharing Folder via Email Address in Dropbox</p></div>
<p>The beauty of this is now Brendan, the visual designer, can work directly out of the &#8220;joe_paddy&#8221; folder and I will receive any/all files and changes to those files in nearly real-time.  On the flip side, since I&#8217;m the one building out the web pages (HTML via PHP, CSS, and JavaScript), any changes I make are reflected immediately on his computer as well.  But Joe, he can&#8217;t just open a PHP file and it render in a browser, it needs to be served up from a well, server!  That&#8217;s where XAMPP comes in.</p>
<h2>XAMPP</h2>
<p>XAMPP is an easy to install Apache distribution containing MySQL, PHP and Perl. XAMPP is really very easy to install and to use &#8211; just download, extract and start.  Currently, XAMPP is available for Windows, OS X, Linux, and Solaris.  XAMPP assists with a distributed collaboration environment when it is <em>coupled</em> with the use of Dropbox.</p>
<p>For example, Brendan and I are collaborating on a website right now.  He is handling the design composition in Photoshop, slicing up images, and creating a style guide.  If you don&#8217;t currently use a style guide in your projects, I highly recommend you do.  In a nutshell, it is a document combining all typefaces, typeface sizes, and typeface colors and colors for other elements (e.g. background color) used in the design composition so the developer doesn&#8217;t have to refer to anything but the style guide when hashing out the CSS.  Okay, so back to the example, Brendan is doing the visual stuff and I am building out the pages in PHP.  Now, if I am making a change to the PHP file and I want Brendan to be able to open a browser and see the webpage in its current state, he can&#8217;t do this without a server running.  He installs XAMPP for his platform, OS X, and he now has a &#8220;local&#8221; server up and running, http://localhost/.  However, the default <a href="http://httpd.apache.org/docs/1.3/configuring.html">httpd.conf</a> file has the document root set to the htdocs folder under the XAMPP install folder.  On Windows, that location is here:  C:\xampp\htdocs.  Unfortunatey, we don&#8217;t want to see XAMPP&#8217;s local site that is bundled with the application, we want to see <em>our</em> site that we are working on.</p>
<p>At this point, I opened the httpd.conf file and found the lines that I needed to modify in order to point the document root to the directory of where I&#8217;m building the site out.  First line is of course, the <code>DocumentRoot</code> setting.  The value for the <code>DocumentRoot</code> should be the full path to the folder that is where I am building the web pages.  This path contains my &#8220;My Dropbox&#8221; folder.</p>
<div id="attachment_172" class="wp-caption alignleft" style="width: 610px"><a href="http://www.subprint.com/blog/wp-content/uploads/2009/05/dc_xampp_conf1.jpg"><img class="size-full wp-image-172" title="dc_xampp_conf1" src="http://www.subprint.com/blog/wp-content/uploads/2009/05/dc_xampp_conf1.jpg" alt="httpd.conf DocumentRoot Setting" width="600" height="132" /></a><p class="wp-caption-text">httpd.conf DocumentRoot Setting</p></div>
<p>The only other line I needed to change was the <code>&lt;Directory&gt;</code> setting as it was pointing to the htdocs folder under the XAMPP install directory and instead needs to be pointing</p>
<div id="attachment_176" class="wp-caption alignleft" style="width: 610px"><a href="http://www.subprint.com/blog/wp-content/uploads/2009/05/dc_xampp_conf2.jpg"><img class="size-full wp-image-176" title="dc_xampp_conf2" src="http://www.subprint.com/blog/wp-content/uploads/2009/05/dc_xampp_conf2.jpg" alt="httpd.conf Setting for Proper Directory Path" width="600" height="534" /></a><p class="wp-caption-text">httpd.conf Setting for Proper Directory Path</p></div>
<p>After making these two changes to my httpd.conf file, I save it, close it, and restart Apache using XAMPP&#8217;s slick control panel.  Simply stop Apache&#8230;</p>
<div id="attachment_178" class="wp-caption alignleft" style="width: 508px"><a href="http://www.subprint.com/blog/wp-content/uploads/2009/05/dc_xampp_control_panel_stop.jpg"><img class="size-full wp-image-178" title="dc_xampp_control_panel_stop" src="http://www.subprint.com/blog/wp-content/uploads/2009/05/dc_xampp_control_panel_stop.jpg" alt="XAMPP Control Panel - Stop Apache Service" width="498" height="320" /></a><p class="wp-caption-text">XAMPP Control Panel - Stop Apache Service</p></div>
<p>&#8230;then start it,</p>
<div id="attachment_179" class="wp-caption alignleft" style="width: 508px"><a href="http://www.subprint.com/blog/wp-content/uploads/2009/05/dc_xampp_control_panel_start.jpg"><img class="size-full wp-image-179" title="dc_xampp_control_panel_start" src="http://www.subprint.com/blog/wp-content/uploads/2009/05/dc_xampp_control_panel_start.jpg" alt="XAMPP Control Panel -- Start Apache Service" width="498" height="323" /></a><p class="wp-caption-text">XAMPP Control Panel -- Start Apache Service</p></div>
<p>&#8230;then navigate to <a rel="nofollow" href="http://localhost/">http://localhost/</a> in your browser and voilà, I am now able to see the website on my local server.</p>
<p>In most cases, trying to get a designer to modify an httpd.conf file can be very difficult, mainly because they are not as technical as developers.  Not a problem in our case, for using Digsby as my instant messenger client I am easily able to direct Brendan on what lines in the httpd.conf file need to be modified.</p>
<h2>Digsby (and Adium and Skype)</h2>
<p><a href="http://www.digsby.com"><img class="alignleft size-thumbnail wp-image-200" title="1232386015_digsby_833x833" src="http://www.subprint.com/blog/wp-content/uploads/2009/06/1232386015_digsby_833x833-150x150.png" alt="1232386015_digsby_833x833" width="150" height="150" /></a><a href="http://www.digsby.com">Digsby</a> is an all encompassing instant messaging, email, and social networking client that I have found to be incredibly stable and abundantly useful for not only instant messaging, but keeping up with new emails in my Gmail account, new message on Facebook, LinkedIn, Myspace, etc.  Digsby is a one stop shop for all of my communication needs.</p>
<p>After adding my GTalk account to Digsby (and after Brendan installed XAMPP on his Mac), I was able to communicate directly with Brendan and guide him through the httpd.conf file in order for him to modify the two lines of code needed to point to the folder we were sharing to build the website.  Moreover, we were then actually able to collaborate and make changes in near real-time.  For example, if we are looking at the &#8220;About&#8221; page of this particular website, he can tell me that the border of an image needs to be red.  I simply make the change in the proper CSS file, save that CSS file, then have Brendan reload <em>his</em> browser and BAM, the image has the border.  The magic lies in the fact that Dropbox only uploads and subsequently downloads the delta (what was saved in the CSS file), not the entire file!</p>
<p>If you&#8217;re on a Mac, I hear <a href="http://adium.im/">Adium</a> is a great instant messaging solution.</p>
<p><a href="http://www.skype.com"><img alt="" src="http://c.skype.com/i/images/logos/skype_logo.png" title="Skype" class="alignleft" width="105" height="47" /></a>Now, if you&#8217;re more of a vocal and visual person or just prefer to talk on the phone with folks, <a href="http://www.skype">Skype</a> may be an even better solution that Digsby.  Skype is great Video Chat and <a href="http://en.wikipedia.org/wiki/Voice_over_Internet_Protocol">VOIP</a> phone service that not only has an instant messaging client, but has the ability for you and another person to <em>physically</em> chat with one another and even see the person as well!  All you need to do is install Skype and hook up your web camera and microphone.  Me and my three brothers have the following camera, which is in HD and has a microphone built in:  <a href="http://www.amazon.com/gp/product/B000RZQZM0?ie=UTF8&amp;tag=subpriintera-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000RZQZM0">Logitech QuickCam Pro 9000</a><img style="border:none !important; margin:0px !important;" src="http://www.assoc-amazon.com/e/ir?t=subpriintera-20&amp;l=as2&amp;o=1&amp;a=B000RZQZM0" border="0" alt="" width="1" height="1" />.  Super easy to install and use; I highly recommend this one.</p>
<h2>Conclusion</h2>
<p>So the combination of the aforementioned resources has enabled myself and Brendan to successfully build out the <a href="http://www.dostorosnyc.com">website</a> plus, it has enabled us to confidently take on any additional projects with which we may be presented.  The best part about it?  All of these resources are FREE.  Moreover, I believe I&#8217;ve only scratched the surface here with this concept of &#8220;distributed collaboration&#8221; as I&#8217;m sure many out there have their own tricks and tips.  So share them in the comments!</p>
<img src="http://feeds.feedburner.com/~r/subPrintBlog/~4/Hgg01o3Mb7Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.subprint.com/blog/distributed-collaboration-building-a-website-remotely/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.subprint.com/blog/distributed-collaboration-building-a-website-remotely/</feedburner:origLink></item>
		<item>
		<title>An Even Simpler and Shorter URL Shortening Bookmarklet Using 3.ly</title>
		<link>http://feedproxy.google.com/~r/subPrintBlog/~3/cXDrzGc2jHk/</link>
		<comments>http://www.subprint.com/blog/3-ly-url-shortening-bookmarklet/#comments</comments>
		<pubDate>Sun, 05 Jul 2009 00:57:24 +0000</pubDate>
		<dc:creator>joemccann</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[3.ly]]></category>
		<category><![CDATA[bookmarklet]]></category>
		<category><![CDATA[short]]></category>
		<category><![CDATA[url]]></category>
		<category><![CDATA[web service]]></category>

		<guid isPermaLink="false">http://www.subprint.com/blog/?p=272</guid>
		<description><![CDATA[After creating my tr.im bookmarklet I came across 3.ly (pronounced &#8220;Three-lee&#8221;) which is probably the shortest url for a website name, but they also provide a URL shortening service. So of course, I had to make a 3.ly bookmarklet. Click the following link to test it out: 3.ly Bookmarklet You can also drag that link [...]]]></description>
			<content:encoded><![CDATA[<p>After creating my <a href="/blog/a-simple-url-shortening-bookmarklet-using-tr-im/">tr.im bookmarklet</a> I came across <a href="http://3.ly">3.ly</a> (pronounced &#8220;Three-lee&#8221;) which is probably the shortest url for a website name, but they also provide a URL shortening service.  So of course, I had to make a 3.ly bookmarklet.</p>
<p>Click the following link to test it out:</p>
<p><a title="3.ly URL Shortening Bookmarklet" href="javascript:var%20j=document.createElement(&quot;script&quot;);j.setAttribute(&quot;src&quot;,%20&quot;http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js&quot;);document.getElementsByTagName(&quot;body&quot;)[0].appendChild(j);void(0);var%20u=document.createElement(&quot;script&quot;);u.setAttribute(&quot;src&quot;,%20&quot;http://www.subprint.com/labs/imgly/js/jquery-ui-1.7.1.custom.min.js&quot;);document.getElementsByTagName(&quot;body&quot;)[0].appendChild(u);void(0);var%20s=document.createElement(&quot;script&quot;);s.setAttribute(&quot;src&quot;,%20&quot;http://www.subprint.com/labs/3ly/js/redirect.js&quot;);document.getElementsByTagName(&quot;body&quot;)[0].appendChild(s);void(0);">3.ly Bookmarklet</a></p>
<p>You can also drag that link to your bookmarks to make use of it for later.  As usual you can find this and other projects I’ve completed to improve your browsing experience on my <a href="../projects/">Projects</a> page.</p>
<img src="http://feeds.feedburner.com/~r/subPrintBlog/~4/cXDrzGc2jHk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.subprint.com/blog/3-ly-url-shortening-bookmarklet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.subprint.com/blog/3-ly-url-shortening-bookmarklet/</feedburner:origLink></item>
		<item>
		<title>A Simple URL Shortening Bookmarklet Using Tr.im</title>
		<link>http://feedproxy.google.com/~r/subPrintBlog/~3/7SbycXtvgAw/</link>
		<comments>http://www.subprint.com/blog/a-simple-url-shortening-bookmarklet-using-tr-im/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 23:37:03 +0000</pubDate>
		<dc:creator>joemccann</dc:creator>
				<category><![CDATA[Posts]]></category>

		<guid isPermaLink="false">http://www.subprint.com/blog/?p=265</guid>
		<description><![CDATA[So if you&#8217;re like me you send people a lot of links to stuff and sometimes they can be absurdly long (think a link to Google Maps with directions from Puget Sound, Washington to Bayou La Batre, Alabama). However, I hate having to actually GO to a URL shortening site like bit.ly or tr.im, type [...]]]></description>
			<content:encoded><![CDATA[<p>So if you&#8217;re like me you send people a lot of links to stuff and sometimes they can be absurdly long (think a link to Google Maps with directions <a href="http://maps.google.com/maps?q=Puget%20Sound%2C%20Washington%20to%20Bayou%20La%20Batre%2C%20Alabama&amp;sourceid=navclient-ff&amp;rlz=1B3GGGL_enUS297US297&amp;um=1&amp;ie=UTF-8&amp;sa=N&amp;hl=en&amp;tab=wl">from Puget Sound, Washington to Bayou La Batre, Alabama</a>).  However, I hate having to actually GO to a URL shortening site like <a href="http://bit.ly">bit.ly</a> or <a href="http://tr.im">tr.im</a>, type in the URL, wait for the page to reload and then copy the URL from there.  Why not just have a simple bookmarklet that you can fire open on any page you are browsing and get a short url right there?  Well, I&#8217;ve created a bookmarklet that does just that.</p>
<p>Click the following link to test it out:</p>
<p><a title="Tr.im Bookmarklet - A URL Shortener" href="javascript:var%20j=document.createElement(&quot;script&quot;);j.setAttribute(&quot;src&quot;,%20&quot;http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js&quot;);document.getElementsByTagName(&quot;body&quot;)[0].appendChild(j);void(0);var%20u=document.createElement(&quot;script&quot;);u.setAttribute(&quot;src&quot;,%20&quot;http://www.subprint.com/labs/imgly/js/jquery-ui-1.7.1.custom.min.js&quot;);document.getElementsByTagName(&quot;body&quot;)[0].appendChild(u);void(0);var%20s=document.createElement(&quot;script&quot;);s.setAttribute(&quot;src&quot;,%20&quot;http://www.subprint.com/labs/trim/js/redirect.js&quot;);document.getElementsByTagName(&quot;body&quot;)[0].appendChild(s);void(0);">Tr.im Bookmarklet</a></p>
<p>You can also drag that link to your bookmarks to make use of it for later.  As usual you can find this and other projects I&#8217;ve completed to improve your browsing experience on my <a href="/blog/projects/">Projects</a> page.</p>
<img src="http://feeds.feedburner.com/~r/subPrintBlog/~4/7SbycXtvgAw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.subprint.com/blog/a-simple-url-shortening-bookmarklet-using-tr-im/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.subprint.com/blog/a-simple-url-shortening-bookmarklet-using-tr-im/</feedburner:origLink></item>
		<item>
		<title>Parallel Script Loading with LABjs</title>
		<link>http://feedproxy.google.com/~r/subPrintBlog/~3/XBMnh7nSv48/</link>
		<comments>http://www.subprint.com/blog/parallel-script-loading-with-labjs/#comments</comments>
		<pubDate>Mon, 29 Jun 2009 03:49:55 +0000</pubDate>
		<dc:creator>joemccann</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Posts]]></category>
		<category><![CDATA[labjs]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.subprint.com/blog/?p=207</guid>
		<description><![CDATA[Once a month, I lead the Austin JavaScript meetup here in Austin, Texas where we get together, talk shop, show demos of projects, and then have beers at the Draught House. After the first few meetings, Kyle Simpson (@getify) decided to help me out with providing content for the meetups and has provided loads of [...]]]></description>
			<content:encoded><![CDATA[<p>Once a month, I lead the Austin JavaScript meetup here in Austin, Texas where we get together, talk shop, show demos of projects, and then have beers at the <a href="http://www.draughthouse.com/">Draught House</a>.  After the first few meetings, Kyle Simpson (<a href="http://twitter.com/getify">@getify</a>) decided to help me out with providing content for the meetups and has provided loads of top-notch quality stuff from his talk on closures and the module programming model to some of his own projects like <a href="http://flxhr.flensed.com/">flxhr</a>.</p>
<p>Recently, Kyle gave a talk on how to download scripts in parallel, something <a href="http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/">Steve Souders</a> and a few others have discussed how to do effectively.  Kyle wrote his own, JavaScript library/framework-agnostic library (for lack of a better term) to allow for parallel script downloading with our <em>without</em> blocking (think dependencies).  He presented this project of his at our meetup in June, and thus <a href="http://labjs.com/">LABjs</a> was born.</p>
<h2>Some History on <code>&lt;script&gt;</code> Tags and Performance</h2>
<p>If you&#8217;ve ever been to a website like <a href="http://www.mashable.com">Mashable.com</a> or <a href="http://www.marketwatch.com">Marketwatch.com</a> or a slew of other sites that seem to take FOREVER to download even with a high-speed connection, then you&#8217;ve probably been the victim of multiple <code>&lt;script&gt;</code> tags blocking the page from fully downloading, and ultimately rendering.  Sorry in advance for picking on Mashable, but the home page had a whopping <strong>59 JavaScript requests</strong> when I went to it today so it is a perfect candidate for LABjs&#8217;s usage, or simply some JavaScript loading optimization of some kind.</p>
<p><a href="http://www.subprint.com/blog/wp-content/uploads/2009/06/mashable-blocking.jpg"><img class="alignleft size-full wp-image-210" title="Mashable's Insane Number of JavaScript Requests" src="http://www.subprint.com/blog/wp-content/uploads/2009/06/mashable-blocking.jpg" alt="Mashable's Insane Number of JavaScript Requests" width="440" height="275" /></a></p>
<p>So why is this bad?  Well, <code>&lt;script&gt;</code> tags, when they download, block other assets from downloading to fully render the page.  As a result, a user&#8217;s experience with the webpage is severely degraded as that page may take significantly longer to download and subsequently render because the browser is unable to download anything else while the <code>&lt;script&gt;</code> tag is &#8220;<a href="http://www.urbandictionary.com/define.php?term=bogart">bogarting</a>&#8221; the download queue. Steve Souders provides an excellent demo of this problem <a href="http://stevesouders.com/hpws/js-blocking.php">here</a>.</p>
<h2>Download Without Blocking</h2>
<p>So how do we avoid or at least minimize the deterioration of the user experience from the blocking associated with multiple <code>&lt;script&gt;</code> tag requests?  That is where LABjs comes in.  LABjs, an acronym for &#8220;Loading and Blocking JavaScript&#8221;, uses well known, yet clever techniques for adding script tags in a manner that allows for non-blocking, parallel downloads.</p>
<p>A quick and easy example of this can be seen in the following code on this <a href="/blog/demos/labjs/">demo page</a>.</p>
<p>Upon page load, a quick inspection of the Net tab in Firebug yields the following results:</p>
<p><a href="http://www.subprint.com/blog/wp-content/uploads/2009/06/without-dependencies-700.jpg"><img class="alignleft size-full wp-image-227" title="Parallel Loading Without Dependencies" src="http://www.subprint.com/blog/wp-content/uploads/2009/06/without-dependencies-700.jpg" alt="Parallel Loading Without Dependencies" width="700" height="192" /></a></p>
<p>What should be noted here is how JavaScript files are being downloading not only with other JavaScript files, but images as well.  The process could not have been simpler either.</p>
<pre class="brush: text;">
&lt;head&gt;
 &lt;script type=&quot;text/javascript&quot; src=&quot;js/LAB.js&quot;&gt;
 &lt;/script&gt;
 &lt;script type=&quot;text/javascript&quot; src=&quot;js/load.js&quot;&gt;
 &lt;/script&gt;
&lt;/head&gt;
</pre>
<p>In the <code>&lt;head&gt;</code> tag we only need to include the request to the <code>LAB.js</code> library file and then a file I called <code>load.js</code> which contains the following LAB API calls.</p>
<pre class="brush: text;">
$LAB
.script(&quot;http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js&quot;, &quot;http://www.google-analytics.com/ga.js&quot;)
.block(function(){
 pageTracker = _gat._getTracker(&quot;UA-3312370-2&quot;);
 pageTracker._trackPageview();
});
</pre>
<p>If you notice, I am making a call to the <code>script()</code> method passing in a request for the latest version of jQuery and the Google Analytics tracking script.  The next is a <code>block()</code> method call that handles my Google Analytics tracking.  Even though this example was to show a simple use of the LABjs API, I did add this block of code for my own personal tracking statistics.  The <code>block()</code> method call is not required for this example to work.</p>
<h2>Downloading with Dependencies</h2>
<p>One of the best features that puts LABjs ahead of other methods and frameworks that produce similar results is that LABjs allows for you to load a file, say the latest version of jQuery, and then run some code that is dependent on that file&#8217;s existence.</p>
<p>An example of using LABjs with dependencies can be seen in the following code on this <a href="/blog/demos/labjs/dependency.php">demo page</a>.</p>
<p>Upon page load, a quick inspection of the Net tab in Firebug yields the following results:</p>
<p><a href="http://www.subprint.com/blog/wp-content/uploads/2009/06/with-dependencies-700.jpg"><img class="alignleft size-full wp-image-230" title="Parallel Loading With Dependencies" src="http://www.subprint.com/blog/wp-content/uploads/2009/06/with-dependencies-700.jpg" alt="Parallel Loading With Dependencies" width="700" height="199" /></a></p>
<p>What is important to note here is the times and places where <code>global.js</code> and the <code>__utm.gif</code> tracking image were downloaded:  <code>global.js</code> is dependent on the jQuery library to execute some code and the tracking image is a result of the Google Analytics script executing the tracking code.  These files were downloaded (and executed) <em>after</em> their dependent files were fully downloaded, the result of the <code>block()</code> method call.  The ease of use and the robustness of dependency management coupled with non-blocking script downloads should be evident with this example.</p>
<h2>The Conventional Route</h2>
<p>Of course, I have to show the same page using the conventional approach of multiple <code>&lt;script&gt;</code> tags.  The demo is <a href="/blog/demos/labjs/conventional.php">here</a>.</p>
<p>Upon page load, a quick inspection of the Net tab in Firebug yields the following results:</p>
<p><a href="http://www.subprint.com/blog/wp-content/uploads/2009/06/conventional.jpg"><img class="alignleft size-full wp-image-241" title="Conventional Method of Downloading JavaScript Files" src="http://www.subprint.com/blog/wp-content/uploads/2009/06/conventional.jpg" alt="Conventional Method of Downloading JavaScript Files" width="700" height="166" /></a></p>
<p>As you can clearly see, the blockage from the JavaScript requests denies any other asset from downloading until the JavaScript file has completely downloaded.  Even with this simple example, it took 3.43 seconds to render the page as compared to the prior example coming in at only 2.35 seconds a difference of <strong>68.5%</strong>.  The numerical results themselves should be reason enough to use LABjs.</p>
<h2>Where Can I Get It</h2>
<p>LAB.js can be found at the humble site, <a href="http://labjs.com">LABjs.com</a> where you can download a zip file of the code with some examples.  LABjs is maintained by Kyle himself and he is incredibly responsive to questions or requests so be sure to follow him on <a href="http://twitter.com/getify">twitter</a>.</p>
<img src="http://feeds.feedburner.com/~r/subPrintBlog/~4/XBMnh7nSv48" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.subprint.com/blog/parallel-script-loading-with-labjs/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.subprint.com/blog/parallel-script-loading-with-labjs/</feedburner:origLink></item>
		<item>
		<title>Demystifying the DOM Ready Event Method</title>
		<link>http://feedproxy.google.com/~r/subPrintBlog/~3/uS7SURQt-FA/</link>
		<comments>http://www.subprint.com/blog/demystifying-the-dom-ready-event-method/#comments</comments>
		<pubDate>Sun, 17 May 2009 06:12:32 +0000</pubDate>
		<dc:creator>joemccann</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Posts]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.subprint.com/blog/?p=80</guid>
		<description><![CDATA[Probably the most fundamental, widely used, and most misunderstood method of the jQuery library is the ready() method (aka the &#8220;DOM Ready&#8221; method), commonly seen as $(document).ready() or simply $().ready() or even indirectly $(function(){...}). Why the third version is indirect? We&#8217;ll get to that later. Many new web designers/developers that start to use jQuery usually [...]]]></description>
			<content:encoded><![CDATA[<p>Probably the most fundamental, widely used, and most misunderstood method of the jQuery library is the <code>ready()</code> method (aka the &#8220;DOM Ready&#8221; method), commonly seen as <code>$(document).ready()</code> or simply <code>$().ready()</code> or even indirectly <code>$(function(){...})</code>.  Why the third version is indirect?  We&#8217;ll get to that later.</p>
<p>Many new web designers/developers that start to use jQuery usually write their first block of code starting with something like the following:</p>
<pre class="brush: js;">
$(document).ready(function(){
    alert(&quot;Hello Whirled&quot;);
});
</pre>
<p>However, if you ask most people what is happening here, most likely the response is, &#8220;When the DOM is ready, I show an alert popup with the text &#8216;Hello Whirled&#8217;&#8221;.  However, there is no &#8220;DOM Ready&#8221; event in JavaScript; it is a rather ingenious method that will execute a block of JavaScript <em>before</em> the page has finished loading.  The benefits to having some JavaScript executed <em>before</em> the page has finished loading are immense, for one may need to manipulate the DOM prior to the page fully rendering, possibly some user agent detection, or whatever.  Waiting to execute that code using the traditional <code>window.onload </code>method doesn&#8217;t allow us to do these things.  But what is <em>really </em>happening when you call the <code>ready()</code> method?  I aim to sort that out from a technical perspective in this article.</p>
<h2>Ready?</h2>
<p>The <code>ready()</code> method does three things when it is called:</p>
<ol>
<li>Attaches listeners to the method by calling the <code>bindReady()</code> function.</li>
<li>Checks to see if <code>jQuery.isReady</code> property is true and if it is, it executes the function immediately.</li>
<li>Otherwise, it adds it to the stack (array) of functions to be executed when <code>jQuery.isReady</code> is in fact true.</li>
</ol>
<pre class="brush: js;">
jQuery.fn.extend({
    /* ... */
    ready: function(fn){
        // Attach the listeners
        bindReady();
        // If the DOM is already ready
        if (jQuery.isReady)
            // Execute the function immediately
            fn.call(document, jQuery);
        // Otherwise, remember the function for later
        else
            // Add the function to the wait list
            jQuery.readyList.push(fn);
        return this;
    }
});
</pre>
<p>The majority of the magic happens inside the <code>bindReady()</code> function:</p>
<pre class="brush: js;">
var readyBound = false;
function bindReady(){
    if (readyBound)
        return;
    readyBound = true;
    // Mozilla, Opera and webkit nightlies currently support this event
    if (document.addEventListener) {
        // Use the handy event callback
        document.addEventListener(&quot;DOMContentLoaded&quot;, function(){
            document.removeEventListener(&quot;DOMContentLoaded&quot;, arguments.callee, false);
            jQuery.ready();
        }, false);
        // If IE event model is used
    }
    else
        if (document.attachEvent) {
            // ensure firing before onload,
            // maybe late but safe also for iframes
            document.attachEvent(&quot;onreadystatechange&quot;, function(){
                if (document.readyState === &quot;complete&quot;) {
                    document.detachEvent(&quot;onreadystatechange&quot;, arguments.callee);
                    jQuery.ready();
                }
            });
            // If IE and not an iframe
            // continually check to see if the document is ready
            if (document.documentElement.doScroll &amp;&amp; window == window.top)
                (function(){
                    if (jQuery.isReady)
                        return;
                    try {
                        // If IE is used, use the trick by Diego Perini
                        // http://javascript.nwbox.com/IEContentLoaded/
                        document.documentElement.doScroll(&quot;left&quot;);
                    }
                    catch (error) {
                        setTimeout(arguments.callee, 0);
                        return;
                    }
                    // and execute any waiting functions
                    jQuery.ready();
                })();
        }
    // A fallback to window.onload, that will always work
    jQuery.event.add(window, &quot;load&quot;, jQuery.ready);
}
</pre>
<p>That&#8217;s a good bit of code, so let&#8217;s break it down into digestible chunks.</p>
<h2>Standards-Compliant Browsers</h2>
<p>The first, and most trivial check, is to see whether or not the <code>readyBound</code> variable is <code>true</code> and if it is, then we&#8217;re done!  Otherwise, let&#8217;s set it to <code>true</code> now because when we only want/need to bind the handlers once.</p>
<pre class="brush: js;">
if (readyBound)
    return;
readyBound = true;
</pre>
<p>Next, we see an example of <a href="https://developer.mozilla.org/En/Browser_Feature_Detection">browser feature detection</a> being used for executing a particular block of code.  Most standards-compliant browsers support the <code>addEventListener()</code> method.  By passing the <code>DOMContentLoaded</code> event to the <code>addEventListener()</code> function we are telling the browser to &#8220;listen&#8221; for the event that is fired when a document&#8217;s DOM content has finished loading.  The anonymous callback function that is passed as the second parameter to <code>addEventListenter()</code> is then executed when that event has fired.  This anonymous event handler function removes itself (referenced via <code>arguments.callee</code>) from being bound to the document once it has been called.  Finally, we call the jQuery utility method <code>jQuery.ready()</code>.  We will discuss this method later on.</p>
<pre class="brush: js;">
// Mozilla, Opera and webkit nightlies currently support this event
if (document.addEventListener) {
    // Use the handy event callback
    document.addEventListener(&quot;DOMContentLoaded&quot;, function(){
        document.removeEventListener(&quot;DOMContentLoaded&quot;, arguments.callee, false);
        jQuery.ready();
    }, false);
    // If IE event model is used
}
</pre>
<h2>Internet Explorer is Special</h2>
<p>In the next block of code, this bit of feature detection checks to see if Internet Explorer&#8217;s event model is used.  To handle iframes, we need to &#8220;listen&#8221; for a &#8220;complete&#8221; response from the request sent by that iframe.  <code>document.attachEvent("onreadystatechange", function(){...})</code> handles this and fires the anonymous function when that response arrives.  If it is in fact a &#8220;complete&#8221; response, then, similar to how we did before, the event is detached (no longer listening), <code>document.detachEvent("onreadystatechange", arguments.callee)</code> and the <code>jQuery.ready()</code> utility method is called.  </p>
<pre class="brush: js;">
 // Mozilla, Opera and webkit nightlies currently support this event
if (document.addEventListener) {
    // Use the handy event callback
    document.addEventListener(&quot;DOMContentLoaded&quot;, function(){
        document.removeEventListener(&quot;DOMContentLoaded&quot;, arguments.callee, false);
        jQuery.ready();
    }, false);
    // If IE event model is used
}

else
    if (document.attachEvent) {
        // ensure firing before onload,
        // maybe late but safe also for iframes
        document.attachEvent(&quot;onreadystatechange&quot;, function(){
            if (document.readyState === &quot;complete&quot;) {
                document.detachEvent(&quot;onreadystatechange&quot;, arguments.callee);
                jQuery.ready();
            }
        });
        // If IE and not an iframe
        // continually check to see if the document is ready
        if (document.documentElement.doScroll &amp;&amp; window == window.top)
            (function(){
                if (jQuery.isReady)
                    return;
                try {
                    // If IE is used, use the trick by Diego Perini
                    // http://javascript.nwbox.com/IEContentLoaded/
                    document.documentElement.doScroll(&quot;left&quot;);
                }
                catch (error) {
                    setTimeout(arguments.callee, 0);
                    return;
                }
                // and execute any waiting functions
                jQuery.ready();
            })();
    }
</pre>
<p>If we are not using iframes, then some true JavaScript trickery is used, so naturally we first want to verify that we are in fact using Internet Explorer and that it is not an iframe:</p>
<pre class="brush: js;">
if (document.documentElement.doScroll &amp;&amp; window == window.top)
</pre>
<p>Now, the good part.  We have a <a href="http://www.dustindiaz.com/awkward-looking-javascript/">self-invoking function</a> that first, checks to see if the <code>jQuery.ready</code> property is true, for if it is then we return.  Next, we use a trick (hack) by <a href="http://javascript.nwbox.com/IEContentLoaded/">Diego Perini</a> to see if the DOM Content is loaded by using the <code>doScroll()</code> method in a try/catch polling loop. This triggers the <code>jQuery.ready()</code> utility method when no errors are returned by the <code>doScroll()</code>.  Pretty slick and a nice find by Diego.  The <code>catch(error)</code> statement here is worth noting as the line containing the code <code>setTimeout(arguments.callee, 0);</code> essentially keeps calling this anonymous function until there are in fact NO errors, which then calls the <code>jQuery.ready()</code> utility method.</p>
<pre class="brush: js;">
     (function(){
        if (jQuery.isReady)
            return;
        try {
            // If IE is used, use the trick by Diego Perini
            // http://javascript.nwbox.com/IEContentLoaded/
            document.documentElement.doScroll(&quot;left&quot;);
        }
        catch (error) {
            setTimeout(arguments.callee, 0);
            return;
        }
        // and execute any waiting functions
        jQuery.ready();
    })();
</pre>
<p>If all of this fails, then we simply attach a <code>load</code> event, to the <code>window</code> object, and THEN call the <code>jQuery.ready</code> utility method when this event has fired.</p>
<pre class="brush: js;">
 // A fallback to window.onload, that will always work
jQuery.event.add(window, &quot;load&quot;, jQuery.ready)
</pre>
<h2>Where Am I?</h2>
<p>Let&#8217;s recap where we&#8217;re at.  By now, we have determined that either the DOM Content is loaded, regardless of the browser, OR we are falling back on the fail-safe <code>window.onload()</code> method.  Now, we just need to execute the <code>jQuery.ready()</code> utility method.</p>
<pre class="brush: js;">
jQuery.extend({
    isReady: false,
    readyList: [],
    // Handle when the DOM is ready
    ready: function(){
        // Make sure that the DOM is not already loaded
        if (!jQuery.isReady) {
            // Remember that the DOM is ready
            jQuery.isReady = true;
            // If there are functions bound, to execute
            if (jQuery.readyList) {
                // Execute all of them
                jQuery.each(jQuery.readyList, function(){
                    this.call(document, jQuery);
                });
                // Reset the list of functions
                jQuery.readyList = null;
            }
            // Trigger any bound ready events
            jQuery(document).triggerHandler(&quot;ready&quot;);
        }
    }
});
</pre>
<p>The <code>jQuery.ready()</code> utility method is concise and elegant in its design.  It starts off by checking to see if the DOM is already loaded and if it is, then we skip to the last line of code in the <code>ready</code> method definition.  If the DOM is not loaded, then we set it to be loaded if this method is called again some time in the future.  Then we check to see if the <code>readyList</code> property of the <code>jQuery</code> object (an array of functions) has a &#8220;truthyness&#8221; value of true, as it is null by default.  If it is true, then we pass this array of functions into the jQuery utility method, <code>jQuery.each()</code>, and iterate over each element of the array.  The second parameter of the <code>jQuery.each()</code> method is an anonymous function that is executed over each iteration.  In this case, we are calling each function in the <code>readyList</code> in the context of the <code>document</code> and passing the <code>jQuery</code> object parameter to each function so it may be used within that function call:  <code>this.call(document, jQuery);</code></p>
<p>After we have iterated over the array of functions we then set the <code>jQuery.readyList</code> value to null, since we just executed all of those functions there is no need to keep track of them for the next potential <code>jQuery.ready()</code> utility method call.  Finally, we trigger any events that may have been bound to the <code>ready</code> event using the <code><a href="http://docs.jquery.com/Events/triggerHandler">triggerHandler()</a></code> method.</p>
<h2>Indirect Call of Ready Method</h2>
<p>Earlier I mentioned there was a third way of calling the <code>jQuery.ready()</code> method, namely <code>$(function(){...})</code>.  By first glance, one may posit what exactly is going on here and how does it correlate to a <code>ready()</code> method call?  First, we are creating a new <code>jQuery</code> object with the common <code>$()</code> notation.  However, instead of passing in a selector such as <code>$('#myDiv')</code>, we are passing in an anonymous function.  If you view the source code of jQuery 1.3.2, you will come across this block of code at line 80:</p>
<pre class="brush: js;">
		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) )
			return jQuery( document ).ready( selector );
</pre>
<p>This code is found within the <code>init()</code> method of the <code>jQuery</code> object and is the final check in the <code>init</code> method to see if the value passed in, <code>selector</code>, is a function and if it is, then it returns a call to the <code>ready()</code> method passing in the anonymous function as the parameter.  So the <code>ready()</code> method is still being called, just indirectly.</p>
<h2>Thoughts?</h2>
<p>Attempting to break the DOM Ready method down into bite-size pieces and <em>still</em> be comprehensible was no easy task.  Please let me know if this article helps you out or if there is anything I can do to improve it.  Thanks! </p>
<p>UPDATE:  Hat tip to <a href="http://twitter.com/getify">@getify</a> for some quality feedback to improve this article.</p>
<img src="http://feeds.feedburner.com/~r/subPrintBlog/~4/uS7SURQt-FA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.subprint.com/blog/demystifying-the-dom-ready-event-method/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.subprint.com/blog/demystifying-the-dom-ready-event-method/</feedburner:origLink></item>
		<item>
		<title>A Simple JavaScript Performance Test With jQuery</title>
		<link>http://feedproxy.google.com/~r/subPrintBlog/~3/UgCPMIuizDI/</link>
		<comments>http://www.subprint.com/blog/a-simple-javascript-performance-test-with-jquery/#comments</comments>
		<pubDate>Sat, 02 May 2009 20:18:25 +0000</pubDate>
		<dc:creator>joemccann</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Posts]]></category>
		<category><![CDATA[firebug]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[test]]></category>

		<guid isPermaLink="false">http://www.subprint.com/blog/?p=52</guid>
		<description><![CDATA[One of the gifts in the swag bag from JSConf this year was a free copy of JSMag, a definite start to quality reading on topics related to JavaScript. I was reading a solid article by Rebecca Murphey (@rmurphey) on &#8220;Using Object Lilterals to Organize Your Features&#8221; and noticed something in the code that inspired [...]]]></description>
			<content:encoded><![CDATA[<p>One of the gifts in the swag bag from <a href="http://www.jsconf2009.com">JSConf</a> this year was a free copy of <a href="http://www.jsmag.com/">JSMag</a>, a definite start to quality reading on topics related to JavaScript.  I was reading a solid article by Rebecca Murphey (<a href="http://twitter.com/rmurphey">@rmurphey</a>) on &#8220;Using Object Lilterals to Organize Your Features&#8221; and noticed something in the code that inspired me to do a quick little test on performance.</p>
<p>In her code, she has an object method defined in the following manner:</p>
<pre class="brush: js;">
myFeature.$section_nav = $('ul/&gt;').attr('id','section_nav').prependTo(myfeature.$container);
</pre>
<p>Absolutely nothing wrong with this code and it reads well and works fine.  However, it is slightly different than the way I write my code when I&#8217;m dynamically creating and appending elements to the DOM.  Typically, instead of creating an element and passing it to the jQuery method, I find the element I want to append the element to and then simply call the append method passing in a block of HTML.  Again, nothing fancy, but the key difference I picked up on was that when I pass a block of HTML, I include all attributes in the element(s) I&#8217;m passing in.  So essentially I would have:</p>
<pre class="brush: js;">
$('#header').append(&quot;&lt;p class=&quot;orange&quot; id=&quot;headerText&quot;/&gt;&quot;);
</pre>
<p>So even though this may be just a coding style, I was curious to see what the difference would be in performance based on passing a block of HTML first, adding attributes to it via the <code>attr()</code> method and then appending (or prepending) to an element, or the way I do it, which is a bit of the reverse.</p>
<p>I created a very simple test with the following markup:</p>
<pre class="brush: html;">
			&lt;div id=&quot;main&quot;&gt;
				&lt;form action=&quot;&quot;&gt;
					&lt;input type=&quot;button&quot; value=&quot;No Attribute Method Call&quot; id=&quot;noAttr&quot; /&gt;
					&lt;input type=&quot;button&quot; value=&quot;With Attribute Method Call&quot; id=&quot;withAttr&quot; /&gt;
					&lt;input type=&quot;button&quot; value=&quot;Clear Response Div&quot; id=&quot;clear&quot; /&gt;
				&lt;/form&gt;
				&lt;div id=&quot;response&quot;&gt;

				&lt;/div&gt;
			&lt;/div&gt;
</pre>
<p>And the subsequent JavaScript:</p>
<pre class="brush: js;">
$(function(){
    var $response = $('#response');

    $('#noAttr').click(function(){
        $response.append('&lt;p id=&quot;myParagraph&quot;/&gt;');
        $('#myParagraph').text('Some Text');
        return false;
    });

    $('#withAttr').click(function(){
        $('&lt;p/&gt;').attr('id', 'myParagraph').appendTo($response);
        $('#myParagraph').text('Some Text');
        return false;
    });

    $('#clear').click(function(){
        var children = $response.children();
        $.each(children, function(i){
            delete children[i].parentNode.removeChild(children[i]);
        });
        return false;
    });

});
</pre>
<p>The results are interesting&#8230;</p>
<div id="attachment_71" class="wp-caption alignleft" style="width: 710px"><a href="http://www.subprint.com/blog/wp-content/uploads/2009/05/test_with_attribute_method.jpg"><img src="http://www.subprint.com/blog/wp-content/uploads/2009/05/test_with_attribute_method.jpg" alt="Test With Attribute Method" title="Test With Attribute Method" width="700" height="83" class="size-full wp-image-71" /></a><p class="wp-caption-text">Test With Attribute Method</p></div>
<p>The above screenshot shows the results in Firebug&#8217;s profiler of the technique used that is similar to Rebecca&#8217;s example.  Note, the total number of calls and the total amount of time it takes to execute the function on the click event.</p>
<div id="attachment_65" class="wp-caption alignleft" style="width: 710px"><a href="http://www.subprint.com/blog/wp-content/uploads/2009/05/test_without_attribute_method.jpg"><img src="http://www.subprint.com/blog/wp-content/uploads/2009/05/test_without_attribute_method.jpg" alt="Test Without Attribute Method" title="Test Without Attribute Method" width="700" height="87" class="size-full wp-image-65" /></a><p class="wp-caption-text">Test Without Attribute Method</p></div>
<p>And these are the results using the technique of which I am most accustomed.</p>
<p>The obvious numbers that stand out to me are the total number of calls and the total amount of execution time.  <strong>90</strong> total function calls in the first example versus only <strong>62</strong> in the second and a difference of <strong>0.811 milliseconds</strong> in total execution time.  Now, many may argue that .811 milliseconds is not that significant of a difference on the surface, but the percentage difference is&#8230;a whopping <strong>37.5%</strong>!  </p>
<p>Try it out for yourself on the <a href="/blog/demos/attribute_method_test/">demo page</a> (requires a standards-compliant browser and a JavaScript profiler).  </p>
<img src="http://feeds.feedburner.com/~r/subPrintBlog/~4/UgCPMIuizDI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.subprint.com/blog/a-simple-javascript-performance-test-with-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.subprint.com/blog/a-simple-javascript-performance-test-with-jquery/</feedburner:origLink></item>
		<item>
		<title>JSConf 2009 — Day Two</title>
		<link>http://feedproxy.google.com/~r/subPrintBlog/~3/0XXD3xxh7vY/</link>
		<comments>http://www.subprint.com/blog/jsconf-2009-%e2%80%94-day-two/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 13:29:33 +0000</pubDate>
		<dc:creator>joemccann</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Posts]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[jsconf]]></category>
		<category><![CDATA[paas]]></category>
		<category><![CDATA[phonegap]]></category>

		<guid isPermaLink="false">http://www.subprint.com/blog/?p=36</guid>
		<description><![CDATA[So I&#8217;m a bit late on wrapping this up, but with so much to absorb from day two, I&#8217;m sure you can understand.  Day two of JSConf 2009 was just as incredible as day one, granted, everyone was a bit sluggish from the &#8220;beer track&#8221; the night before, there was still an abundance of quality [...]]]></description>
			<content:encoded><![CDATA[<p>So I&#8217;m a bit late on wrapping this up, but with so much to absorb from day two, I&#8217;m sure you can understand.  Day two of JSConf 2009 was just as incredible as day one, granted, everyone was a bit sluggish from the &#8220;beer track&#8221; the night before, there was still an abundance of quality (and entertaining) presentations on various topics.</p>
<p>James Duncan (<a title="James Duncan Twitter Profile" href="http://twitter.com/jamesduncan">@jamesduncan</a>) from <a title="Joyent" href="http://www.joyent.com">Joyent</a> gave an excellent talk on &#8220;JavaScript Platform as a Service&#8221; and the economics associated with it.  Duncan made an excellent correlation to using web technology related services very much like one would pay for electricity:  you should only pay for what you use, a solid argument against adding additional data centers, servers, and the like. The concept behind his Platform as a Service (PaaS) is not necessarily new, but it&#8217;s association with JavaScript is.  Duncan claims there are &#8220;tons of money being spent to make JavaScript super fast,&#8221; and &#8220;the world is really changing&#8221; in regards to JavaScript.  Looking forward to what comes of this.</p>
<p>Easily the most entertaining presentation was by Brian Leroux (<a title="Brian Leroux Twitter Profile" href="http://twitter.com/brianleroux">@brianleroux</a>) from<a title="Nitobi Home Page" href="http://www.nitobi.com/"> Nitobi</a> on <a title="Phonegap Home Page" href="http://phonegap.com/">Phonegap</a>.  Just check the second slide and you&#8217;ll see why his presentation woke the crowd up.</p>
<div id="ss_1341358"></div>
<p>If you are not familiar with Phonegap, you should be.  With all the fragmentation between mobile operating systems and how we developers loathe said fragmentation, Phonegap comes to the rescue by allowing you to develop in your native environment (e.g. HTML,CSS,Javascript) and allows your app will work on multiple mobile platforms.  Pretty ingenious and not very well known, which is baffling to me.  Most iPhone developers, I believe, would prefer their app to work on the Android phones and Blackberries as well, yet there doesn&#8217;t seem to be a large adoption to Phonegap&#8230;yet.  I believe JSConf, with the incredibly bright and influential minds that were there, will help push this abstraction SDK further in the mobile dev community.</p>
<p>Some highlights that stood out to me from the other talks included the concept of hyperlinking/JSON referencing in a REST Architecture and <a title="Persevere Home Page" href="http://sitepen.com/labs/persevere.php">Persevere</a> by Kris Zyp, some remedial website performance related topics by Stoyan Stefanov (author of <a title="OOJ" href="http://www.amazon.com/Object-Oriented-JavaScript-high-quality-applications-libraries/dp/1847194141%3FSubscriptionId%3D1YNZ339ZCHHAKYFSY702%26tag%3Dsubpriintera-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D1847194141">Object Oriented JavaScript</a>), an excellent introduction by Richard Worth on the jQuery UI framework, a high-energy presentaiton of the <a title="Sproutcore Home Page" href="http://www.sproutcore.com/">Sproutcore</a> framework by Mike Subelsky, and finally a truly thorough and comprehensive presentation of the true depth of the Dojo framework by Peter Higgins (<a title="Peter Higgins Twitter Profile." href="http://twitter.com/phiggins">@phiggins</a>).</p>
<p>I could go on and on about the presentations and the mental stimulation gained from this conference, but I would never get to work on time.  If you are a serious JavaScript engineer, you would be remiss to not attend next year&#8217;s JSConf.  The content and quality of the conference overall was by far the best I&#8217;ve ever experienced.</p>
<img src="http://feeds.feedburner.com/~r/subPrintBlog/~4/0XXD3xxh7vY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.subprint.com/blog/jsconf-2009-%e2%80%94-day-two/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.subprint.com/blog/jsconf-2009-%e2%80%94-day-two/</feedburner:origLink></item>
	</channel>
</rss>
