<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>Zach Leatherman</title>
	<subtitle>The blog formerly known as Web 3.0, 6 Bladed Razors, 7 Minute Abs</subtitle>
	
	<link href="http://www.zachleat.com/web/" />
	<updated>2013-05-23T23:52:01-05:00</updated>
	<id>http://www.zachleat.com/</id>
	<author>
		<name>Zach Leatherman</name>
		<email>zachleat@zachleat.com</email>
	</author>

	
	
	<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/zachleat" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="zachleat" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
		<title>Performance and Responsive Web Design</title>
		<link href="http://www.zachleat.com/web/rwd-perf/" />
		<updated>2013-05-17T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/perf-rwd</id>
		<content type="html">&lt;p&gt;The presentation was originally given to &lt;a href="http://nebraskajs.com/2012/performance-in-rwd/"&gt;NebraskaJS&lt;/a&gt; in November of 2012. Unfortunately due to my own technical ineptitude with screen recording software I wasn’t able to publish the talk. So when I was asked to present on the topic again at the &lt;a href="http://www.meetup.com/Omaha-Mobile-Group/events/104130942/"&gt;Omaha Mobile Group&lt;/a&gt;, I thought it would be a good opportunity to update the talk and get a second chance at recording it in front of an audience.&lt;/p&gt;

&lt;h2&gt;Video&lt;/h2&gt;

&lt;div class="fluid-width-video-wrapper"&gt;&lt;iframe width="420" height="315" src="http://www.youtube.com/embed/Aw5wEdcUtz4" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/div&gt;


&lt;h2&gt;View the &lt;a href="https://speakerdeck.com/zachleat/performance-and-responsive-web-design"&gt;Slide Deck (April 2013)&lt;/a&gt;&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Or, &lt;em&gt;view &lt;a href="https://speakerdeck.com/nebraskajs/performance-and-responsive-web-design"&gt;the original Slide Deck (November 2012)&lt;/a&gt;.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Content&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0:00&lt;/code&gt; Title and Personal Background&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3:04&lt;/code&gt; Responsive Web Design Primer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;5:24&lt;/code&gt; The Web has Responsive Roots&lt;/li&gt;
&lt;li&gt;&lt;code&gt;6:24&lt;/code&gt; Alternatives to RWD

&lt;ul&gt;
&lt;li&gt;Do nothing&lt;/li&gt;
&lt;li&gt;Create separate mdot site&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;14:44&lt;/code&gt; &lt;strong&gt;Common RWD Performance Problems&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;16:03&lt;/code&gt; Blocking JavaScript&lt;/li&gt;
&lt;li&gt;&lt;code&gt;18:27&lt;/code&gt; Blocking CSS&lt;/li&gt;
&lt;li&gt;&lt;code&gt;30:07&lt;/code&gt; Images

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;31:11&lt;/code&gt; Manipulating Images with CSS&lt;/li&gt;
&lt;li&gt;&lt;code&gt;36:47&lt;/code&gt; Responsive Images (in HTML)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RWD Buzzkills

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;45:40&lt;/code&gt; Advertising&lt;/li&gt;
&lt;li&gt;&lt;code&gt;46:47&lt;/code&gt; Social Networking Widgets&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;50:23&lt;/code&gt; RWD Showcase Showdown&lt;/li&gt;
&lt;li&gt;&lt;code&gt;54:21&lt;/code&gt; Conclusion&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Questions&lt;/strong&gt; &lt;em&gt;(Some really great discussion here)&lt;/em&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;56:19&lt;/code&gt; How do Data URIs impact the critical path?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;57:43&lt;/code&gt; The difference between Responsive and Adaptive?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;58:18&lt;/code&gt; Do you have to start from scratch with RWD?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;59:39&lt;/code&gt; How would Jimmy Wales and Wikipedia implement RWD?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;em&gt;(Side note: I wish there was an equivalent to &lt;a href="https://github.com/davatron5000/TimeJump"&gt;TimeJump&lt;/a&gt; for YouTube embeds)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Reactions, Reviews&lt;/h2&gt;

&lt;blockquote class="twitter-tweet"&gt;&lt;p&gt;Performance &amp;amp; Responsive Web Design &lt;a href="https://t.co/EjZJugzu" title="https://speakerdeck.com/nebraskajs/performance-and-responsive-web-design"&gt;speakerdeck.com/nebraskajs/per…&lt;/a&gt; great presentation from @&lt;a href="https://twitter.com/zachleat"&gt;zachleat&lt;/a&gt;&lt;/p&gt;&amp;mdash; Brad Frost (@brad_frost) &lt;a href="https://twitter.com/brad_frost/status/269949833190715392"&gt;November 17, 2012&lt;/a&gt;&lt;/blockquote&gt;




&lt;blockquote class="twitter-tweet"&gt;&lt;p&gt;People of Omaha! You _want_ to hear @&lt;a href="https://twitter.com/zachleat"&gt;zachleat&lt;/a&gt; talk about responsive design and performance. Trust me. &lt;a href="http://t.co/gOphoOZ696" title="http://www.meetup.com/Omaha-Mobile-Group/events/104130942/"&gt;meetup.com/Omaha-Mobile-G…&lt;/a&gt;&lt;/p&gt;&amp;mdash; Responsive Design (@RWD) &lt;a href="https://twitter.com/RWD/status/317747443531911168"&gt;March 29, 2013&lt;/a&gt;&lt;/blockquote&gt;




&lt;blockquote class="twitter-tweet"&gt;&lt;p&gt;The best RWD deck I've seen in a long time. The optimization section is a must read - &lt;a href="https://t.co/NK1i0gpd6Z" title="https://speakerdeck.com/nebraskajs/performance-and-responsive-web-design"&gt;speakerdeck.com/nebraskajs/per…&lt;/a&gt; by @&lt;a href="https://twitter.com/nebraskajs"&gt;nebraskajs&lt;/a&gt;&lt;/p&gt;&amp;mdash; Eric Snowden (@ericsnowden) &lt;a href="https://twitter.com/ericsnowden/status/309389156902113280"&gt;March 6, 2013&lt;/a&gt;&lt;/blockquote&gt;




&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;

&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/iK1-fsB_sw8" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>zachleat.com is Dead, Long Live zachleat.com</title>
		<link href="http://www.zachleat.com/web/zachleat-is-dead/" />
		<updated>2013-05-05T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/new-website</id>
		<content type="html">&lt;p&gt;&lt;em&gt;If you’re reading this in the RSS Feed, please accept my humble apologies for not transparently converting my feed. This is one of the perils of switching from WordPress to Jekyll. The URL for the feed has &lt;strong&gt;not&lt;/strong&gt; changed, but you’ll probably see a lot of unread items appearing here, so feel free to “mark all as read.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Welcome to the redesign of zachleat.com! Notably, the title of the blog is now my name, instead of &lt;code&gt;Web 3.0, 6 Bladed Razors, 7 Minute Abs&lt;/code&gt;. I’ve decided that using my name for the blog title is more in line with the principles I set forth in &lt;a href="/web/fumbling-with-social-media/"&gt;A Web Developer Fumbling with Social Media&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Tools&lt;/h2&gt;

&lt;p&gt;The entire site’s source code is &lt;a href="https://github.com/zachleat/zachleat.com"&gt;available on GitHub&lt;/a&gt;. If you see any issues with the site, please &lt;a href="https://github.com/zachleat/zachleat.com/issues"&gt;file them on GitHub&lt;/a&gt;. I probably could be convinced to rip out the proprietary pieces and release it as a blog boilerplate project—let me know if this is something you’d be interested in using.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mojombo/jekyll"&gt;Jekyll&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gruntjs.com/"&gt;Grunt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zurb.com/playground/foundation-icons"&gt;Zurb Foundation Social Icons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pygments.org/"&gt;Pygments Syntax Highlighter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://fitvidsjs.com/"&gt;FitVids (CSS only)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.google.com/fonts/specimen/Bitter"&gt;Bitter @font-face&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Grunt and Jekyll work beautifully together, even though they’re written in two different languages. It’s especially convenient that &lt;code&gt;grunt watch&lt;/code&gt; is configured to run the appropriate jekyll commands to generate the site automatically.&lt;/p&gt;

&lt;p&gt;That being said, if anyone knows of a really good Node.js site generator, please let me know. I’ve tried a bunch of them and haven’t yet found anything as good as Jekyll.&lt;/p&gt;

&lt;h2&gt;Theme&lt;/h2&gt;

&lt;p&gt;It’s a simple minimalistic mobile-first responsive web design (that’s a mouthful, eh?) theme that I’ve built from scratch. I’m calling it &lt;strong&gt;Butt Sweater&lt;/strong&gt;, for obvious reasons. Okay, not really. Well actually I mean to say, the reasons are not obvious—it’s really called &lt;a href="https://github.com/zachleat/zachleat.com/blob/master/web/css/buttsweater.scss"&gt;Butt Sweater&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Removals&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Wordpress: It was good to me for many years, but I am not sad to see Wordpress go and will look forward to blogging using Markdown in my normal code editor.&lt;/li&gt;
&lt;li&gt;jQuery: I love it, but do not make use of enough JavaScript on the site to warrant it—yet.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Future Plans&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;a href="/web/socialcount/"&gt;SocialCount&lt;/a&gt;, which will mean either re-adding jQuery or removing the jQuery dependency from SocialCount.&lt;/li&gt;
&lt;li&gt;I want to use the Google Analytics data to generate a visualization for the site that will communicate post popularity. I want it to be easy for visitors to find my most popular posts on the big list of posts on the home page.&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Import the old Comments. This is still in the works.  Whether or not I re-add the ability to let users post new comments directly on the site is still a matter for debate.&lt;/del&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;For now, &lt;a href="https://twitter.com/zachleat/"&gt;let me know what you think on twitter&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/bqcBCZH18do" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Tool or Die, a Web Developer’s Workflow</title>
		<link href="http://www.zachleat.com/web/tool-or-die/" />
		<updated>2013-03-17T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/tool-or-die</id>
		<content type="html">&lt;p&gt;This is a talk I gave at &lt;a href="http://www.nebraskacodecamp.com/Sessions/6"&gt;Nebraska Code Camp 2013&lt;/a&gt;.&lt;/p&gt;

&lt;div class="fluid-width-video-wrapper"&gt;
&lt;iframe width="420" height="315" src="http://www.youtube.com/embed/NkVmhe-vvAo" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;


&lt;blockquote&gt;&lt;p&gt;“Tool and die makers are a class of machinists who work primarily in toolroom environments—…often in an environment with flexible, semipermeable boundaries from production work.”&lt;/p&gt;

&lt;p&gt;These are the people that make the tools to make the products. This was the environment I grew up in—watching my father work as a tool and die maker. He could make anything! But more importantly, he knew the value of good tools—even if you had to construct them yourself.&lt;/p&gt;

&lt;p&gt;Tools are important and tooling for Web Development is improving! I’ll go through a few of my favorites: Node.js, grunt.js, npm, yepnope, SASS, grunticon, Browser devtools, Testing tools, and others.&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;&lt;a href="http://www.youtube.com/watch?v=NkVmhe-vvAo"&gt;Watch on YouTube&lt;/a&gt;&lt;/h2&gt;

&lt;h2&gt;&lt;a href="http://www.zachleat.com/toolordie/start-here.html"&gt;View the Slides&lt;/a&gt;&lt;/h2&gt;

&lt;h2&gt;&lt;a href="https://github.com/zachleat/ToolOrDie"&gt;Fork the Slides on GitHub&lt;/a&gt;&lt;/h2&gt;

&lt;h2&gt;But You Don’t Have to Take My Word For It &lt;img src="/web/img/readingrainbow.png" alt="Reading Rainbow Logo" /&gt;&lt;/h2&gt;

&lt;p&gt;Cory House was quick off the blocks with a &lt;a href="http://www.bitnative.com/2013/03/17/nebraska-code-camp-2013-lessons-learned/"&gt;review of all the talks he attended&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Zach laid out his presentation in a unique way, relying totally on hand-made lean HTML markup that slowly blossomed as he walked us through topics. I really enjoyed this iterative and novel approach – it was the perfect choice for such a markup heavy session.&lt;/p&gt;&lt;/blockquote&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/xPKrLzqkO7I" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>A Web Developer Fumbling with Social Media</title>
		<link href="http://www.zachleat.com/web/fumbling-with-social-media/" />
		<updated>2013-01-26T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/fumbling-with-social-media</id>
		<content type="html">&lt;p&gt;As a curious web developer that’s moderately obsessed with statistics, I decided to go back and look at my history of side projects, blog posts, and other junk I’ve posted on twitter to see what has had the biggest impact on my ‘social reach.’ Yeah, I know. It felt wrong typing ‘social reach’—I’ll put a dollar in the jar. I’ll probably owe a few of those before this post is done.&lt;/p&gt;

&lt;p&gt;It’s a common sentiment that as developers we should focus on &lt;em&gt;making cool stuff&lt;/em&gt; and the rest will solve itself. While that has been my general plan for my career and side projects, in hindsight I don’t believe that to be the complete truth. I think developers should spend time on self marketing—larger professional networks (not just social networks) lead to more opportunities.&lt;/p&gt;

&lt;p&gt;So as a blind squirrel, I come to you with the nuts I’ve found: &lt;strong&gt;seven events that have bumped my network size and what I’ve learned from studying them&lt;/strong&gt;. Note that Facebook is not mentioned here. I don’t use Facebook for career development.&lt;/p&gt;

&lt;h2&gt;Share and Be Shared&lt;/h2&gt;

&lt;p&gt;Out of those seven events, three were the direct result of Mr. Paul Irish. While I have no idea what I did to get in Paul’s good graces—I appreciate his concerted effort to share &lt;a href="http://paulirish.com/2011/web-browser-frontend-and-standards-feeds-to-follow/"&gt;RSS feeds&lt;/a&gt; (Event 1), &lt;a href="http://paulirish.com/2012/developers-we-admire/"&gt;people to follow on Twitter&lt;/a&gt; (Event 2), and &lt;a href="https://plus.google.com/113127438179392830442/posts/T2VqiobsvLF"&gt;Google circles&lt;/a&gt; (Event 3). Paul increases the number of people consuming web development content which leads to more well informed developers. &lt;em&gt;A rising tide lifts all boats.&lt;/em&gt; This is something we can all do. Look for some similar posts from me soon.&lt;/p&gt;

&lt;h2&gt;Silos are Lonely&lt;/h2&gt;

&lt;p&gt;Trailblazing can lead to isolation. Solve problems collaboratively or competitively—don’t solve your own problems alone.&lt;/p&gt;

&lt;p&gt;After &lt;a href="http://www.zachleat.com/web/bigtext-makes-text-big/"&gt;BigText&lt;/a&gt; came out, I was getting &lt;code&gt;2&lt;/code&gt; RSS subscribers per day. Four months later when Paravel released &lt;a href="fittextjs.com"&gt;FitText&lt;/a&gt; (Event #4) and linked to BigText that number jumped to &lt;code&gt;6&lt;/code&gt;. Even though the two plugins were competitors, we were both trying to solve a similar problem and our growth became intertwined.&lt;/p&gt;

&lt;h2&gt;Concentrate on the Right Network&lt;/h2&gt;

&lt;p&gt;It’s a lot easier to get an RSS subscriber or get circled on Google than it is to get someone to follow you on Twitter. It would seem that Twitter users curate their Twitter friends very closely since it’s one big unconfigurable stream (don’t get me started about how useless lists are). RSS and Google both let you self-organize your incoming posts in such a way that makes it easier to ignore content without unsubscribing.&lt;/p&gt;

&lt;p&gt;If I had to choose, I’d take a Twitter follower over an RSS feed subscriber over a Google follower. But it ain’t a zero sum game.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average RSS feed subscribers per day (2.4 years): 4.1&lt;/li&gt;
&lt;li&gt;Average Google followers per day (1.1 years): 2.03&lt;/li&gt;
&lt;li&gt;Average Twitter followers per day (4.3 years): 1.09&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Name-drop Yourself&lt;/h2&gt;

&lt;p&gt;Plaster your name on everything you do. Link to your Twitter account and RSS feeds.&lt;/p&gt;

&lt;p&gt;I’ve screwed the pooch on this quite often—most notably on &lt;a href="https://github.com/filamentgroup/SocialCount"&gt;SocialCount&lt;/a&gt; and BigText especially. I’ve had people say to me: “Oh—SocialCount? You built that?” Obviously not ideal. Personally, I felt that both of those plugins were higher quality than &lt;a href="http://parseIntimate.com"&gt;parseIntimate&lt;/a&gt; (Event #5), but parseIntimate had my twitter handle right on the front which bumped my followers more than SocialCount or BigText (prior to FitText).&lt;/p&gt;

&lt;h2&gt;Align Career with Community&lt;/h2&gt;

&lt;p&gt;Despite my ghost town of a profile on Google , my circled count jumped when I joined Filament Group (Event #6). Of course, working for a company that is so heavily invested in the community and open source is great.&lt;/p&gt;

&lt;h2&gt;Give Talks and Encouragement&lt;/h2&gt;

&lt;p&gt;For the &lt;a href="http://f2em.com/"&gt;Front End Engineering Manifesto&lt;/a&gt; (Event #7) I followed my own advice and put my twitter handle on both the top and bottom of the presentation and added SocialCount widgets for easy sharing. However, F2EM almost didn’t see the light of day.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If &lt;a href="https://twitter.com/rversaw"&gt;Ryan Versaw&lt;/a&gt; hadn’t personally encouraged me to present a topic at Nebraska Code Camp, I wouldn’t have created the presentation.&lt;/li&gt;
&lt;li&gt;After giving the talk I sat on the content because I felt it was a little too preachy and dogmatic and was nervous about publicizing it. About 17 months later, &lt;a href="https://twitter.com/toddmparker"&gt;Todd Parker&lt;/a&gt; stumbled onto it and encouraged me to release it.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Sometimes you just need a little push and I was lucky to get it from those guys. And at the end I’m very glad I posted it—F2EM was one of my most successful projects.&lt;/p&gt;

&lt;p&gt;While I haven’t dipped my toe into the professional speaking circuit, I should thank &lt;a href="https://twitter.com/reybango"&gt;Rey Bango&lt;/a&gt; for encouraging me to submit a talk to the jQuery Conference awhile back. I’ll dive in some day Rey!&lt;/p&gt;

&lt;p&gt;I’ll keep my eyes open for someone that I can give a little push to and I encourage you to do the same. If you need my help or advice, I’d be glad to do what I can to help. Hit me up on &lt;a href="https://twitter.com/zachleat"&gt;Twitter&lt;/a&gt; or on &lt;a href="https://twitter.com/zachleat"&gt;Google Plus&lt;/a&gt;.&lt;/p&gt;

&lt;div class="google-chart"&gt;
  &lt;style&gt;
  #chart-0 .annotatedtimelinetable th, td { padding: 0; }
  #chart-0 .annotationsdiv { display: none; }
  &lt;/style&gt;
  &lt;script type="text/javascript" src="//ajax.googleapis.com/ajax/static/modules/gviz/1.0/chart.js"&gt; {"dataSourceUrl":"//docs.google.com/spreadsheet/tq?key=0Alz1CG9ZSGbWdDZtUml2TmhWYXhGeFhUMU1CMmgyRGc&amp;#038;transpose=0&amp;#038;headers=1&amp;#038;merge=COLS&amp;#038;range=A1%3AA45%2CB1%3AB45%2CC1%3AC45%2CD1%3AD45&amp;#038;gid=0&amp;#038;pub=1","options":{"displayAnnotations":false,"titleTextStyle":{"fontSize":16},"animation":{"duration":0},"displayRangeSelector":false,"hAxis":{"useFormatFromData":true,"minValue":null,"viewWindow":{"min":null,"max":null},"maxValue":null},"wmode":"opaque","vAxes":[{"useFormatFromData":true,"minValue":null,"viewWindow":{"min":null,"max":null},"maxValue":null},{"useFormatFromData":true,"minValue":null,"viewWindow":{"min":null,"max":null},"maxValue":null}],"booleanRole":"certainty","title":"Chart title","scaleType":"fixed","legend":"none","thickness":"4","displayZoomButtons":false,"width":580,"height":200},"state":{},"view":{},"chartType":"AnnotatedTimeLine","chartName":"Fumbling on Social Media"} &lt;/script&gt;
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;&lt;a href="https://docs.google.com/spreadsheet/ccc?key=0Alz1CG9ZSGbWdDZtUml2TmhWYXhGeFhUMU1CMmgyRGc"&gt;Full data available on Google Spreadsheets&lt;/a&gt;. RSS subscriber data provided by &lt;a href="http://feedburner.google.com/"&gt;Feedburner&lt;/a&gt; (even though my first post was in 2007, I switched from naked RSS in 2010). Twitter data was provided by &lt;a href="http://twittercounter.com/"&gt;TwitterCounter&lt;/a&gt; and Google data by &lt;a href="http://socialstatistics.com/"&gt;Social Statistics&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/G0qWPBFLZ1c" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>SocialCount, Faster &amp; Lighter Social Networking Widgets</title>
		<link href="http://www.zachleat.com/web/socialcount/" />
		<updated>2012-11-27T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/socialcount</id>
		<content type="html">&lt;p&gt;I’m excited to let you guys know that my first &lt;a href="http://filamentgroup.com"&gt;Filament Group&lt;/a&gt; open source project was released. I made the move to Filament to both allow more client/open-source crossover work and to collaborate with some great Front End Engineers. &lt;em&gt;SocialCount&lt;/em&gt; is the first public evidence of that goal.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;SocialCount is a small jQuery plugin for progressively enhanced, lazy loaded, mobile friendly social networking widgets.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Third party JavaScript is one of the biggest challenges we face in our quest for high performance web sites and hopefully SocialCount will help tame the slothful beast.&lt;/p&gt;

&lt;p&gt;Astute readers may recognize SocialCount from the implementation on &lt;a href="http://f2em.com"&gt;A Front End Engineer’s Manifesto&lt;/a&gt; (page 2 and the footer).&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://filamentgroup.com/lab/socialcount/"&gt;Filament Group Lab Post&lt;/a&gt;&lt;/h2&gt;

&lt;h2&gt;&lt;a href="http://github.com/filamentgroup/socialcount/"&gt;Contribute on GitHub&lt;/a&gt;&lt;/h2&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/PuGJtpx9zI0" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>A Front End Engineer’s Manifesto</title>
		<link href="http://www.zachleat.com/web/manifesto/" />
		<updated>2012-09-02T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/manifesto</id>
		<content type="html">&lt;p&gt;Early last year at Nebraska Code Camp 2011, I gave a talk to a bunch of .NET developers about my own personal perspective on the world of Front End Engineering.&lt;/p&gt;

&lt;p&gt;True to form, I developed the slide deck for the web using &lt;a href="/web/bigtext-makes-text-big/"&gt;BigText&lt;/a&gt;, &lt;a href="http://christophercliff.github.com/sausage/"&gt;sausage.js&lt;/a&gt;, and a few other self-developed but yet-to-be released plugins. I uploaded it &lt;em&gt;world wide&lt;/em&gt; for my presentation but never published the URL publicly. Unexpectedly, last week a developer from France found it and &lt;a href="https://twitter.com/NumEricR/status/239298110701068288"&gt;shared it on Twitter&lt;/a&gt;. Well, the cat is out of the bag.&lt;/p&gt;

&lt;p&gt;I’ve been reluctant to share the slides because I certainly don’t want developers to take them as dogmatic truth. Rather, I’d love for people to see a forest using trees they’ve planted themselves. Try to take a step back and see the big picture when you’re problem solving on the front end and figure out what’s important to you.&lt;/p&gt;

&lt;p&gt;So with a bit of trepidation but without further adieu:&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://f2em.com"&gt;f2em.com, A Front End Engineer’s Manifesto&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;If you’d like to see this talk live, let me know in the comments.&lt;/p&gt;

&lt;p&gt;The site is also available on &lt;a href="https://github.com/zachleat/f2em.com"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Talk Description&lt;/h3&gt;

&lt;blockquote&gt;&lt;p&gt;In the fast paced world of Front End Engineering, change reigns supreme. Dormant for years, the Browser Wars are back and have broken web development wide open. Led by competing vendors championing their own implementations of HTML5, CSS3, and other Web Standards, they’re unchaining us from the desktop computing environment. We’re seeing web browsers in our favorite Mobile Phones, E-Book Readers, and Tablet devices. Does your web site work with the Android Browser? On the iPad? How about the Kindle browser? IE9? Do you even know what version Google Chrome is on?&lt;/p&gt;

&lt;p&gt;As web programmers, how do we keep up with this blistering, nauseating pace while still taking time to improve our skills? I’ll go through a set of principles and guidelines I use to simplify the world of Front End Engineering. These criteria will help you write better future-compatible flux-resistant code. They will help you evaluate new toolsets, APIs, frameworks, and even file formats and codecs. They will improve the quality of your web sites and applications.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Many thanks to &lt;a href="http://twitter.com/natekoechley"&gt;Nate Koechley&lt;/a&gt;, who influenced some of this manifesto with his talk on &lt;a href="http://www.youtube.com/watch?v=B9n3Fy7rJmA"&gt;Professional Front End Engineering&lt;/a&gt;, and to the countless other developers and designers who have made equally important community contributions.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/a5nhj8YUOEI" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>CSS3 Job Transition</title>
		<link href="http://www.zachleat.com/web/css3-job-transition/" />
		<updated>2012-05-16T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/css3-job-transition</id>
		<content type="html">&lt;p&gt;I’m extremely excited to announce that I have accepted a full time position with &lt;a href="http://filamentgroup.com/"&gt;Filament Group&lt;/a&gt;. I will be working alongside web developer titans of industry &lt;a href="http://twitter.com/toddmparker"&gt;Todd Parker&lt;/a&gt;, &lt;a href="http://twitter.com/scottjehl"&gt;Scott Jehl&lt;/a&gt;, &lt;a href="http://twitter.com/wilto"&gt;Mat ‘Wilto’ Marquis&lt;/a&gt;, &lt;a href="http://twitter.com/pattytoland"&gt;Patty Toland&lt;/a&gt;, and &lt;a href="http://twitter.com/maggiewachs"&gt;Maggie Costello Wachs&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="nf"&gt;#zachleat&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;employment&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1209600s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* 14d */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If you’ve been living under a block-level element and aren’t familiar with Filament Group, I’m sure you’re familiar with a few of their contributions to the web development world. They’re well known for their advocacy and real world application of development practices that are important for the future of the web: Accessibility, Progressive Enhancement, and Responsive Design. They’ve literally &lt;a href="http://filamentgroup.com/dwpe/"&gt;written the book on Progressive Enhancement&lt;/a&gt;, and their recent redesign of the &lt;a href="http://bostonglobe.com/"&gt;Boston Globe&lt;/a&gt; was one of the first major large scale implementations of Responsive Design. If that weren’t enough, they are also leading the development of the &lt;a href="http://jquerymobile.com/"&gt;jQuery Mobile&lt;/a&gt; project.&lt;/p&gt;

&lt;p&gt;Woooooo!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/8Cja_-YUTmE" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Let’s get parseIntimate.</title>
		<link href="http://www.zachleat.com/web/lets-get-parseintimate/" />
		<updated>2012-02-13T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/lets-get-parseintimate</id>
		<content type="html">&lt;p&gt;This Valentine’s Day, spend a little quality time with JavaScript. Don’t be afraid to &lt;a href="http://parseintimate.com"&gt;get parseIntimate&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In all seriousness, I do still see new JavaScript developers that are unaware of the parseInt problem. I’m hoping this will raise awareness or failing that at least make some people smile.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/u4VFpPhuKCk" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Placeholder Title for Article about HTML5 Placeholders</title>
		<link href="http://www.zachleat.com/web/placeholder/" />
		<updated>2012-02-05T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/placeholder</id>
		<content type="html">&lt;p&gt;When I’m not out fighting crime, I spend my days developing reusable components for the web. One of those reusable components I wrote was an implementation of a placeholder plugin. For the sake of privacy, all component names have been anonymized so I’ll refer to this home-grown implementation as The Mankini (if for no other reason than to drive some swimwear shopping traffic to my blog).&lt;/p&gt;

&lt;p&gt;The Mankini’s development predated the HTML5 specification but the end result was functionally similar. The difference being that in addition to operating on text inputs and textareas, it also worked with LF/CR and selects (injects an option with an empty value). The HTML5 specification requires that LF/CR be stripped from the placeholder value.&lt;/p&gt;

&lt;p&gt;One of the most important design considerations our interaction design team specified for The Mankini was that it was not to be used as a replacement for a form label. It was a complement to the form label and nothing more. The &lt;a href="http://dev.w3.org/html5/spec/Overview.html#the-placeholder-attribute"&gt;HTML5 specification came to the same conclusion&lt;/a&gt;: &lt;em&gt;“The placeholder attribute should not be used as an alternative to a label.”&lt;/em&gt; The reasoning is obvious: if the form field has a non-empty value, you need to be able to easily identify the value’s semantic meaning.&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2012/02/Screen-Shot-2012-02-05-at-12.12.09-AM.png" title="An example of misused placeholders" alt="" /&gt;&lt;br/&gt;
Instead of putting the label text into the placeholder, use the placeholder to supplement the labels with an example e-mail and URL to provide more of a hint to the user for proper formatting. This example isn’t a huge usability issue since the three fields’ values would be easily identifiable, but it’s important to keep in mind.&lt;/p&gt;

&lt;h2&gt;Placeholder Testing&lt;/h2&gt;

&lt;p&gt;I decided to run a &lt;a href="http://www.zachleat.com/test/placeholder.html"&gt;few compatibility tests&lt;/a&gt; on the placeholder attribute to see where I could reuse the HTML5 placeholder inside of The Mankini (the test results are also available on &lt;a href="https://github.com/zachleat/Compatibility-Tests/blob/master/placeholder.html"&gt;GitHub&lt;/a&gt;). This yielded a few interesting things about some consistent and inconsistent cross-browser incompatibilities with the specification that I thought were worth sharing.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The HTML5 spec states that the placeholder should be visible when &lt;em&gt;“element’s value is the empty string and/or the control is not focused.”&lt;/em&gt; The and/or presents the implementor with a decision. Do they keep the placeholder text visible when the field is focused but the value is still empty? Or do I remove the placeholder when focusing into an empty field?&lt;/p&gt;

&lt;p&gt;My personal preference is that the text remains until the user starts to type. Safari 5.1, iOS 5, and Chrome 17%2B were the only browser implementations to agree with this as of time of writing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;The HTML5 spec has suggested (not required) that placeholders &lt;em&gt;only&lt;/em&gt; apply to &lt;code&gt;&amp;lt;input type="text, search, password, tel, url, email, number"&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt;. For some input types such as &lt;code&gt;hidden&lt;/code&gt;, &lt;code&gt;radio&lt;/code&gt;, or &lt;code&gt;checkbox&lt;/code&gt; this limitation makes sense, the placeholder would add nothing to these elements. But for others like &lt;code&gt;datetime&lt;/code&gt;, &lt;code&gt;date&lt;/code&gt;, &lt;code&gt;month&lt;/code&gt;, &lt;code&gt;week&lt;/code&gt;, &lt;code&gt;time&lt;/code&gt;, &lt;code&gt;datetime-local&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, or &lt;code&gt;file&lt;/code&gt; the argument can be made that it would be useful.&lt;/li&gt;
&lt;li&gt;There is &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=21286"&gt;an open WebKit issue&lt;/a&gt; to add placeholder support to contenteditable. Hopefully the specification gets modified and this gets added, as it would have been useful for my &lt;a href="http://www.zachleat.com/web/bigtext-makes-text-big/"&gt;BigText Demo Wizard&lt;/a&gt; which manually implemented that same feature.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;input type="number"&amp;gt;&lt;/code&gt; support is broken in Safari and it’s already been &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=61095"&gt;reported and fixed&lt;/a&gt;. “The future is here, just not evenly distributed.”&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;As a side note, it should be said that both Opera and iOS both have comprehensively badass support of the new HTML5 form element types.&lt;/p&gt;

&lt;h2&gt;Overlooked Polyfill Considerations&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;For those browsers that did implement the placeholder, it was well supported in password fields, showing as plaintext and then converting to masked input when the user started to enter data. This was a nice surprise, but polyfilling that behavior in old Internet Explorers will require additional lifting since dynamically changing the type attribute is not permitted.&lt;/li&gt;
&lt;li&gt;Placeholder text should not be included with form submit.&lt;/li&gt;
&lt;li&gt;Placeholder text should reinitialize on form reset (note: there is no &lt;code&gt;delegate&lt;/code&gt; event for &lt;code&gt;reset&lt;/code&gt; in jQuery)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance. Is the component required to iterate over all elements and add a class to initialize each one individually? For best performance, use CSS attribute selectors (&lt;code&gt;input[type="text"][placeholder]&lt;/code&gt;) for the default style and iterate only to remove the light gray color on form elements with non-empty values. This only requires a className modification for a much smaller set of elements, only the ones with non-empty values. Remember that the browsers we polyfill are often the slowest.&lt;/p&gt;

&lt;p&gt;Does the component modify the &lt;code&gt;className&lt;/code&gt; property on &lt;code&gt;focus&lt;/code&gt; and &lt;code&gt;blur&lt;/code&gt;? I found this to be a huge performance issue for the Mankini in IE7 and IE8 on pages with large DOM trees and was a lot faster if the Mankini only modified one element’s style (think jQuery’s &lt;code&gt;$(this).css('color', '#000')&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Clear the values on page unload. After page refresh, some browsers will attempt to save unsubmitted form values and re-enter the values when the page reloads (added after reviewing &lt;a href="https://github.com/mathiasbynens/jquery-placeholder"&gt;Mathias Bynen’s jQuery-placeholder&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Bathwater, No Babies&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://html5please.us/#placeholder"&gt;HTML5 Please&lt;/a&gt; recommends that we use the new and shiny responsibly and gives the go-ahead to use the placeholder polyfill on our pages. I humbly disagree. This seems to be the same trap we fell into for rounded corners and box shadows. We put extra effort into trying to get our sites to render and behave identically cross-browser, when we should have just let them render in old browsers without rounded corners or box-shadows at all. To test whether or not a polyfill is necessary, I created a super complex decision workflow called &lt;strong&gt;The Polyfill Test&lt;/strong&gt;. It consists of 2 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Look at your own browser statistics. If the feature is at &gt;50%, continue to Step 2.&lt;/li&gt;
&lt;li&gt;Determine if the user be able to complete their task without the feature. If the task is still completable without significant impairment, the polyfill isn’t necessary.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Globally, placeholder support is sitting at 60% and growing. This particular feature has passed the tipping point. If your audience isn’t a representative sample of the global web browser statistics (big enterprise intranets with 97% Internet Explorer), your mileage may vary.&lt;/p&gt;

&lt;p&gt;If you’re already using validation on the form fields (client and/or server side) and you’re correctly using the placeholder to supplement (not replace) the field labels, I would argue that the polyfill isn’t needed. It’s an implementation nice-to-have, not a requirement.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update: Added note about Chrome 17+ support for placeholder text remaining on focus per Mathias’ feedback below.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/W9ZBgsavXME" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Deferreds and a Better Geolocation API</title>
		<link href="http://www.zachleat.com/web/deferred-geolocation/" />
		<updated>2011-11-07T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/deferred-geolocation</id>
		<content type="html">&lt;p&gt;&lt;em&gt;Warning, this article is intended for Deferred unbelievers to convince them that Deferred objects are both easy and useful. If you’re already a Deferred object expert, you might want to skip this one.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Earlier this year I was given the opportunity to attend the jQuery Conference in San Francisco. I was delighted to go, able to finally meet some of the JavaScript greats I’d been stalking following online for years.&lt;/p&gt;

&lt;p&gt;Looking back on the conference, the one presentation that had the &lt;strong&gt;biggest impact on the way that I code&lt;/strong&gt; had to have been &lt;a href="https://twitter.com/danheberden"&gt;Dan Heberden&lt;/a&gt;‘s “&lt;a href="http://danheberden.com/presentations/deferreds-putting-laziness-to-work/"&gt;Deferreds, Putting Laziness to Work.&lt;/a&gt;” (I would be remiss if I didn’t also mention inspiration from a &lt;a href="http://speakerdeck.com/u/eliperelman/p/jquery-deferreds-and-promises"&gt;recent presentation&lt;/a&gt; by &lt;a href="https://twitter.com/eliperelman"&gt;Eli Perelman&lt;/a&gt; at the &lt;a href="http://www.meetup.com/jquery-omaha/"&gt;Omaha jQuery Meetup&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;At first, Deferred objects sound scary. I can assure you that they’re actually incredibly easy and incredibly useful. Today we’ll go through the simple task of &lt;strong&gt;reworking the &lt;a href="http://www.w3.org/TR/geolocation-API/"&gt;Geolocation API&lt;/a&gt; to use jQuery Deferred objects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here is the standard Geolocation API to retrieve the user’s current position:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="js"&gt;&lt;span class="nx"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geolocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getCurrentPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// success&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// failure&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// options&lt;/span&gt;
  &lt;span class="nx"&gt;enableHighAccuracy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;When the above API is called, a prompt is shown to the user asking if they want to divulge their location information to the domain of the currently active web site. Typically this prompt is a non-blocking asynchronous operation (although not explicitly defined in the specification).&lt;/p&gt;

&lt;p&gt;Let’s go ahead and change it to use a jQuery Deferred object:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="js"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getCurrentPositionDeferred&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;deferred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Deferred&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geolocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getCurrentPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Notice that the success callback is replaced by the deferred object’s resolve method and the error callback is replaced by the reject method. All of our function arguments are removed from the API. We’re left with one simple options argument.&lt;/p&gt;

&lt;p&gt;This allows us to do things like:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="js"&gt;&lt;span class="nx"&gt;getCurrentPositionDeferred&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;enableHighAccuracy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// success&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;fail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// failure&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;always&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// executes no matter what happens.&lt;/span&gt;
  &lt;span class="c1"&gt;// I&amp;#39;ve used this to hide loading messages.&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// You can add an arbitrary number of&lt;/span&gt;
&lt;span class="c1"&gt;// callbacks using done, fail, or always.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We could also use &lt;code&gt;$.when&lt;/code&gt; to run code upon completion of two arbitrary and contrived operations like a Geolocation call and an Ajax request. Awesome.&lt;/p&gt;

&lt;p&gt;To coordinate between multiple Deferred objects, use $.when:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="js"&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getCurrentPositionDeferred&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ajax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/someUrl&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// both the ajax call and the geolocation call have finished successfully.&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I wonder what other browser native APIs could be better served by using Deferred objects instead of function arguments.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/PZ2QSLWnLzw" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>A Mobile Web Divided</title>
		<link href="http://www.zachleat.com/web/a-mobile-web-divided/" />
		<updated>2011-08-08T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/a-mobile-web-divided</id>
		<content type="html">&lt;p&gt;Unless you’ve been living comfortably under an elaborate dwelling constructed entirely out of rock, you’re aware of the growing popularity of smartphones and other mobile devices. With that growth we’ve witnessed a bumper crop of component libraries and frameworks to enable us to create mobile web sites and applications.&lt;/p&gt;

&lt;h2&gt;One Web, Two Web Primer&lt;/h2&gt;

&lt;p&gt;There are two different approaches one can take when developing a mobile web site. The first approach has been assigned the delightfully inclusive moniker &lt;a href="http://www.w3.org/TR/mobile-bp/#OneWeb"&gt;‘&lt;em&gt;One Web&lt;/em&gt;’&lt;/a&gt;. &lt;em&gt;One Web&lt;/em&gt; involves creating a single web site accessible from both mobile and desktop web browsers and the site’s presentation is custom tailored at run time to the capabilities of the user’s device.&lt;/p&gt;

&lt;p&gt;The second approach involves creating two completely separate web sites, one for mobile and one for the desktop. The advantage with this approach is that content and the user interface can be tailored specifically for mobile, as the user’s context while using each site is likely to be drastically different. An obvious nickname for this approach might be &lt;em&gt;‘Two Web’&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Two Web&lt;/em&gt; involves a white list of mobile User Agents that server side code uses to detect mobile devices and redirects them to a mobile specific site. The remaining User Agents are left to view the desktop version. An improvement to this approach allows end users to opt-out of the mobile version by simply clicking on a link that redirects to the desktop version and persists the setting (often using a cookie).&lt;/p&gt;

&lt;p&gt;With &lt;em&gt;One Web&lt;/em&gt; the site is customized and adapted based primarily on screen dimension, orientation, and pixel density. Contrast that to &lt;em&gt;Two Web&lt;/em&gt;, which usually divides touch screen and non touch screen devices. While this may make it easier on developers, it’s awkward for users. For example, consider Google Plus on an iPad. The entire experience feels like it was intended for a small screen, and feels barren and feature-poor on the larger tablet screen. The full Google Plus web site would be better for the iPad.&lt;/p&gt;

&lt;p&gt;Other downsides to &lt;em&gt;Two Web&lt;/em&gt; include maintenance of two separate code bases, maintenance of the User Agent white list as new devices are released, and dependency on server side code to redirect mobile User Agents to the mobile site.&lt;/p&gt;

&lt;p&gt;Developers should also be aware of the historical precedence of browser vendors &lt;em&gt;borrowing&lt;/em&gt; User Agent strings from other devices as they become popular. That’s why almost all User Agents in existence today contain the string “Mozilla” and why WebKit User Agents contain “like Gecko.” Come to think of it, User Agent theft happens most often when the target is Netscape or Netscape progeny.&lt;/p&gt;

&lt;h2&gt;Make Your Choice&lt;/h2&gt;

&lt;p&gt;An informed reader might already be aware of the choice between One and &lt;em&gt;Two Web&lt;/em&gt;. What you might not be aware of is that your mobile JavaScript libraries and toolkits may have already made this choice for you. The mobile web development space is clouded with tools that don’t document their requirement of &lt;em&gt;Two Web&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Most of the tools that have been reviewed below have focused on WebKit support only. It is not the author’s desire to simply suggest that these tools should work on non-WebKit mobile browsers. &lt;strong&gt;The tools we use should not create a web divided between mobile and desktop.&lt;/strong&gt; In a theoretical world where WebKit has a global monopoly on both mobile and desktop web browsing, it would still create problems if sites are restricted to mobile only or desktop only. Developers must be aware of the compromises we’ve inherited from our tools.&lt;/p&gt;

&lt;p&gt;As of June 2011, mobile web browsing is &lt;a href="http://en.wikipedia.org/wiki/Usage_share_of_web_browsers#Summary_table"&gt;only 6.5% of all web browsing&lt;/a&gt;, while 24.5% of all web browsing is desktop WebKit (non-mobile browsers like Chrome or Safari). While evidence would suggest that the share of mobile web browsing will increase, we should be very cautious to assume that WebKit (mobile or desktop) will ever reach anything close to 100% market share.&lt;/p&gt;

&lt;p&gt;Let’s look at how a few sample pages render in a few desktop browsers. (&lt;em&gt;Keep in mind that I did not test in the other major rendering engine, Presto currently used by Opera 11.5&lt;/em&gt;)&lt;/p&gt;

&lt;h3&gt;&lt;a href="http://dev.sencha.com/deploy/touch/examples/nestedlist/"&gt;Sencha Touch 1.1.0&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Trident (IE9): Not Supported&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2011/07/Screen-Shot-2011-07-26-at-10.48.51-PM.png" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;Gecko (Firefox 5): Not Supported&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2011/07/Screen-Shot-2011-07-26-at-10.31.41-PM.png" title="Sencha Touch in Firefox" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;Instead of a nice list with large click targets, we’re greeted with a simple white screen. No error messages detailing a JavaScript error occurred on the page. No warning saying the web browser being used here isn’t supported (the bane of Progressive Enhancement advocates). Really bad user experience here.&lt;/p&gt;

&lt;p&gt;Officially, Sencha Touch support is not “anything WebKit” as some have suggested. It officially supports Apple iOS 3 , Android 2.1 , and BlackBerry 6 devices. It does not include WebOS, which is a WebKit browser, &lt;strong&gt;nor does it include any desktop web browsers.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;&lt;a href="http://www.dhtmlx.com/touch/samples/apps/uidemo/index.html"&gt;DHTMLx Touch v.1.0 RC&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Trident (IE9): Not Supported&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2011/07/Screen-Shot-2011-07-27-at-6.26.50-PM.png" title="DHTMLx Touch in IE9" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;Gecko (Firefox 5): Not Supported&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2011/07/Screen-Shot-2011-07-26-at-10.16.48-PM.png" title="DHTMLx Touch in Firefox" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;DHTMLx Touch operated much better than Sencha Touch on desktop browsers. Despite the fact that many of the demos on their website are hidden behind QR codes. You can use a &lt;a href="http://zxing.org/w/decode.jspx"&gt;QR decoder&lt;/a&gt; to get the URLs for viewing on your desktop device. As for official web browser support, the DHTMLx Touch web site states:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;While browsing the demos of DHTMLX Touch, note that the framework requires a mobile device to display and work correctly. You can also run the demos on standard PCs in Firefox 3.6 and above, and WebKit browsers (Safari, Chrome, etc.), but there still can be some issues since DHTMLX Touch is optimized for mobile devices.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Unfortunately, even though it works for the most part, desktop web browsers are still unsupported. It should also be noted that DHTMLx isn’t full WebKit either, as Blackberry 6 is not yet officially supported.&lt;/p&gt;

&lt;h3&gt;&lt;a href="http://chrism.dojotoolkit.org/mobile-0.2/make_samples/dojo-samples/demos/mobile-gallery/demo.html"&gt;Dojo Mobile 0.2&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Trident (IE9): Supported&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2011/08/Screen-Shot-2011-08-08-at-9.51.41-PM.png" title="Dojo Mobile in IE9" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;Gecko (Firefox 5): Supported&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2011/07/Screen-Shot-2011-07-26-at-10.18.51-PM.png" title="Dojo Mobile in Firefox" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;Dojo Mobile also did fairly well. There were a few minor rendering issues with WebKit prefixed gradients (and no background color fallback) which I would consider to be very minor bugs. Here’s the good news from the &lt;a href="http://dojotoolkit.org/reference-guide/dojox/mobile.html#id5"&gt;Dojo documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Dojox.mobile supports not only webkit-based mobile browsers, but also non-CSS3 desktop browsers such as IE and (older) Firefox.&lt;/p&gt;&lt;/blockquote&gt;

&lt;h3&gt;&lt;a href="http://jquerymobile.com/demos/1.0b2/#/demos/1.0b2/docs/lists/index.html"&gt;jQuery Mobile 1.0b2&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Trident (IE9): Supported&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2011/08/Screen-Shot-2011-08-08-at-10.05.50-PM.png" title="jQuery Mobile in IE9" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;Gecko (Firefox 5): Supported&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2011/07/Screen-Shot-2011-07-26-at-10.08.24-PM.png" title="jQuery Mobile in Firefox" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;In most of the other frameworks, cross browser compatibility documentation felt like an afterthought mentioned in passing. Not jQuery Mobile. It has the most complete &lt;a href="http://jquerymobile.com/gbs/"&gt;web browser support documentation&lt;/a&gt; of any mobile component framework. Not only is their documentation the best, their device support is the most comprehensive. The project officially supports Internet Explorer all the way back to version 7, which speaks volumes to their commitment to allow the developer to make the choice between &lt;em&gt;One Web&lt;/em&gt; and &lt;em&gt;Two Web&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;If you’re developing Hybrid Native applications using software like &lt;a href="http://www.phonegap.com/"&gt;PhoneGap&lt;/a&gt;, desktop web browser support doesn’t matter here. Feel free to disregard this entire article.&lt;/p&gt;

&lt;p&gt;However, if you are developing for the web I would encourage you to look strongly at &lt;em&gt;One Web&lt;/em&gt; as the default choice, and use &lt;em&gt;Two Web&lt;/em&gt; as the exception when your content and context require drastically different non-adaptable versions of the site for mobile devices. Certainly I’m not suggesting that either &lt;em&gt;One or Two Web&lt;/em&gt; are silver bullets. But we should all be aware of how the tools we choose weigh on our decision, and how this decision will affect our users in the future.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/5oT7H5q6o8A" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>FitText + BigText: A Tale of Two Plugins</title>
		<link href="http://www.zachleat.com/web/fittext-and-bigtext/" />
		<updated>2011-05-12T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/fittext-and-bigtext</id>
		<content type="html">&lt;p&gt;Earlier this week, &lt;a href="http://twitter.com/trentwalton"&gt;@TrentWalton&lt;/a&gt; &lt;a href="http://twitter.com/TrentWalton/status/67972022776508416"&gt;tweeted&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;We at &lt;a href="http://twitter.com/paravelinc"&gt;@paravelinc&lt;/a&gt; happily present to you FitText—a jQuery plugin for inflating web type:&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Naturally, I wondered how it compared to BigText, a plugin of my own creation to Make Text Big. Trent &lt;a href="http://twitter.com/TrentWalton/status/67989004427079682"&gt;continued&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;It’s in the GitHub readme, but I want to recognize BigText from &lt;a href="http://twitter.com/zachleat"&gt;@zachleat&lt;/a&gt; as another font sizer for non-fluid sites:&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;I was delighted to get some attribution from Trent, and even more delighted to see their plugin. It’s really a great piece of work. However, his statement that BigText is just for non-fluid sites is not quite accurate. Let’s dive in.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.zachleat.com/web/bigtext-makes-text-big/"&gt;&lt;img src="/web/wp-content/uploads/2011/05/Screen-shot-2011-05-12-at-11.05.26-PM.png" title="BigText" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://fittextjs.com/"&gt;&lt;img src="/web/wp-content/uploads/2011/05/Screen-shot-2011-05-12-at-11.10.01-PM.png" title="FitText" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the surface, BigText and FitText might seem very similar. In fact, they are quite different and approach what might seem to be a similar problem (resizing text to fit a container) in very different ways.&lt;/p&gt;

&lt;p&gt;At its simplest, we can boil it down like this: If you’re crafting a specific design with &lt;strong&gt;copy that is not going to change&lt;/strong&gt;, use FitText. If your &lt;strong&gt;text is dynamic&lt;/strong&gt; (maybe user generated), use BigText.&lt;/p&gt;

&lt;p&gt;Here’s more detail:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&amp;#160;&lt;/th&gt;
&lt;th&gt;BigText&lt;/th&gt;
&lt;th&gt;FitText&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Demos&lt;/th&gt;
&lt;td&gt;&lt;a href="http://jsfiddle.net/zachleat/anJpE/"&gt;BigText Fiddle&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="http://jsfiddle.net/zachleat/ExhDC/"&gt;FitText Fiddle&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;&amp;#160;&lt;/th&gt;
&lt;td colspan="2"&gt;&lt;em&gt;Try resizing the demo windows above.&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Algorithm&lt;/th&gt;
&lt;td&gt;&lt;strong&gt;Sizes text automatically&lt;/strong&gt; from a base up to fit the element width, regardless of initial font size.&lt;/td&gt;
&lt;td&gt;Uses the width of the element and a configurable JavaScript argument (the ratio) to &lt;strong&gt;scale text down&lt;/strong&gt; to smaller widths. This ratio argument must be set manually.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Responsive Design&lt;/th&gt;
&lt;td colspan="2"&gt;Both plugins work with &lt;strong&gt;responsive design techniques&lt;/strong&gt;, operating correctly with media queries, fluid designs, and window resizing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Text&lt;/th&gt;
&lt;td&gt;Works with user generated text, or any text isn&amp;#8217;t cemented at design time. See the &lt;a href="http://www.zachleat.com/bigtext/demo/"&gt;BigText Demo Wizard&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;Requires up front configuration to specific text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Resize Event&lt;/th&gt;
&lt;td&gt;Works with existing debounced resize libraries, if they exist on the page.&lt;/td&gt;
&lt;td&gt;Does not use a debounced resize event.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Unobtrusive&lt;/th&gt;
&lt;td&gt;CSS and BigText font-sizes are independent of each other.&lt;/td&gt;
&lt;td&gt;FitText uses your CSS font-size as a maximum font size.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;&amp;#160;&lt;/th&gt;
&lt;td colspan="2"&gt;&lt;em&gt;Don&amp;#8217;t forget to set sane CSS font-size defaults when JavaScript isn&amp;#8217;t available.&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Unit Tested&lt;/th&gt;
&lt;td&gt;Full Test Suite&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;&lt;strong&gt;FitText is very lightweight and fast&lt;/strong&gt;, even considering it doesn’t yet use a debounced resize event. The &lt;a href="https://github.com/davatron5000/FitText.js/blob/master/jquery.fittext.js"&gt;FitText algorithm&lt;/a&gt; is &lt;strong&gt;quite beautiful&lt;/strong&gt;. A huge well done to &lt;a href="http://paravelinc.com/"&gt;Paravel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;FitText relies on the fact that there is a &lt;strong&gt;linear relationship between font-sizes and element widths&lt;/strong&gt;. Once you’ve established the ratio between the two, it’s off to the races. In fact, it would probably be technically possible to determine the ratio solely on the initial inner-width of the text and the initial font-size. I’ll have to play around with that approach but if it works it would give an amazing speed improvement to BigText.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;font-size = outer-width / configurable-ratio&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In a perfect world, BigText and FitText could be combined, to create a &lt;em&gt;mutant auto-text-sizing plugin baby&lt;/em&gt; that gives the best of both worlds.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/13BqWBSFeOw" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Pragmatic Progressive Enhancement</title>
		<link href="http://www.zachleat.com/web/pragmatic/" />
		<updated>2011-05-09T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/pragmatic</id>
		<content type="html">&lt;p&gt;&lt;img src="/web/wp-content/uploads/2011/05/juniper.jpg" title="Juniper Plant" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;A few weeks ago at the jQuery Conference (San Francisco 2011), Nicholas Zakas delivered a wildly entertaining presentation entitled &lt;strong&gt;&lt;a href="http://www.slideshare.net/nzakas/progressive-enhancement-20"&gt;“Progressive Enhancement 2.0”&lt;/a&gt;&lt;/strong&gt; (slides 65-79 are especially great), updating the basic rules of PE for a modern age. While prior Progressive Enhancement techniques included layering content, presentation, and behavior (conveniently represented as HTML, CSS, and JavaScript). PE 2.0 (not to be confused with our other 2nd generation friend, the Web) involves &lt;strong&gt;multiple layers of CSS&lt;/strong&gt; for differing device capabilities (rounded corners for example) and &lt;strong&gt;multiple layers of JavaScript&lt;/strong&gt; (ECMAScript 5 capable browsers, for example). He made the argument that this also included &lt;strong&gt;ignoring older browsers&lt;/strong&gt; (in some cases) and only moving forward with new functionality for newer, more capable devices.&lt;/p&gt;

&lt;p&gt;Like any web developer that believes in getting actual work done, I agree with his argument but not without exemption.&lt;/p&gt;

&lt;h2&gt;Pieces of Flair&lt;/h2&gt;

&lt;p&gt;The benefit of Progressive Enhancement pays off when your code encounters a device is &lt;strong&gt;incapable of interpreting the CSS or JavaScript correctly&lt;/strong&gt; in a way the code was intended. This could be because of a bug in the rendering or JavaScript engine (or God-forbid an error in the code itself), or it could be because the feature being utilized is newer than the device itself and it could not have supported it without clairvoyance or a time machine.&lt;/p&gt;

&lt;p&gt;The example Nicholas used to display this case was the Twitter home page, which uses CSS border-radius to display rounded corners. In user agents that don’t support border-radius, such as IE&amp;lt;9, the elements have sharp rectangular corners. Using Progressive Enhancement here is a no-brainer, especially for features (like rounded corners) that have no bearing on the actual meat of the page, the content.&lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;when the feature is the content&lt;/strong&gt; and degradation requires additional work, the decision is more complex. &lt;strong&gt;HTML5 &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; probably aren’t an acceptible baseline&lt;/strong&gt; for progressive enhancement yet (based on current web browser statistics), and (video/audio) may never be an acceptable baseline depending on your views on universal accessible content. The best baseline might be a text-only transcript of the media. It really depends on how much importance the video/audio is to the core functionality of the page.&lt;/p&gt;

&lt;h2&gt;Input&lt;/h2&gt;

&lt;p&gt;Historically speaking, in order of mainstream application the progression of input devices used to interact with (even back before web) applications was: keyboard, mouse, touch, and (even more recently) speech (see the &lt;a href="http://nooshu.com/experimenting-with-webkit-form-speech-input"&gt;speech attribute on text inputs in Google Chrome&lt;/a&gt;). Logical progression concludes that we’ll see gesture APIs (think Microsoft Kinect) available at some point as well. It’s very important to consider that the &lt;strong&gt;*the mechanism of input must also be carefully layered&lt;/strong&gt;. Start with a good baseline of keyboard support for your application, then add mouse interactions, then layer any specific (multi-)touch interactions on top of that, and so on. You don’t want to skip any intermediate input layers.&lt;/p&gt;

&lt;p&gt;In Nicholas’ presentation, he presented an example of the Yahoo! homepage, specifically modified for tablet devices (slide 115). He went on to describe that the carousel functionality on the main image on the page was not available when viewing the page in Firefox. I think this is a good example of what happens when you skip layers of input interactions, moving straight to touch, without first layering mouse-based input. The approach the Yahoo! team took might be okay if you can afford to develop multiple independent code bases for a single home page, but most teams are going to want to get as much out of a single code-base as they can.&lt;/p&gt;

&lt;h2&gt;Cutting Fat&lt;/h2&gt;

&lt;p&gt;A side benefit of targeting Progressive Enhancement to your core functionality allows you to easily add ancillary features that &lt;strong&gt;don’t need to span the entirety of your browser support spectrum&lt;/strong&gt;. Some might argue that the Carousel functionality in the Yahoo! tablet example could be considered ancillary, but the positioning and screen real estate dedicated to it suggests otherwise. Facebook’s chat in IE6 is a good example of this (slide 114). Is chat part of the core functionality that Facebook wants to guarantee device independent access to? Apparently not. Making decisions in this realm involves a real cost benefit analysis, &lt;strong&gt;weighing the feature against user benefit, browser market share, and development/implementation time&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;Exceptions&lt;/h2&gt;

&lt;p&gt;It’s important to note that &lt;strong&gt;not all things can be developed using Progressive Enhancement&lt;/strong&gt;. There are certain use cases in which viewing the content in a lower fidelity than the author originally intended would destroy the value of content altogether. While these use cases are rare for most sites, most artistic endeavors can be classified as such. Consider &lt;a href="http://www.thewildernessdowntown.com/"&gt;The Wilderness Downtown&lt;/a&gt;, an amazing and beautiful interactive film built by Chris Milk using HTML5. The strong, vivid emotional connection between the film and the viewer would have been destroyed had the content been a text-based transcript, or just audio, or even just a video. &lt;strong&gt;Art must not be compromised&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now, some of you probably read the above paragraph and are thinking to yourself that your blog also qualifies under the above exemption (you’re the guy that doesn’t have full text feeds on his RSS aren’t you?). Just be real with yourself, most things probably don’t fit into the same level of interactivity as The Wilderness Downtown. &lt;strong&gt;Don’t use art as an excuse.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Start with the &lt;strong&gt;primary goal&lt;/strong&gt; of each individual page, this &lt;strong&gt;must be universally accessible&lt;/strong&gt;. If the goal is to display text content, the text must be available sans-JavaScript. If the goal is to show a video or play audio, consider a transcript as your baseline. If the goal is to solicit form input from the end user, don’t skip input interaction layers. But don’t be afraid to shirk best practices on things that aren’t necessary to that goal, like social media links, a real-time chat client, trends/statistics, etc. &lt;strong&gt;You’ll know what matters.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update: Changed the title of the article.&lt;/em&gt;
&lt;em&gt;Update: Rather than My Yahoo!, Nicholas informed me that it was just the Yahoo! homepage.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/qlXyd8CSl7g" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>HTML5 vs. Native Applications, The Presentation</title>
		<link href="http://www.zachleat.com/web/html5-vs-native-applications/" />
		<updated>2011-03-05T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/html5-vs-native-applications</id>
		<content type="html">&lt;p&gt;This slide deck was prepared for my guest lecture at the University of Nebraska-Omaha’s spring course on Mobile Application Development (BSAD 8916-005). The course was developed &lt;a href="http://googleresearch.blogspot.com/2009/07/app-inventor-for-android.html"&gt;in partnership with Google’s University Relations program&lt;/a&gt; and included a variety of business and management students with &lt;em&gt;limited programming experience&lt;/em&gt;. My lecture was approximately six weeks into the course, and the students had already developed a few simple Android applications. My task was to convince them that HTML5 and Web Development is a viable alternative to native application development, for most use cases.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(I appreciate the irony of sharing these slides using the flash plugin)&lt;/em&gt;&lt;/p&gt;

&lt;object id="__sse7160947" width="510" height="426"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=presentation-110305125324-phpapp02&amp;#038;stripped_title=html5-vs-native-applications&amp;#038;userName=zachleat" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse7160947" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=presentation-110305125324-phpapp02&amp;#038;stripped_title=html5-vs-native-applications&amp;#038;userName=zachleat" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="510" height="426"&gt;&lt;/embed&gt;&lt;/object&gt;


&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.slideshare.net/zachleat/html5-vs-native-applications/download"&gt;Download the original PDF (exported from Keynote)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/mobile/uno/Laundry-Timer/"&gt;Download the source code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;If there’s demand, I do have a video of the talk. Let me know and I can do a bit more work to package the video and upload it.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/EGDOWQuAuAY" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Raging Netflix Queue, a Google Chrome Extension</title>
		<link href="http://www.zachleat.com/web/raging-netflix-queue/" />
		<updated>2011-02-21T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/raging-netflix-queue</id>
		<content type="html">&lt;p&gt;The premise is simple. When attempting to find movies to watch in my local theater, I often stumble upon titles that I feel to be more rental quality than theater quality. So I wanted an easier way to add those movies to my Netflix queue. I created a Google Chrome extension to accomplish just that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://chrome.google.com/extensions/detail/nbnnepgogimidfbfkbcfmdeimmfadmmp"&gt;&lt;img src="/web/wp-content/uploads/2011/02/Screen-shot-2011-02-21-at-10.15.44-AM.png" alt="" /&gt;&lt;/a&gt;When Raging Netflix Queue recognizes the site you’re browsing to be a movie web site, it will show a small green Netflix icon in the address bar. Clicking that icon will add the title to your queue. If the title is available for Instant Viewing, it will go into your Instant Queue. If not available for Instant View, it will go into your DVD Queue. If the title is still in theaters and not yet available on DVD, it will go into the Saved portion of your DVD Queue, and Netflix will automatically add it to your DVD Queue when it becomes available.&lt;/p&gt;

&lt;p&gt;Raging Netflix Queue supports Rotten Tomatoes, IMDB, Google Movies, Apple Trailers, Movie Fone, movies.com, Yahoo Movies, and Fandango. Let me know if you have others you’d like to see added.&lt;/p&gt;

&lt;h2&gt;&lt;a href="https://chrome.google.com/extensions/detail/nbnnepgogimidfbfkbcfmdeimmfadmmp"&gt;Download Raging Netflix Queue&lt;/a&gt;&lt;/h2&gt;

&lt;h2&gt;Screencast&lt;/h2&gt;

&lt;div class="fluid-width-video-wrapper"&gt;&lt;iframe title="YouTube video player" src="http://www.youtube.com/embed/YuRuYdfvTA0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/div&gt;


&lt;h2&gt;Hiccups&lt;/h2&gt;

&lt;h3&gt;Years&lt;/h3&gt;

&lt;p&gt;The extension will parse the release year from the movie page, in order to guarantee better accuracy of results (There are a ton of remakes out there with the same titles). However, the actual year may vary. Some sites report theater release date, while others DVD release date, or the movie may have gone through a small showing and then a larger showing later. Thus, we allow plus or minus one year leverage when searching Netflix. See &lt;a href="http://www.rottentomatoes.com/m/cedar_rapids_2010/"&gt;Cedar Rapids (2011) on Rotten Tomatoes&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Use of “The” or And/&amp;amp;&lt;/h3&gt;

&lt;p&gt;Apple’s entry for &lt;a href="http://trailers.apple.com/trailers/universal/adjustmentbureau/"&gt;The Adjustment Bureau&lt;/a&gt; does not include “The” in the title. While this would be solved if Netflix allowed partial name matches in their OData API, Raging Netflix Queue does an additional search prepending “The” to the title, if no titles were found on the first go.&lt;/p&gt;

&lt;p&gt;Netflix requires exact name matches in their API and prefers “and” over “&amp;amp;” in my tests. Raging Netflix Queue does a simple string replace there.&lt;/p&gt;

&lt;h3&gt;Single Quotes&lt;/h3&gt;

&lt;p&gt;Titles like “The King’s Speech” don’t match, due to another limitation with the &lt;a href="http://developer.netflix.com/docs/oData_Catalog"&gt;Netflix OData API&lt;/a&gt;. There is no way to escape single quotes in the query string. I’m waiting on Netflix for an answer there.&lt;/p&gt;

&lt;h2&gt;Hindsight&lt;/h2&gt;

&lt;p&gt;It’s true that I have built a &lt;a href="/web/2007/04/18/javascript-code-coverage-tool-for-firebug/"&gt;web browser plugin (to an add-on) before&lt;/a&gt;, and even a &lt;a href="/web/2010/07/19/dom-sailbloat/"&gt;plug-in to a ported web browser add-on&lt;/a&gt;, but it was a great experience to build an actual web browser extension and Google Chrome has made it very easy to do so. This was also a &lt;strong&gt;jQuery-free project&lt;/strong&gt;, as I would think that all Google Chrome extensions would be. jQuery is intended to solve cross browser compatibility issues, and a web browser specific extension shouldn’t have any of those. Sure, it feels like you’re being spoiled to use native String &lt;code&gt;trim()&lt;/code&gt;, Array &lt;code&gt;forEach&lt;/code&gt;, and &lt;code&gt;document.querySelector&lt;/code&gt;. But damn it, I deserve nice things every once in awhile.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.southparkstudios.com/clips/155280/raging-clues"&gt;&lt;em&gt;I’m getting such a huge queue right now.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/vUr65bzLv8o" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>The JavaScript Testing Challenge Winner</title>
		<link href="http://www.zachleat.com/web/javascript-tdd-winner/" />
		<updated>2011-02-14T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/javascript-tdd-winner</id>
		<content type="html">&lt;p&gt;Congratulations to &lt;a href="http://twitter.com/stevelove"&gt;Steve Love&lt;/a&gt;, who was the first to complete &lt;a href="/web/2010/11/13/javascript-tdd/"&gt;The JavaScript Testing Challenge&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://tddjs.com/"&gt;&lt;img src="/web/wp-content/uploads/2011/02/ttdjs.png" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;He wins a copy of &lt;a href="http://twitter.com/cjno"&gt;Christian Johansen&lt;/a&gt;‘s book, &lt;a href="http://tddjs.com/"&gt;Test-Driven JavaScript Development&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you code for a living, testing will make your life easier. Even though the contest is over, I encourage you to go through the steps and complete the original challenge, if for no other reason than to see how easy it is to get a simple testing environment set up with JsTestDriver.&lt;/p&gt;

&lt;p&gt;Stay tuned for more coding challenges!&lt;/p&gt;

&lt;p&gt;Related: &lt;a href="/web/2011/01/09/javascript-tdd-update/"&gt;An Update to The JavaScript Testing Challenge&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s Steve’s screencast (using, I assume, a mechanical keyboard?):&lt;/p&gt;

&lt;object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0' width='560' height='345'&gt;&lt;param name='movie' value='http://screenr.com/Content/assets/screenr_1116090935.swf' &gt;&lt;/param&gt;&lt;param name='flashvars' value='i=170158' &gt;&lt;/param&gt;&lt;param name='allowFullScreen' value='true' &gt;&lt;/param&gt;&lt;embed src='http://screenr.com/Content/assets/screenr_1116090935.swf' flashvars='i=170158' allowFullScreen='true' width='560' height='345' pluginspage='http://www.macromedia.com/go/getflashplayer' &gt;&lt;/embed&gt;&lt;/object&gt;

&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/nmQq9leZw9A" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Et tu, X-UA-Compatible?</title>
		<link href="http://www.zachleat.com/web/et-tu-x-ua-compatible/" />
		<updated>2011-02-06T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/et-tu-x-ua-compatible</id>
		<content type="html">&lt;p&gt;&lt;a href="http://www.flickr.com/photos/jedibfa/5067647765/"&gt;&lt;img src="/web/wp-content/uploads/2011/02/juliusceasar.jpg" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or, the story of how I learned that &lt;strong&gt;the X-UA-Compatible header/meta tag is NOT the same as the Internet Explorer 8 Compatibility View button&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please note that the following information may be common knowledge, as this behavior is as described in the pre-requisite &lt;a href="http://blogs.msdn.com/b/ie/archive/2010/10/19/testing-sites-with-browser-mode-vs-doc-mode.aspx"&gt;Microsoft documentation&lt;/a&gt; on the subject. However, I feel this behavior to be unintuitive and requiring more explicit communication.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Library developers live in a much different world from full stack developers. If you’re supplying code that will be used by others, you’re faced with a different set of priorities. As such, the library I manage provides certain user agent sniffing conveniences, namely classes to replace CSS Hacks (similar to the approach used in HTML Boilerplate to provide ie6 through ie9 classes on the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; tag) and JavaScript booleans (similar to &lt;a href="http://api.jquery.com/jQuery.browser"&gt;&lt;code&gt;jQuery.browser&lt;/code&gt;&lt;/a&gt;). Much like jQuery, &lt;a href="http://docs.jquery.com/Release:jQuery_1.3#No_More_Browser_Sniffing"&gt;these conveniences remain&lt;/a&gt; for backwards compatibility.&lt;/p&gt;

&lt;p&gt;The purpose of this post is in fact not to convince you whether or not User Agent Sniffing is a &lt;a href="http://infrequently.org/2011/01/cutting-the-interrogation-short/"&gt;good tradeoff for performance&lt;/a&gt; (even though, in some cases I believe it is), but instead to provide further evidence that using the User Agent alone is an unreliable method to determine the rendering engine of the web browser, and must be complemented with other approaches. &lt;strong&gt;If you’re going to sniff, you have to sniff harder.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;X-UA-Compatible Breaks navigator.userAgent&lt;/h2&gt;

&lt;p&gt;Microsoft defines two terms to help communicate how new versions of Internet Explorer render a page: Browser Mode and Document Mode. Browser Modes are determined prior to any request made to the server (and cannot be changed by web developers). If the user triggers an IE7 Browser Mode using the Compatibility View Button, a new request is made to the server. Document Modes are determined in the page response.&lt;/p&gt;

&lt;h3&gt;Compatibility View Button Flow&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;User presses the Compatibility View button. This changes the Browser Mode.&lt;/li&gt;
&lt;li&gt;Request sent (since the Browser Mode has changed, &lt;strong&gt;the User-Agent is also changed&lt;/strong&gt; to MSIE 7.0)&lt;/li&gt;
&lt;li&gt;Response from Server&lt;/li&gt;
&lt;li&gt;Document Mode determined&lt;/li&gt;
&lt;/ol&gt;


&lt;h3&gt;X-UA-Compatible Flow&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Internet Explorer uses the default Browser Mode (newest available in the browser)&lt;/li&gt;
&lt;li&gt;Request sent (Browser Mode determines User-Agent to send, probably MSIE 8.0 or MSIE 9.0)&lt;/li&gt;
&lt;li&gt;Response from Server. Content may include X-UA-Compatible &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag and/or Response HTTP headers such as X-UA-Compatible).&lt;/li&gt;
&lt;li&gt;Document Mode determined, using X-UA-Compatible and the DocType&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;If a X-UA-Compatible header is sent back in the Compatibility View flow, it will take precedence but obviously will not change the request User-Agent HTTP header.&lt;/p&gt;

&lt;p&gt;It’s important to note that since the request has already gone before the Document Mode is determined, the Document Mode has no bearing on the request User-Agent HTTP header. While Microsoft probably could have changed &lt;code&gt;navigator.userAgent&lt;/code&gt; to be different than the request User-Agent HTTP header, I feel they made the correct decision is keeping the same value. &lt;code&gt;navigator.userAgent&lt;/code&gt; remains the same value as the request User-Agent HTTP header in IE8, but Microsoft changed this behavior in IE9. In IE9, &lt;code&gt;navigator.userAgent&lt;/code&gt; represents the document mode, not the request User-Agent header.&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2011/02/Screen-shot-2011-02-06-at-1.27.14-PM.png" title="Screenshot of Microsoft Documentation" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;The User Agent isn’t the only thing being determined. The prerequisite Microsoft documentation states that the Browser Mode determines the User Agent, Default Document Mode, and Conditional Comments. This is not accurate. &lt;strong&gt;The Document Mode determines which Conditional Comments execute, not the Browser Mode.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Also note that using IE’s &lt;strong&gt;Conditional Compilation&lt;/strong&gt; feature to return the version of JScript will be the same, independent of Document Mode.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var ie = /*@cc_on @_jscript_version @*/0;
// Always returns 5.8 in IE8, independent of Document Mode.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Example Code from &lt;a href="https://github.com/scottjehl/Respond/blob/aedc482328a4cbd9d74c5de178eb2cb974b67af5/respond.src.js#L171"&gt;Scott Jehl’s respond.js&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;Test Pages&lt;/h3&gt;

&lt;p&gt;Try the following tests in Internet Explorer 8 to test for yourself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="/test/x-ua-compatible/index.html"&gt;Stock Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/test/x-ua-compatible/ie7.html"&gt;Setting X-UA-Compatible IE=7 using a Meta Tag&lt;/a&gt; (or &lt;a href="/test/x-ua-compatible/emulateie7.html"&gt;IE=EmulateIE7&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="/test/x-ua-compatible/header-ie7/ie7.html"&gt;Setting X-UA-Compatible IE=7 using an HTTP Header&lt;/a&gt; (or &lt;a href="/test/x-ua-compatible/header-emulateie7/emulateie7.html"&gt;IE=EmulateIE7&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;What Does This Mean?&lt;/h2&gt;

&lt;p&gt;If you use X-UA-Compatible to change the Document Mode/IE Trident rendering engine, any client side code relying on &lt;code&gt;navigator.userAgent&lt;/code&gt; (such as jQuery.browser) or server side code relying on the User-Agent HTTP Header will be incorrect. Since we can’t rely on the User Agent, what can we use? Microsoft does provide a &lt;code&gt;document.documentMode&lt;/code&gt; integer we could use, pretty easily. But, I think there is a better approach.&lt;/p&gt;

&lt;p&gt;Consider &lt;a href="https://gist.github.com/527683"&gt;a great piece of JavaScript written by James Padosley&lt;/a&gt; to find Internet Explorer version numbers using Conditional Comments. His code seemed to meld perfectly with the above realization that the Document Mode determines Conditional Comment execution. We can use this to fix &lt;code&gt;jQuery.browser&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Place this script after jQuery, but before any code that uses jQuery.browser
// Modified to only test for IE 6 , since jQuery only supports 6 
(function($)
{
    if(!$.browser.msie) {
        return;
    }

    var v = 5,
        div = document.createElement('div'),
        all = div.getElementsByTagName('i');

    while (
        div.innerHTML = '',
        all[0]
    );

    $.browser.version = v;
})(jQuery);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, of course, since we’re creating nodes there is a small performance penalty in using the above script over Regular Expressions and document.documentMode. I feel this to be worthwhile, given that I’ve been &lt;a href="/web/2008/10/19/jquery-bug-ie-reports-incorrect-browserversion/"&gt;burned by Internet Explorer’s version number before&lt;/a&gt;. But next time, I reserve the right to choose performance over simplicity.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/XuRQQpzi2Hg" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>BigText Makes Text Big</title>
		<link href="http://www.zachleat.com/web/bigtext-makes-text-big/" />
		<updated>2011-01-11T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/bigtext-makes-text-big</id>
		<content type="html">&lt;p&gt;*I like shortcuts: Fork &lt;a href="https://github.com/zachleat/BigText"&gt;BigText on Github&lt;/a&gt; or Check out the &lt;a href="/bigtext/demo/"&gt;BigText Demo Wizard&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It all began with a simple web foray to &lt;a href="http://designingmonsters.com/"&gt;Designing Monsters&lt;/a&gt;. Their simple, typographic design was beautiful. But why? Their combination of the beautiful League Gothic font, use of &lt;a href="http://letteringjs.com/"&gt;Lettering.JS&lt;/a&gt;, and some simple font scaling gave the page a wonderful consistent vertical alignment. Like the Million Dollar Homepage, I wanted to rebuild it — but I didn’t want to spend a lot of time manually adjusting font sizes. So I did what any programmer with the jQuery Golden Hammer would do, I turned my problem into a nail.&lt;/p&gt;

&lt;p&gt; &lt;img src="/web/wp-content/uploads/2011/01/Screen-shot-2011-01-11-at-7.37.54-PM.png" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;At its simplest, the BigText jQuery plugin takes a single element and &lt;strong&gt;sizes the text inside of its child &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s to fit the width of the parent element&lt;/strong&gt;. Gives the text that lovely vertical alignment.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;div id="bigtext" style="width: 300px"&amp;gt;
    &amp;lt;div&amp;gt;The elusive&amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;BIGTEXT&amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;plugin exclusively&amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;captured on film&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;

$('#bigtext').bigtext();
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Implementation Details&lt;/h2&gt;

&lt;p&gt;The plugin itself is more than just a simple font-size incrementer. I wasn’t happy with the performance of simply iterating through font sizes with a single fixed interval. I decided it would be better to test multiple decreasing intervals. For each line, it increments first by &lt;code&gt;16em&lt;/code&gt; until it detects a line break, backs off an interval then increments by &lt;code&gt;8em&lt;/code&gt;. It continues with &lt;code&gt;4em&lt;/code&gt;, &lt;code&gt;2em&lt;/code&gt;, &lt;code&gt;1em&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;.&lt;code&gt;1em&lt;/code&gt;, until it finds the correct font-size to the nearest hundredth of an em. It’s noteworthy that Webkit does not respect font-sizes to the nearest hundredth, it’s precision is maxed out at tenths. This algorithm results in fewer tests in most cases, especially where the resulting font-size will be very large. Performance is always important. After font-size, it moves to word-spacing as a backup for extra precision, especially needed on Webkit.&lt;/p&gt;

&lt;h2&gt;&lt;a href="/bigtext/demo/"&gt;The BigText Demo Wizard&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;This is where the magic happens.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Editable text (&lt;code&gt;contenteditable&lt;/code&gt;), and BigText will run on every keyup event to resize what you’re typing.&lt;/li&gt;
&lt;li&gt;Dynamic horizontal and vertical centering using &lt;a href="http://infrequently.org/2009/08/css-3-progress/"&gt;Alex Russell’s Flex Box CSS classes&lt;/a&gt; (This is easy now, hooray!)&lt;/li&gt;
&lt;li&gt;3D transforms (browser support checked using &lt;a href="http://www.modernizr.com/"&gt;Modernizr&lt;/a&gt;, currently only available in Safari. Note: Chrome flattens to 2D space)&lt;/li&gt;
&lt;li&gt;Custom fonts are loaded using &lt;a href="http://code.google.com/apis/webfonts/docs/webfont_loader.html"&gt;Google’s Font Loader JavaScript API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://benalman.com/projects/jquery-throttle-debounce-plugin/"&gt;Ben Alman’s Throttle Plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The rest is mostly jQuery UI with the &lt;a href="http://taitems.tumblr.com/post/482577430/introducing-aristo-a-jquery-ui-theme"&gt;Aristo theme&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Turns out, the &lt;em&gt;BigText Demo Wizard&lt;/em&gt; makes for really easy &lt;a href="http://vimeo.com/channels/kinetictypography"&gt;Kinetic Typography&lt;/a&gt; screencasts (not amazing, but surely easy):&lt;/p&gt;

&lt;div class="fluid-width-video-wrapper"&gt;&lt;iframe class="youtube-player" type="text/html" width="640" height="385" src="http://www.youtube.com/embed/OuqB6e6NPRM" frameborder="0"&gt;&lt;/iframe&gt;&lt;/div&gt;


&lt;p&gt;The above is simply the manual process of typing lyrics into the &lt;em&gt;BigText Demo Wizard&lt;/em&gt;. You can easily make one of these too, with the help of the following keyboard shortcuts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CTRL + ALT + X: Set the text to a random 3D transform angle.&lt;/li&gt;
&lt;li&gt;CTRL + ALT + C: Toggles between white and black background.&lt;/li&gt;
&lt;li&gt;CTRL + ALT + R: Reset 3D to default state.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CTRL + ALT + SPACE: Fade out current text, clears the text, sets a random 3D transform angle, ready to type!&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;CTRL + ALT + ENTER: Same as CTRL + ALT + SPACE, but keeps the same 3D transform angle.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The fun part about the &lt;em&gt;BigText Demo Wizard&lt;/em&gt; for me was that it almost turned into a non-musical instrument when I used it real-time to complement music. Feel free to cruise Pandora and type lyrics to the music until your wrists get sore. &lt;strong&gt;What can you make with it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The BigText Demo Wizard was tested manually in Safari 5, Chrome 8, Opera 11, Firefox 3.6, and Internet Explorer 8. The BigText jQuery plugin has a full JsTestDriver suite, available on &lt;a href="https://github.com/zachleat/BigText"&gt;GitHub&lt;/a&gt;. Just run ./test.sh or test.bat&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/n9RfsZEOq4w" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>An Update to The JavaScript Testing Challenge</title>
		<link href="http://www.zachleat.com/web/javascript-tdd-update/" />
		<updated>2011-01-09T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/javascript-tdd-update</id>
		<content type="html">&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update&lt;/strong&gt;: &lt;a href="/web/2011/02/14/javascript-tdd-winner/"&gt;The JavaScript Testing Challenge Winner&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="/web/2010/11/13/javascript-tdd/"&gt;The JavaScript Testing Challenge&lt;/a&gt;, I asked JavaScript developers of the world to change their heathen ways and embrace the future of automated testing for a healthier and brighter tomorrow.&lt;/p&gt;

&lt;p&gt;However, due to seasonal timing or otherwise real life related reasons, the challenge was greeted with a worldwide chorus of universally blank stares. So, in the true spirit of Christmas, I’m removing the deadline and &lt;strong&gt;will award the grand prize to the developer with the first correct and complete PrimeFactors code kata screencast&lt;/strong&gt;. That’s right, be the first to answer the challenge will win a copy of Test-Driven JavaScript Development by Christian Johansen (PDF or Print version, your choice).&lt;/p&gt;

&lt;p&gt;If you have any questions or need help getting started, let me know! I’d be glad to help. Good luck!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Time of entry will be based on the twitter at message sent to @zachleat. Full restrictions and rules posted &lt;a href="/web/2010/11/13/javascript-tdd/"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/FvulT8FVcxQ" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>The JavaScript Testing Challenge</title>
		<link href="http://www.zachleat.com/web/javascript-tdd/" />
		<updated>2010-11-13T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/javascript-tdd</id>
		<content type="html">&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update 2&lt;/strong&gt;: &lt;a href="/web/2011/02/14/javascript-tdd-winner/"&gt;The JavaScript Testing Challenge Winner&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update&lt;/strong&gt;: &lt;a href="/web/2011/01/09/javascript-tdd-update/"&gt;An Update to The JavaScript Testing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Think back to the last time you wrote new code from scratch. Not autogenerated Dreamweaver image hovers or a pasted script from Dynamic Drive, but pure unadulterated new code. What was your process? I’m betting it’s probably similar to: (1) code, (2) switch to a browser, (3) confirm desired behavior for the change you’ve made, and (4) repeat.&lt;/p&gt;

&lt;p&gt;Comrades, let me assure you that there is a better way, and it starts with writing unit tests. As a Front End Engineer that’s been doing it bareback without tests since I started in 1997, let me assure you that adopting automated testing strategies is one of the &lt;strong&gt;single best changes I’ve made to my development cycle&lt;/strong&gt; to make myself more productive. Enough fluff. Let’s get started!&lt;/p&gt;

&lt;h2&gt;Testing Environment Setup in 3 Steps&lt;/h2&gt;

&lt;p&gt;Prerequisite: Java on the classpath&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download the &lt;a href="https://github.com/zachleat/JavaScript-Code-Katas/zipball/master"&gt;JavaScript-Code-Katas Source (ZIP)&lt;/a&gt; (or checkout the code from the &lt;a href="https://github.com/zachleat/JavaScript-Code-Katas"&gt;Github Repository&lt;/a&gt;, if you have git available)&lt;/li&gt;
&lt;li&gt;Extract and browse to it using your operating system’s command line.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run (Windows)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;gt; JsTestDriver.bat Template&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Run (MacOS)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ ./JsTestDriver.sh Template&lt;/code&gt;&lt;br/&gt;
&lt;em&gt;This script will close Safari (be careful if you’re using Safari in other windows)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;If a web browser popped up on your screen, congratulations! You have an automated testing environment set up and running. Easy, right?&lt;/p&gt;

&lt;h2&gt;Writing a Test&lt;/h2&gt;

&lt;p&gt;Now, let’s write our first test!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open up &lt;code&gt;templateTest.js&lt;/code&gt; in your favorite IDE.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the following:     TemplateTest = TestCase('TemplateTest');&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TemplateTest.prototype.testSample = function()
{
    assertTrue(true);
    assertFalse(false);
    assertEquals(true, true);
};
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Re-run the JsTestDriver shell script from Step #3 above.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Now you should see something like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Total 1 tests (Passed: 1; Fails: 0; Errors: 0) (2.00 ms)
  Safari 533.18.5 Mac OS: Run 1 tests (Passed: 1; Fails: 0; Errors 0) (2.00 ms)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Notice how you didn’t have to touch any HTML boilerplate code or manually bring up a web browser?&lt;/strong&gt; Productivity ensues! You’ve made it this far, are you brave enough to dive into a Code Kata?&lt;/p&gt;

&lt;h2&gt;Prime Factors Code Kata&lt;/h2&gt;

&lt;p&gt;Code Katas are just small programs used as practice. They’re a great way to introduce Test Driven Development and improve proficiency with your IDE.&lt;/p&gt;

&lt;p&gt;The Prime Factors Code Kata requires a function that takes a single integer argument and returns an array of prime factors of that argument in ascending numerical order. For example, passing in &lt;code&gt;8&lt;/code&gt; should return &lt;code&gt;2, 2, 2&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.google.com/present/edit?id=0AVz1CG9ZSGbWZG5iajc4c18zN2R2NzJnZmRq&amp;amp;hl=en&amp;amp;authkey=CO38t6gL"&gt;Original Java version by Uncle Bob Martin&lt;/a&gt; (see &lt;a href="http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata"&gt;original post&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/zachleat/JavaScript-Code-Katas/blob/master/PrimeFactors/primeFactors.js"&gt;JavaScript implementation of the Prime Factors algorithm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I’ve recorded an unmodified single-take screencast of myself performing the kata below. I’m using the same source code I provided above, but with the &lt;a href="http://code.google.com/p/js-test-driver/wiki/UsingTheEclipsePlugin"&gt;JsTestDriver Eclipse plugin&lt;/a&gt; instead of using the command line to run the tests. The plugin is great for the screencast, because it very easily shows when the tests are failing or passing. You might also notice that it reruns the tests automatically every time I save.&lt;/p&gt;

&lt;div class="fluid-width-video-wrapper"&gt;&lt;iframe width="560" height="315" src="http://www.youtube.com/embed/zsCYkmAJBAY" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/div&gt;


&lt;h2&gt;JsTestDriver&lt;/h2&gt;

&lt;p&gt;If you want to learn more a about JsTestDriver, check out their &lt;a href="http://code.google.com/p/js-test-driver/"&gt;Google Code&lt;/a&gt; page. “But I use QUnit!” you say. That’s fine, &lt;a href="http://code.google.com/p/js-test-driver/wiki/QUnitAdapter"&gt;there is an adaptor for that&lt;/a&gt;. Using both tools together, you won’t need to launch each individual browser manually and trigger the tests to start. It will save you time.&lt;/p&gt;

&lt;p&gt;In the interest of full disclosure, here are the issues I’ve ran into so far using JsTestDriver:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Doesn’t apply CSS in some browsers. &lt;a href="http://code.google.com/p/js-test-driver/issues/detail?id=81"&gt;Issue #81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Defaults to quirks mode. &lt;a href="http://code.google.com/p/js-test-driver/issues/detail?id=79"&gt;Issue #79&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Challenge&lt;/h2&gt;

&lt;p&gt;Testing will help you. It will improve your the quality of your code and your productivity. I challenge you to practice the JavaScript Prime Factors Code Kata in your own IDE with your own automated testing process. Send a link to me on Twitter (&lt;a href="http://twitter.com/zachleat"&gt;@zachleat&lt;/a&gt;) with an unmodified single-take screencast of you performing the kata (in JavaScript) by December 25, 2010 and &lt;strong&gt;the fastest kata screencast will win a copy of &lt;a href="http://tddjs.com/"&gt;Test-Driven JavaScript Development&lt;/a&gt;&lt;/strong&gt; by &lt;a href="http://twitter.com/cjno/"&gt;Christian Johansen&lt;/a&gt; (PDF or Print version, your choice*).&lt;/p&gt;

&lt;p&gt;&lt;a href="http://screenr.com/"&gt;Screenr&lt;/a&gt; is a great tool for recording screencasts, if you need one.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Coding must follow every step performed by myself in the above version. Templates and keyboard shortcuts can be used at your leisure, but no code can be generated specific to the kata itself (it must be a generic). Use your best judgement here, I reserve the right to disqualify any entries submitted that don’t follow the true spirit of the competition.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don’t fuck with the speed of the video. I’m spending my own money on this, so if you’re cheating then you’re just stealing from me. Just be cool about it, okay?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Print version of the prize is restricted to USA or Canada, PDF version is available internationally (unless you want to work something out for shipping costs).&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/PUzJb37Fg98" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Faking Onload for Link Elements</title>
		<link href="http://www.zachleat.com/web/load-css-dynamically/" />
		<updated>2010-07-29T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/load-css-dynamically</id>
		<content type="html">&lt;p&gt;&lt;strong&gt;Updated 2011/09/27: Rejoice! This issue has now &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=185236"&gt;been fixed in Firefox&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Or, &lt;strong&gt;I Am Dynamically Loaded CSS (and So Can You!)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dynamic resource loading is one of the keys to have a performance happy web application. There are generally three different criteria we must address when making a request: cross domain security policies, asynchronous/synchronous (will it block the host page while loading), and whether or not events are triggered when the request completes.&lt;/p&gt;

&lt;p&gt;If the resource and host page are on the same domain, obviously &lt;code&gt;XMLHttpRequest&lt;/code&gt; works the best. We can control whether or not the resource is loaded asynchronously or synchronously, and we know exactly when it gets done.&lt;/p&gt;

&lt;p&gt;If the resource and host page are on different domains (increasingly more common with CDN’s), our options narrow. Loading the JavaScript is a solved problem, just use the &lt;code&gt;onload&lt;/code&gt; event on the &lt;code&gt;` tag and you’re good to go (&lt;/code&gt;onreadystatechange` for IE). But CSS is more complicated.&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Option for (a)synchronous&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript/CSS Same Domain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;XMLHttpRequest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Both&lt;/td&gt;
&lt;td&gt;&lt;code&gt;onreadystatechange&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript Different Domain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Synchronous (Asynchronous where &lt;a href="https://developer.mozilla.org/en/html/element/script"&gt;async property&lt;/a&gt; is supported)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;onload&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;onreadystatechange&lt;/code&gt; for IE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS  Different Domain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Asynchronous&lt;/td&gt;
&lt;td&gt;&lt;em&gt;What this blog post is about.&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;h2&gt;Existing Solutions&lt;/h2&gt;

&lt;p&gt;In all of the library source code I evaluated, Internet Explorer didn’t cause any issues. It fires both the &lt;code&gt;onload&lt;/code&gt; and &lt;code&gt;onreadystatechange&lt;/code&gt; events for `` nodes. Obviously this is ideal behavior, and IE got it right. But what about Firefox and Safari/Chrome?&lt;/p&gt;

&lt;h3&gt;YUI 2.8.1 and 3.1.1&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://github.com/yui/yui3/blob/master/build/yui/get.js#L311"&gt;Original Source&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// FireFox does not support the onload event for link nodes, so there is
// no way to make the css requests synchronous. This means that the css 
// rules in multiple files could be applied out of order in this browser
// if a later request returns before an earlier one.  Safari too.
if ((ua.webkit || ua.gecko) &amp;amp;&amp;amp; q.type === "css") {
    _next(id, url);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I wouldn’t be surprised if the commit log there was from Bon Jovi; that code is living on a prayer.&lt;/p&gt;

&lt;h3&gt;LazyLoad&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://github.com/rgrove/lazyload/blob/master/lazyload.js#L283"&gt;Original Source&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Gecko and WebKit don't support the onload event on link nodes. In
// WebKit, we can poll for changes to document.styleSheets to figure out
// when stylesheets have loaded, but in Gecko we just have to finish
// after a brief delay and hope for the best.
if (ua.webkit) {
    // resolve relative URLs (or polling won't work)
    p.urls[i] = node.href;
    poll();
} else {
    setTimeout(_finish, 50 * len);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Better, closer, warmer. This includes a nice method for working with webkit browsers. The poll method compares &lt;code&gt;document.styleSheets&lt;/code&gt;, since Webkit has the nice option of only appending to the styleSheets object when the styleSheet has successfully loaded.&lt;/p&gt;

&lt;p&gt;So we have working solutions for IE and Safari/Chrome. The only unsolved piece of the puzzle here is Firefox.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://wonko.com/post/how-to-prevent-yui-get-race-conditions"&gt;This post&lt;/a&gt; from the same author as LazyLoad also describes another solution which involves modifying the source CSS and polling against it. But that’s not really ideal. Can we do better?&lt;/p&gt;

&lt;h2&gt;Solution&lt;/h2&gt;

&lt;p&gt;Here’s what I came up with (using jQuery for brevity, note that this solution &lt;strong&gt;only fixes Firefox&lt;/strong&gt;, and does not incorporate the above already solved solutions):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var url = 'css.php',
    id = 'dynamicCss' + (new Date).getTime();

$('&amp;lt;style/&amp;gt;').attr({
    id: id,
    type: 'text/css'
}).html('@import url(' + url + ')').appendTo(document.getElementsByTagName('head')[0]);

function poll() {
    try {
        var sheets = document.styleSheets;
        for(var j=, k=sheets.length; j&amp;lt;k; j++) {
            if(sheets[j].ownerNode.id == id) {
                sheets[j].cssRules;
            }
        }
        // If you made it here, success!
        alert('success!');
    } catch(e) {
        window.setTimeout(poll, 50);
    }
}

window.setTimeout(poll, 50);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;&lt;a href="/javascript/loadcss/load.html"&gt;See this Demo in Action&lt;/a&gt; (Firefox Only)&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Update: After much joy and celebration, I have discovered that an approach similar to the above was written by Oleg Slobodskoi in his &lt;a href="http://plugins.jquery.com/files/jquery.xLazyLoader.js.txt"&gt;xLazyLoader&lt;/a&gt; plugin for jQuery. It shouldn’t be surprising that two independent developers might reach the same solution, and is just more proof that software patents are stupid. :)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update #2 Added note about HTML5 async property on script tags.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/fnv4r5UoREI" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>ALARMd is now on Github</title>
		<link href="http://www.zachleat.com/web/alarmd-is-now-on-github/" />
		<updated>2010-07-21T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/alarmd-is-now-on-github</id>
		<content type="html">&lt;p&gt;In an effort to &lt;del&gt;mindlessly copy what everyone else on the internet is doing&lt;/del&gt; keep current on the latest and greatest Source Code Management tools, I decided that it would be good practice to move my open source project ALARMd (as seen on &lt;a href="http://lifehacker.com/271043/wake-up-to-a-youtube-video-with-alarmd"&gt;Lifehacker&lt;/a&gt;) from &lt;a href="/web/2008/10/08/alarmd-is-a-google-code-project/"&gt;Google Code&lt;/a&gt; to Github.&lt;/p&gt;

&lt;p&gt;Feel free to fork/contribute at your leisure.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://github.com/zachleat/ALARMd"&gt;http://github.com/zachleat/ALARMd&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re new, you can check out &lt;a href="http://www.alarmd.com/"&gt;ALARMd.com&lt;/a&gt; to see what I’m talking about.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/PNeINiLAWGw" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Maiden Voyage of the DOM Sailbloat</title>
		<link href="http://www.zachleat.com/web/dom-sailbloat/" />
		<updated>2010-07-19T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/dom-sailbloat</id>
		<content type="html">&lt;p&gt;&lt;img src="/web/wp-content/uploads/2010/07/typhoon-in-macao.jpg" title="typhoon-in-macao" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;As many of you may already know, my day job includes managing a large and complex enterprise jQuery-based user interface component library. It’s used by all new web applications at the company, which boasts over an IT department of approximately 1500 people and hundreds of web applications. Needless to say, I get a fair volume of interesting support tickets that come my way. A few weeks ago, I had the pleasure of receiving one such ticket.&lt;/p&gt;

&lt;p&gt;The support ticket’s symptoms included a oft-heard complaint: poor performance. On the web, poor performance can be attributed to a great many things, but most often can be boiled down to a bottleneck in JavaScript code using the DOM API. This time, strangely enough, the culprit was something else entirely.&lt;/p&gt;

&lt;p&gt;One of the first things I check when an application complains of poor performance is the total size of the document, or how many nodes it has. One of the best ways to ensure good performance is to keep your document small, especially on projects using heavy dynamic element selection and filtering (think jQuery, Mootools, Prototype, Dojo, or any code using a selector engine like Sizzle). Any JavaScript library emulating CSS selectors executing over a very large document is going to take quite a bit longer than querying a small document, especially when the user’s browser doesn’t support native &lt;code&gt;querySelector&lt;/code&gt; or &lt;code&gt;getElementsByClassName&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To get an idea of what the size of a large document is, I usually go to a site with some fairly advanced JavaScript and query their size.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Returns the total number of nodes in the document
document.getElementsByTagName('*').length;
// note: this number will not include any child nodes inside of iframes.
&lt;/code&gt;&lt;/pre&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;URL&lt;/th&gt;
&lt;th&gt;Total Element Count&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maps.google.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;731&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;my.yahoo.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1508&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;calendar.google.com (Authenticated)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;681&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reader.google.com (Authenticated)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4866&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;Getting back to the support ticket in question. After querying the document, I quickly found that the page contained over &lt;strong&gt;50000 nodes&lt;/strong&gt;. Wow. So, we’ve caught a big one. You’re going to be telling your grandkids about this some day. But, now what?&lt;/p&gt;

&lt;p&gt;I decided it would be beneficial to find out where and what all of those nodes were. After clicking around the live document in the Firebug’s HTML tab for awhile, looking at View Source, and Ajax requests in the Console, I successfully determined the culprit. This particular application was using &lt;a href="http://wicket.apache.org/"&gt;Wicket&lt;/a&gt;, a popular Java library for web applications, which includes its own &lt;em&gt;Ajax Logger&lt;/em&gt; component (similar to my favorite &lt;a href="http://log4javascript.org/"&gt;log4javascript&lt;/a&gt;; or something like the &lt;a href="http://developer.yahoo.com/yui/logger/"&gt;YUI Logger&lt;/a&gt;), used to keep track of an application’s Ajax calls and JavaScript page manipulations with an inline GUI embedded in the parent document. On one page load, this application’s Ajax logger component had &lt;strong&gt;created 40000 nodes of log content&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It’s important to realize that embedding unnecessary content of that magnitude on the page can be very detrimental to performance. &lt;strong&gt;JavaScript loggers should log to a new child window, rather than be embedded in the parent document.&lt;/strong&gt; This way they won’t bloat the document, but still provide you with much needed logging information.&lt;/p&gt;

&lt;p&gt;But, in the future, how might this type of problem be more easily diagnosed and prevented? Ideally, when confronted with large documents, we want to see where in the document the majority of those nodes are located. But there isn’t an easy way to see which portion of the document is using the largest number of nodes, especially if the culprit is deep into the document tree. We can go through the source code manually, but that isn’t very efficient.&lt;/p&gt;

&lt;p&gt;So in the spirit of exploratory development to help troubleshoot real-world problems, I decided to make a Firebug Lite plugin. This would give me an easy cross-browser tool to diagnose my problem in a familiar interface. Load up Firebug Lite, load the &lt;em&gt;DOM Sailbloat&lt;/em&gt; JavaScript file, and easily spot the HTML love handles.&lt;/p&gt;

&lt;p&gt;Here’s what it looks like in action:&lt;br/&gt;
&lt;img src="/web/wp-content/uploads/2010/07/Screen-shot-2010-07-19-at-9.59.49-PM.png" title="Screen shot of the DOM Sailbloat Firebug Lite plugin" alt="" /&gt;&lt;/p&gt;

&lt;h2&gt;Go Forth&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/domsailbloat/"&gt;See the demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/domsailbloat/domsailbloat.js"&gt;Download the source&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/zachleat/DOM-Sailbloat"&gt;Fork the Sailbloat on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;&lt;em&gt;Note: there is currently an undiagnosed issue with the Sailbloat and it fails to load intermittently. If you know why, I’d be happy to put your name in the source code credits.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/hxL1ltMzdA4" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>A Race Against Time Pickers</title>
		<link href="http://www.zachleat.com/web/a-race-against-time-pickers/" />
		<updated>2010-06-08T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/a-race-against-time-pickers</id>
		<content type="html">&lt;p&gt;The Date Picker component is one of the most popular user interface components on the web today.  Its operation is very simple: focus into a field (sometimes a click on a dedicated calendar button is required) intended to contain a specific date and an on-screen calendar will be shown next to the form field, allowing the user to click on a specific date to populate the form field.&lt;/p&gt;

&lt;p&gt;&lt;a href="/web/wp-content/uploads/2010/06/Screen-shot-2010-06-01-at-8.57.37-PM.png"&gt;&lt;img src="/web/wp-content/uploads/2010/06/Screen-shot-2010-06-01-at-8.57.37-PM.png" title="Date Picker Component" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Date Pickers are helpful components that are useful for a couple of reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They allow you to easily &lt;strong&gt;map an existing real-world mental model&lt;/strong&gt; (the Calendar) to form input (a text field). This provides &lt;strong&gt;additional context&lt;/strong&gt; beyond what the simple string value of a date represents: days of the week, Calendar month labels, leap year information.&lt;/li&gt;
&lt;li&gt;They allow for more usable and actionable data restrictions and error feedback.  Want the user to select a weekday?  Just show them on the calendar which days are available.&lt;/li&gt;
&lt;li&gt;Visual cue as to what the form field’s data format should be.  If a calendar icon is next to the form field, it becomes very obvious what kind of data the user should put into the field.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Now, the last two reasons are all well and good, but carry no intrinsic incentive for the user to actually click on and use the Date Picker component.  &lt;strong&gt;The first reason is what actually motivates a user&lt;/strong&gt; to bring up the Date Picker and select a date on it.&lt;/p&gt;

&lt;p&gt;Now, consider the following Time Picker component, popularized by &lt;a href="http://ejohn.org/blog/picking-time/"&gt;a John Resig blog post&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://haineault.com/media/jquery/ui-timepickr/page/"&gt;&lt;img src="/web/wp-content/uploads/2010/06/Screen-shot-2010-06-06-at-3.28.22-PM.png" title="Time Picker Example #2" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Comparing to the Date Picker component above, one could easily make the argument that it offers little to &lt;strong&gt;no incentive over simple keyboard input&lt;/strong&gt;.  It offers no additional context, extra data, or an existing physical mental model for the user to associate with.  The only advantage it might offer is an easy calculator for those unfamiliar with 24-hour (military) time.  I would argue that placing the AM/PM selection at the beginning of the selection creates a reversal of the closest established mental model a person typically uses to represent a time: the digital clock (hours, minutes, seconds, and AM/PM at the end).&lt;/p&gt;

&lt;h2&gt;Examples&lt;/h2&gt;

&lt;p&gt;Here’s a sampling of some other time picker implementations:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://pttimeselect.sourceforge.net/example/index.html"&gt;&lt;img src="/web/wp-content/uploads/2010/06/pttimeselect.png" title="Another Time Picker" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This implementation is very similar to the first example, just organized differently.  We can do better.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.pit-r.de/timepicker/demo/pickerDemo.htm"&gt;&lt;img src="/web/wp-content/uploads/2010/06/picker.png" title="Yet Another Time Picker, Two Analog Clocks, one for hours and one for minutes" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reading an analog clock isn’t the problem.  When we think of time, we start with numeric representations of the hours and minutes.  The first thing that pops into the average person’s head when they hear “6:00 PM” probably isn’t: the little hand on the 6 and the big hand on the 12.  The analog clock representation is &lt;strong&gt;a mental hurdle&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="/web/wp-content/uploads/2010/06/timedatepicker.png"&gt;&lt;img src="/web/wp-content/uploads/2010/06/timedatepicker.png" title="A simple time picker" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we’re getting closer.  The user selects a full representation of the time, not just the last piece of the puzzle.  I like the intuitive and simple organization of this time picker.  You know immediately what you’re selecting.  I think we can organize the times a little bit better though, give them a visual hierarchy.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.jnathanson.com/index.cfm?page=jquery/clockpick/ClockPick#demog"&gt;&lt;img src="/web/wp-content/uploads/2010/06/clockpick.png" title="Yet Another Time Picker" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This picker represents more of the spirit of what we’re looking for.  It shows a simple list of the hourly options and progressively discloses the minute selections.  I think switching to a single column layout would be more intuitive for keyboard navigation (combining the above two implementations into one super-component) and would do well with larger click targets.&lt;/p&gt;

&lt;p&gt;These implementation examples speak to a larger trend of front end engineers that concentrate too much on code optimization and cross browser compatibility, and &lt;strong&gt;not enough on usability and user driven design&lt;/strong&gt;.  It’s an easy trap to fall prey to, but one we must be wary of.  A Time Picker might offer benefit in terms of data restriction (e.g.: select an hour in the range of a normal workday), but it does very little for the efficiency and usability of data entry.  So, before you start putting Time Pickers on all of your forms, make sure the Time Picker you add represents something like this:&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2010/06/ISPKA4134_large.jpg" title="Digital Clock" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;and not this:&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2010/06/Screen-shot-2010-06-06-at-4.04.50-PM.png" title="Onscreen Keyboard" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Image Sources: &lt;a href="http://www.tesora.com.au/Digibell_Retro_Alarm_Clock_.htm"&gt;tesora.com.au&lt;/a&gt; and &lt;a href="http://www.codeproject.com/"&gt;codeproject.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/_HzOee0d_cM" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Point, Charset, Match: Character Encoding in JavaScript</title>
		<link href="http://www.zachleat.com/web/charset/" />
		<updated>2010-03-26T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/charset</id>
		<content type="html">&lt;p&gt;&lt;em&gt;If you’re not familiar with the principles of &lt;strong&gt;character encoding&lt;/strong&gt;, read the prerequisite &lt;a href="http://diveintohtml5.org/semantics.html#encoding"&gt;Dive Into HTML 5 section&lt;/a&gt; on the subject.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When you see issues with Character Encoding, it’s traditionally in the form of text on your page that looks like this: &lt;img src="/web/wp-content/uploads/2010/03/unencoded.png" title="unencoded" alt="" /&gt; in Firefox or &lt;img src="/web/wp-content/uploads/2010/03/unencoded-ie.png" title="unencoded-ie" alt="" /&gt; in IE.&lt;/p&gt;

&lt;p&gt;Usually, those characters mean that the character encoding used on the page is either ambiguous (not specified), or incorrect. We can use Firefox to determine that Character Encoding of a web page (Right Click and go to View Page Info; or use the “Character Encoding” entry in the View menu). Check to make sure that the encoding reported by Firefox is the same encoding used in your IDE. For example, Eclipse 3.5 has a “Set Encoding” option in the Edit menu.&lt;/p&gt;

&lt;p&gt;The reason most English alphabetic and numeric characters are consistent independent of character encoding is due to consistency in the lower characters in each encoding. The characters making up the &lt;a href="http://www.asciitable.com/"&gt;ASCII character set&lt;/a&gt; (0-127) are the same as the lowest 128 characters of &lt;a href="http://en.wikipedia.org/wiki/ISO/IEC_8859-1#ISO-8859-1"&gt;ISO-8859-1&lt;/a&gt;, &lt;a href="http://www.utf8-chartable.de/"&gt;UTF-8&lt;/a&gt;, and others.&lt;/p&gt;

&lt;p&gt;Managing your character encodings gets trickier as you add more architectural layers to your application. For example, character encodings may differ in your database, the properties files used to configure your application (java.util.Properties uses ISO-8859-1 by default), or maybe the XML or JSON file you’re loading from an external API.&lt;/p&gt;

&lt;p&gt;Ever heard of HTML character entities? That’s the primary reason they exist — as a sort of encoding independent reference to a particular character. So, for example, the Œ character does not exist in the ISO-8859-1 character set. To display this character in a document with ISO-8859-1 encoding, use the equivalent HTML character entity: &lt;code&gt;&amp;amp;OElig;&lt;/code&gt;. For an easier reference, check out this full table of &lt;a href="http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references"&gt;HTML character entities&lt;/a&gt;. If using ISO-8859-1 for your HTML document, any entity above Unicode index 255 will need to be escaped. If you’re using UTF-8 encoding, HTML character entities shouldn’t be required.&lt;/p&gt;

&lt;h2&gt;Setting the Character Encoding&lt;/h2&gt;

&lt;p&gt;To specify the character encoding for any file, you can set a &lt;code&gt;Content-Type&lt;/code&gt; header &lt;a href="http://www.w3.org/International/O-HTTP-charset"&gt;by configuring your web server or application&lt;/a&gt;. Apache lets you easily set different default character encodings for each individual file extension (&lt;code&gt;.js&lt;/code&gt; for example). Using the &lt;code&gt;Content-Type&lt;/code&gt; header is the most full proof and efficient &lt;a href="#performance"&gt;1&lt;/a&gt; method to serve content.&lt;/p&gt;

&lt;p&gt;But without access to the Apache configuration, how do we specify the character encoding?&lt;/p&gt;

&lt;h3&gt;For external JavaScript Files&lt;/h3&gt;

&lt;h4&gt;In the HTML File&lt;/h4&gt;

&lt;p&gt;Just add the &lt;code&gt;charset&lt;/code&gt; attribute. If not specified, the HTML document’s character encoding is used by default (specified in the &lt;code&gt;Content-Type&lt;/code&gt; header or the appropriate meta tag, for example: &lt;code&gt;&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"/&amp;gt;&lt;/code&gt;).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;script type="text/javascript" src="script.js" charset="utf-8"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;In the JavaScript File&lt;/h4&gt;

&lt;p&gt;To my knowledge, &lt;strong&gt;there is no way for a JavaScript file to report its own character encoding&lt;/strong&gt;. To me, this seems like an omission. Each individual document should be able to report its own character encoding without a header. CSS files can do it (&lt;code&gt;@charset&lt;/code&gt; at-rule). HTML files can do it (&lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag). Why not JavaScript files?&lt;/p&gt;

&lt;h4&gt;For Dynamically Created Script Tags&lt;/h4&gt;

&lt;pre&gt;&lt;code&gt;var s = document.createElement('script');
s.src = 'script.js';
s.type = 'text/javascript';
s.charset = 'utf-8';
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you’re using &lt;a href="http://api.jquery.com/jQuery.ajax/"&gt;jQuery’s Ajax&lt;/a&gt; functions to load external JavaScript files, perhaps you might be inclined to use the &lt;code&gt;script dataType&lt;/code&gt;. jQuery even provides a &lt;code&gt;scriptCharset&lt;/code&gt; option for wrapping the above method for changing the charset on a dynamic script tag. &lt;strong&gt;Be warned&lt;/strong&gt;, the jQuery Ajax function uses two different methods to load external script files (as of version 1.4.2). If a same-domain request, it uses an &lt;code&gt;XMLHttpRequest&lt;/code&gt;. If a cross-domain request, it uses a dynamic &lt;code&gt;script&lt;/code&gt; tag. So the &lt;strong&gt;&lt;code&gt;scriptCharset&lt;/code&gt; jQuery option only applies to cross-domain requests&lt;/strong&gt;. We’ll need some other method to mitigate our character encoding issues (or just use dynamic script tags).&lt;/p&gt;

&lt;h4&gt;For XMLHttpRequest Objects&lt;/h4&gt;

&lt;p&gt;Our saving grace would be the &lt;a href="https://developer.mozilla.org/en/XMLHttpRequest#overrideMimeType()"&gt;&lt;code&gt;overrideMimeType&lt;/code&gt;&lt;/a&gt; method, if it weren’t poetically unavailable in Internet Explorer. Using this method, we can override the mime type and character encoding.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var xhr = new XMLHttpRequest();
// Not available in Internet Explorer (up to version 8 at time of writing)
if (xhr.overrideMimeType) {
    xhr.overrideMimeType('application/x-javascript; charset=utf-8');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Portable non-ASCII JavaScript&lt;/h3&gt;

&lt;p&gt;The best way to make non-ASCII characters in JavaScript files portable is to escape the characters properly. If the character is destined for HTML, use an HTML character entity (if available, not all Unicode or ISO-8559-1 characters have entities). Or, escape the characters using the proper Latin or &lt;a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Unicode"&gt;Unicode escape sequence&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Raw characters
var string = "ñó";

// HTML character entities
var string = "&amp;amp;ntilde;&amp;amp;oacute;";

// Escaped to Latin
var string = "xf1xf3";

// Escaped to Unicode
var string = "u00f1u00f3";
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you use the Google Closure Compiler, you’ll get the Unicode escape sequences for free (see issues &lt;a href="http://code.google.com/p/closure-compiler/issues/detail?id=24"&gt;24&lt;/a&gt; and &lt;a href="http://code.google.com/p/closure-compiler/issues/detail?id=68"&gt;68&lt;/a&gt;). Make sure to read the tickets for more benefits of serving your JavaScript files using Unicode escape sequences to output only ASCII characters.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;The easiest way to preemptively solve a lot of character encoding issues is to use UTF-8 for everything, and configure your web server/application to serve the UTF-8 &lt;code&gt;Content-Type&lt;/code&gt; header. If you’re writing JavaScript code that you’re going to distribute to the masses, convert any non-ASCII characters using the proper escape sequences. Your JavaScript will be more portable, and will work out of the box on more server configurations.&lt;/p&gt;

&lt;h4&gt;Sources&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://www.kylescholz.com/blog/2010/01/performance_implications_of_charset.html"&gt;Performance Implications of Charset, an article by Kyle Scholz&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/EqcdQuGQ4FM" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Internet Explorer Array.sort Unreliable</title>
		<link href="http://www.zachleat.com/web/array-sort/" />
		<updated>2010-02-24T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/array-sort</id>
		<content type="html">&lt;p&gt;What would you expect to be the result of executing the following code?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Create a medium size array, at least 100 items
var obj = [];
for(var j=0, k=150; j&amp;lt;k; j++) {
    // the value here doesn't matter.
    obj.push('ABCD'+j);
}

// Sort the array alphabetically.
obj.sort(function(m,p){
    m=(''+m).toLowerCase();
    p=(''+p).toLowerCase();

    if(m &amp;gt; p) return 1;
    if(m &amp;lt; p) return -1;
    return 0;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;obj&lt;/code&gt; Array should now be sorted, in alphabetical order based on value.  &lt;strong&gt;BUT, in our best friend Internet Explorer, a &lt;code&gt;Number Expected&lt;/code&gt; error may be the result.&lt;/strong&gt;  Don&amp;#8217;t be fooled if your test array behaves correctly, it only happens intermittently for arrays of varying size!&lt;/p&gt;

&lt;p&gt;So, I &lt;a href="http://www.zachleat.com/test/numberexpected/"&gt;whipped up a quick test to check the damage&lt;/a&gt;.  Iterating over array sizes from 1 to 150, running the Array sort algorithm.  The following failures resulted:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Browser&lt;/th&gt;
&lt;th&gt;Failures *&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Internet Explorer 6&lt;/td&gt;
&lt;td&gt;4 sizes out of 150&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internet Explorer 7&lt;/td&gt;
&lt;td&gt;18 sizes out of 150&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internet Explorer 8 (and Compatibility Mode)&lt;/td&gt;
&lt;td&gt;2 sizes out of 150&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internet Explorer 9 (and Compatibility Mode)&lt;/td&gt;
&lt;td&gt;0 sizes out of 150 (Fixed!)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;* Failures may vary to the specifications of the test machine.&lt;/p&gt;

&lt;p&gt;Of course, the &lt;code&gt;Number Expected&lt;/code&gt; error is going to result whenever your code doesn&amp;#8217;t return a number inside of the function callback.  But the problem here is something deeper than simple application code failure.  The problem is in JScript itself.  Any modification to the sort arguments may result in the &lt;code&gt;Number Expected&lt;/code&gt; error.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// modifies the argument m and is unreliable.
m=(''+m).toLowerCase();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This problem will manifest itself more frequently if you use the Google Closure Compiler, which restructures JavaScript to reuse argument variables if possible, probably to save the 4 character penalty of a &amp;#8220;var &amp;#8221; declaration.&lt;/p&gt;

&lt;p&gt;Normally, reusing argument variables is a safe practice for primitives, since they are passed by value and not by reference, as is the case in this Array sort example &lt;sup&gt;&lt;a href="#by-ref"&gt;1&lt;/a&gt;&lt;/sup&gt;.  So, what exactly is going on here?  One commenter at the &lt;a href="http://code.google.com/p/closure-compiler/issues/detail?id=58"&gt;Google Closure Compiler bug&lt;/a&gt; seems to think that the actual array values are being passed by reference instead of by value.  I&amp;#8217;m not completely convinced that&amp;#8217;s the case.&lt;/p&gt;

&lt;h2&gt;The Fix&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Don&amp;#8217;t reuse the argument variables inside of an Array sort function.&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Changing the above example
obj.sort(function(m1,p1){
    var m=(''+m1).toLowerCase(),
        p=(''+p1).toLowerCase();

    if(m &amp;gt; p) return 1;
    if(m &amp;lt; p) return -1;
    return 0;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Check the &lt;a href="http://www.zachleat.com/test/numberexpected/"&gt;source code of the demo file&lt;/a&gt; to see the different methods of modifying the arguments that I attempted.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you want to learn more about passing by value or reference, &lt;a href="http://snook.ca/archives/javascript/javascript_pass"&gt;Jonathan Snook has a nice explanation&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;&lt;em&gt;Internet Explorer can&amp;#8217;t make you do anything, it can only make you wish you hadn&amp;#8217;t.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Updated: Added note about Internet Explorer 9 and its Compatibility View. Looks like it&amp;#8217;s fixed!&lt;/strong&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/kDkb2uGBlLk" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>If the Menu Fitts, We Must Acquit</title>
		<link href="http://www.zachleat.com/web/if-the-menu-fitts-we-must-acquit/" />
		<updated>2010-02-15T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/if-the-menu-fitts-we-must-acquit</id>
		<content type="html">&lt;p&gt;One of the first things you’ll learn when diving into a self-taught course on usability is the hugely popular Fitts’s Law. In a nutshell, Fitts’s Law tries to predict the time needed to move to a “target area” (usually a link, menu, button, or form element) as a function of the distance to the element and its size. &lt;strong&gt;The bigger/closer the element, the faster a user can move to it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, upon discovering myself a newly minted Mac OS convert from the hugely popular World of Windows, I quickly discovered that the application menus (File, Edit, etc) were one of the glaring differences I’d have to adjust to. Mac OS had all menus separated from the application window, all the way at the top of the screen. Coming from the Windows environment, this seemed unintuitive. But after reading more about Fitts’s Law, I discovered the reasoning: the &lt;a href="http://www.codinghorror.com/blog/2006/08/fitts-law-and-infinite-width.html"&gt;edges of the screen are treated as an infinite height or width&lt;/a&gt;! Which is just a way of modifying the Fitts’s Law to say: &lt;strong&gt;the easiest things to click on are at the edges of the screen.&lt;/strong&gt; That’s why the close icon or the Start Menu is so easy to access on Windows, and &lt;a href="http://www.asktog.com/basics/firstPrinciples.html#fittsLaw"&gt;why the Application Menu is at the top of the screen in Mac OS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We know about Fitts’s Law, but &lt;strong&gt;why aren’t we applying it to our web applications?&lt;/strong&gt; Why aren’t we using the power of infinite height/width to help out on our designs? It seems like this crucial usability law has been overlooked on the web, and without good reason. Let’s look at a few applications that get it wrong (of course, in my humble opinion).&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2010/02/Screen-shot-2010-02-15-at-11.08.15-PM.png" title="Screen shot 2010-02-15 at 11.08.15 PM" alt="Wordpress Admin Menu" /&gt;&lt;img src="/web/wp-content/uploads/2010/02/Screen-shot-2010-02-15-at-11.12.57-PM.png" title="Screen shot 2010-02-15 at 11.12.57 PM" alt="Google Mail Menu" /&gt;&lt;img src="/web/wp-content/uploads/2010/02/Screen-shot-2010-02-15-at-11.09.16-PM.png" title="Screen shot 2010-02-15 at 11.09.16 PM" alt="Google Reader Menu" /&gt;&lt;/p&gt;

&lt;p&gt;All of these screenshots were taken from 100% width designs, with no real reason not to incorporate the ideas behind Fitts’s Law into the menuing system. At first glance when I brought up Google Reader, I was excited. The hover behavior appeared when the mouse cursor was positioned at the very far left of the screen, but was disappointed to discover that the although the hover background color had changed, the entire hover target was not clickable.&lt;/p&gt;

&lt;p&gt;Naturally, I decided to make a test of my own, to test which web browsers allowed &lt;em&gt;Fitts’s Law Menus&lt;/em&gt;. The test case encompassed both left and bottom aligned menus, for completeness. A top menu was excluded, given that the top of the screen is reserved for browser chrome or application menuing. A right menu was also excluded as the right portion of the screen is reserved for the page scrollbar (which is the easiest scrollbar to manipulate with your mouse, per the same rules).&lt;/p&gt;

&lt;p&gt;Also, on the Mac OS 10.6 and Windows XP operating systems, a &lt;em&gt;Fitts’s Law Menu&lt;/em&gt; at the bottom of the screen is not possible, given that the Dock and Taskbar in these operating systems occupy at least a 4 pixel trough of the bottom-most space on the monitor, even as a hover target in “auto-hide” mode. &lt;strong&gt;Everyone is fighting over these crucial and very useful edge pixels.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To test whether or not this behavior is working correctly, &lt;strong&gt;maximize your browser window&lt;/strong&gt; and &lt;strong&gt;move the cursor as far left on the screen as possible&lt;/strong&gt;, but still over the menu. If the links are still clickable, congratulations, your browser works!&lt;/p&gt;

&lt;h2&gt;&lt;a href="/test/fittmenu/"&gt;View the Demo / Test Page for the Fitts’s Law Menu&lt;/a&gt;&lt;/h2&gt;

&lt;h2&gt;Compatibility Table&lt;/h2&gt;

&lt;table class="compatibility"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Browser&lt;/th&gt;
&lt;th&gt;Operating System&lt;/th&gt;
&lt;th&gt;Left Menu&lt;/th&gt;
&lt;th&gt;Bottom Menu&lt;/th&gt;
&lt;th&gt;Status Bar&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Internet Explorer 8&lt;/td&gt;
&lt;td&gt;Windows XP&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;IE8 has a small 3 pixel border on the left and right of each window.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internet Explorer 7&lt;/td&gt;
&lt;td&gt;Windows XP&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;IE7 has a small 3 pixel border on the left and right of each window.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internet Explorer 6&lt;/td&gt;
&lt;td&gt;Windows XP&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;IE6 has a small 3 pixel border on the left and right of each window.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Chrome&lt;/td&gt;
&lt;td&gt;Windows XP and Mac OS 10.6&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mozilla Firefox 3.5 and 3.6&lt;/td&gt;
&lt;td&gt;Windows XP and Mac OS 10.6&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safari 4.0.4&lt;/td&gt;
&lt;td&gt;Windows XP and Mac OS 10.6&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;&lt;em&gt;The full screen mode of each individual browser was considered outside the scope of this study.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;We should stand on the shoulders of giants and reuse the usability studies already completed on software that has gone before us. The left side of the browser window is the best place to utilize Fitts’s Law, and we should move our left-aligned menus on fluid width designs to occupy the space flush with the window’s edge to increase the speed at which those menus will be accessible by users. Having an infinite width menu is a big click target to hit.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/sxycnPLhHgw" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>CSS 3 Text: A Tale of writing-mode Woe</title>
		<link href="http://www.zachleat.com/web/css3-text-writing-mode/" />
		<updated>2010-02-12T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/css3-text-writing-mode</id>
		<content type="html">&lt;p&gt;After reading an interesting article on using the &lt;a href="http://www.thecssninja.com/css/real-text-rotation-with-css"&gt;writing-mode CSS property&lt;/a&gt; to display vertical text (I’m always interested in how to abuse what browsers currently support into something new and exciting), I decided to look into this &lt;code&gt;writing-mode&lt;/code&gt; property and see what opportunities it might present.&lt;/p&gt;

&lt;p&gt;Generally when exploring a development opportunity, I tend to prioritize my adventures towards things that are supported in Internet Explorer first. This often has the biggest cross-browser payoff, since the other browser vendors tend to have a quicker draw than the Microsoft Team. However, surprisingly enough, this &lt;code&gt;writing-mode&lt;/code&gt; study proved the opposite to be true. It seems very interesting that Microsoft has decided to implement a portion of the CSS 3 specification, given its general stance of moving slower than an iceberg to avoid “breaking the web.” But I, for one, welcome our new choose-your-own-adventure standards loving overlords.&lt;/p&gt;

&lt;p&gt;As far as my tests go, the only browser to support the &lt;code&gt;writing-mode&lt;/code&gt; property at all is Internet Explorer, which was very surprising. At it’s heart, though, &lt;code&gt;writing-mode&lt;/code&gt; is just shorthand for two other properties: &lt;code&gt;direction&lt;/code&gt; and &lt;code&gt;block-progression&lt;/code&gt;. Luckily, &lt;strong&gt;Firefox, Safari, Chrome and IE back through at least version 6 support the &lt;code&gt;direction&lt;/code&gt; property&lt;/strong&gt; and have proprietary options for rotation, which &lt;strong&gt;allows for emulation of a few of the unsupported &lt;code&gt;writing-mode&lt;/code&gt;‘s&lt;/strong&gt;, but not all of them. The missing piece of &lt;code&gt;writing-mode&lt;/code&gt; emulation belongs to the &lt;code&gt;block-progression&lt;/code&gt; property, which isn’t supported by anyone, and would allow elements to flow reverse vertically (start at the bottom of a block and flow upwards).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It’s important to note that while &lt;a href="http://blogs.msdn.com/ie/archive/2009/05/29/the-css-corner-writing-mode.aspx"&gt;IE8 has really set the bar for implementation here&lt;/a&gt; and has chosen to support &lt;code&gt;writing-mode: lr-bt&lt;/code&gt; and &lt;code&gt;writing-mode: rl-bt&lt;/code&gt;, they aren’t used to display any known language text. They’re just included for completeness, and aren’t a part of the &lt;a href="http://www.w3.org/TR/2003/CR-css3-text-20030514/"&gt;W3C CSS 3 Text Module specification.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://zachleat.com/test/writing-mode/"&gt;View the Demo / Test Page&lt;/a&gt;&lt;/h2&gt;

&lt;h2&gt;Compatibility Table&lt;/h2&gt;

&lt;table class="compatibility"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th rowspan="2"&gt;writing-mode&lt;/th&gt;
&lt;th colspan="3"&gt;Internet Explorer&lt;br&gt;(Trident)&lt;/th&gt;
&lt;th&gt;Mozilla Firefox&lt;br&gt;(Gecko)&lt;/th&gt;
&lt;th&gt;Apple Safari&lt;br&gt;(Webkit)&lt;/th&gt;
&lt;th&gt;Google Chrome&lt;br&gt;(Webkit)&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;6&lt;/th&gt;
&lt;th&gt;7&lt;/th&gt;
&lt;th&gt;8&lt;/th&gt;
&lt;th&gt;3.6&lt;/th&gt;
&lt;th&gt;4&lt;/th&gt;
&lt;th&gt;4&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lr-tb&lt;/code&gt;&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rl-tb&lt;/code&gt;&lt;/td&gt;
&lt;td class="emulate"&gt;emulatable&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="emulate"&gt;emulatable&lt;/td&gt;
&lt;td class="emulate"&gt;emulatable&lt;/td&gt;
&lt;td class="emulate"&gt;emulatable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="background-color: #eee;"&gt;
&lt;td&gt;&lt;code&gt;lr-bt&lt;/code&gt;&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="background-color: #eee;"&gt;
&lt;td&gt;&lt;code&gt;rl-bt&lt;/code&gt;&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tb-lr&lt;/code&gt;&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tb-rl&lt;/code&gt;&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="emulate"&gt;emulatable&lt;/td&gt;
&lt;td class="emulate"&gt;emulatable&lt;/td&gt;
&lt;td class="emulate"&gt;emulatable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bt-lr&lt;/code&gt;&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;td class="no"&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bt-rl&lt;/code&gt;&lt;/td&gt;
&lt;td class="emulate"&gt;emulatable&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="yes"&gt;yes&lt;/td&gt;
&lt;td class="emulate"&gt;emulatable&lt;/td&gt;
&lt;td class="emulate"&gt;emulatable&lt;/td&gt;
&lt;td class="emulate"&gt;emulatable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;h2&gt;CSS Code for Emulation&lt;/h2&gt;

&lt;h3&gt;Writing Mode: &lt;code&gt;lr-tb&lt;/code&gt;&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;// Do nothing, this is the default
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Writing Mode: &lt;code&gt;rl-tb&lt;/code&gt;&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;direction: rtl;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Writing Mode: &lt;code&gt;lr-bt&lt;/code&gt;&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;// Not possible using W3C spec
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Writing Mode: &lt;code&gt;rl-bt&lt;/code&gt;&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;// Not possible using W3C spec
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Writing Mode: &lt;code&gt;tb-lr&lt;/code&gt;&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;// Not possible using W3C spec
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Writing Mode: &lt;code&gt;tb-rl&lt;/code&gt;&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Writing Mode: &lt;code&gt;bt-lr&lt;/code&gt;&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;// Not possible using W3C spec
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Writing Mode: &lt;code&gt;bt-rl&lt;/code&gt;&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;direction: rtl;
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Given that &lt;strong&gt;4 of the 6 known writing modes are available&lt;/strong&gt; or available through CSS emulation means we’re in pretty good shape on the internationalization front. Consulting the Microsoft provided table for common use cases, we’re only in trouble when trying to use the “Mongolian script writing system” and an “Arabic script block quote embedded in Mongolian script document.”&lt;/p&gt;

&lt;p&gt;In some far fetched fantasy-world legacy application where a page may use tables for layout, I could see an application team possibly using the &lt;code&gt;direction&lt;/code&gt; property to redistribute the tables for a print stylesheet. But that certainly wouldn’t be a common use case, since using CSS for layouts is going to give you much more flexibility in that regard. If you can think of any other off the wall uses for &lt;code&gt;writing-mode&lt;/code&gt; or &lt;code&gt;direction&lt;/code&gt;, I’d love to hear them!&lt;/p&gt;

&lt;h2&gt;Related&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Very &lt;a href="http://fantasai.inkedblade.net/style/discuss/vertical-text/#logical"&gt;complete article on CSS 3 writing-mode&lt;/a&gt;, including some &lt;code&gt;direction&lt;/code&gt; properties that don’t exist in the specification (like &lt;code&gt;ttb&lt;/code&gt;, &lt;code&gt;ltr-ttb&lt;/code&gt;, and &lt;code&gt;ltr-btt&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=writing-mode"&gt;Bugzilla Bug for writing-mode in Firefox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;As of the time of this writing, I was unable to find any results for writing-mode on the Webkit bug tracker.&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/HsPx3AnrfQU" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Trash that “Back to Top” Link</title>
		<link href="http://www.zachleat.com/web/trash-that-back-to-top-link/" />
		<updated>2010-02-05T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/trash-that-back-to-top-link</id>
		<content type="html">&lt;blockquote&gt;&lt;p&gt;It would seem that perfection is attained not when no more can be added, but when no more can be removed.&lt;/p&gt;

&lt;p&gt;—Antoine de Saint Exupéry&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;While most would argue that the principles espoused in the above quote might also be applied to the quote itself, it would serve us better to consider how we can &lt;strong&gt;attempt perfection in our User Interface designs&lt;/strong&gt; instead.&lt;/p&gt;

&lt;p&gt;The most complete litany of reasons why you should spend your page weight on more useful bytes has been &lt;a href="http://www.cs.tut.fi/~jkorpela/www/totop.html"&gt;compiled by Jukka Korpela&lt;/a&gt;, although he seems to both confirm that they are harmful and still use them on his site.&lt;/p&gt;

&lt;p&gt;The rules of engagement I find useful when dealing with the ill-fated “Back to Top” or its ugly stepsister “Top of Page” link are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Delete the link.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Really, you don’t need the link. It’s a &lt;strong&gt;sacred cow remnant&lt;/strong&gt; of a time when people believed that all content needed to be positioned &lt;a href="http://iampaddy.com/lifebelow600/"&gt;above the page fold&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Guess what? &lt;strong&gt;People know how to scroll!&lt;/strong&gt; They know how to scroll down, they know how to scroll up. Considering this prerequisite has been met, it becomes very apparent that the “Back to Top” link shares an &lt;strong&gt;unnecessary overlap in functionality with the scrollbar&lt;/strong&gt; and is thus, unnecessary itself.&lt;/p&gt;

&lt;p&gt;If you have an incredibly long page with a full set of “Table of Contents” links, it would be better to position your &lt;a href="http://jqueryfordesigners.com/fixed-floating-elements/"&gt;table of contents fixed to the viewport&lt;/a&gt;, so as to make it always available to the user. If the Table of Contents is always available, the user will never have to click a link as a shortcut to find it.&lt;/p&gt;

&lt;p&gt;While not a usability epidemic, the “Back to Top” link is still widely used. &lt;a href="http://www.instantshift.com/2009/07/14/90-creative-back-to-top-links-and-best-practices/"&gt;Instant Shift&lt;/a&gt; and &lt;a href="http://www.smashingmagazine.com/2008/11/27/short-story-about-top-links/"&gt;Smashing Magazine&lt;/a&gt; both have articles with hundreds of examples of sites with these links.&lt;/p&gt;

&lt;p&gt;Don’t agree? If you’re stubborn as hell and hate simplicity, you’re going to keep the link on your page no matter what reasons are presented. In that case, at the very least follow these two guidelines:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Use &lt;strong&gt;progressive enhancement&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;a href="#" id="back-to-top"&amp;gt;Back to Top&amp;lt;/a&amp;gt;

// Requires jQuery
$('#back-to-top').click(function() {
    window.scrollTo(0,0);

    // don't change the hash if not needed
    return false;
});
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hide the link&lt;/strong&gt; if the page doesn’t have a scrollbar. If no scrollbar exists, the user will &lt;strong&gt;always be “at the top.”&lt;/strong&gt;     // Continuing with Previous Example&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Continuing with Previous Example
$(function() {
    $('#back-to-top').hide();
});

// If the page scrolls, we know there is a scrollbar.
$(window).scroll(function() {
    $('#back-to-top').show();
});

// For completeness, you may also want to
//   add logic to the "resize" event.
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Really though, &lt;strong&gt;just delete the link.&lt;/strong&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/7Wx5PE8t8iY" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>The “24″ Clock on ALARMd</title>
		<link href="http://www.zachleat.com/web/the-24-clock-on-alarmd/" />
		<updated>2010-01-24T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/the-24-clock-on-alarmd</id>
		<content type="html">&lt;p&gt;If you’re only using @font-face for titles and text, you’re missing out on a whole &lt;a href="http://www.zachleat.com/web/2010/01/03/css-sprites-using-font-face/"&gt;wealth of use cases&lt;/a&gt; that have yet to be explored. For instance, I created a very simple &lt;a href="http://fontstruct.fontshop.com/fontstructions/show/282059"&gt;7 Segment Display Numeric font&lt;/a&gt; to be used for a skin on &lt;a href="http://www.alarmd.com/"&gt;alarmd.com&lt;/a&gt; and changed the color using nothing but CSS to create the “24″ Clock (true fans will note that the actual font is italic and &lt;a href="http://www.panopticist.com/2006/05/there_is_something_weird_going_on_with_the_clock_on_24.php"&gt;has a serif on the 1&lt;/a&gt;). Nonetheless, this is just another useful application of @font-face.&lt;/p&gt;

&lt;p&gt;Take a look at the &lt;a href="http://www.fontsquirrel.com/fonts/list/style/Dingbat"&gt;Dingbats section on fontsquirrel&lt;/a&gt; to get your brain going in the same direction.&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2010/01/Screen-shot-2010-01-24-at-1.22.39-AM.png" title="Screenshot of the 24 Clock on alarmd.com" alt="" /&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/TdMZGQKG-lo" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>DIY Webdings – CSS Sprites using @font-face</title>
		<link href="http://www.zachleat.com/web/css-sprites-using-font-face/" />
		<updated>2010-01-03T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/css-sprites-using-font-face</id>
		<content type="html">&lt;p&gt;Almost everyone knows the Webdings font or its sibling Wingdings. Even if you don’t, chances are pretty good that it’s installed on your system.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Webdings is a symbol font designed in 1997 as a response to the need of Web designers for a fast and easy method of incorporating graphics in their pages.&lt;br/&gt;
…&lt;/p&gt;

&lt;p&gt;Webdings is ideal for enriching the appearance of a Web page. Because it’s a font, it can be installed on the user’s system, (or embedded in the document itself) is fully scaleable [sic] and quick to render. It’s a perfect way of including graphics on your site without making users wait for lots of graphic files to download.&lt;/p&gt;

&lt;p&gt;– Source &lt;a href="http://www.microsoft.com/typography/fonts/family.aspx?FID=5"&gt;Microsoft Typography&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Microsoft was onto something here, and there is a nice parallel that can be drawn between the font and a CSS sprite: namely that multiple images are stored under the guise of a single HTTP request. So, why not create our own font and use it as a CSS sprite? Each character in the font (glyph) will be a single image in the sprite.&lt;/p&gt;

&lt;h2&gt;Why is this awesome?&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;We can &lt;strong&gt;change the color&lt;/strong&gt; of our font using nothing but CSS &lt;code&gt;color&lt;/code&gt;. This is a big one. We don’t have to have separate images for hover states! And if we want to change the color scheme, there are no new images to generate and we don’t have to make any changes to the font to do so.&lt;/li&gt;
&lt;li&gt;Don’t have to monkey around with difficult to maintain CSS positioning code.&lt;/li&gt;
&lt;li&gt;Fonts scale, graphics don’t. Zooming in on a graphic will result in a pixelated image, but fonts will be smooth like a 6 blade razor shave. Try zooming on the demo file below.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Why is this not awesome?&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Font glyphs can only contain one color.&lt;/li&gt;
&lt;li&gt;May experience the Flash of unstyled text (FOUT) while the font is loading.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extra markup required for IE6 and IE7. While @font-face is supported in all non-extinct versions of IE, each @font-face sprite requires a corresponding text character on the screen. For instance, &lt;code&gt;A&lt;/code&gt;, the A is required to display the @font-face Sprite stored under the A glyph.&lt;/p&gt;

&lt;p&gt;Luckily, in most browsers we can inject a character using CSS :after/:before and the &lt;code&gt;content&lt;/code&gt; property. Unfortunately, this is &lt;a href="http://www.quirksmode.org/css/beforeafter_content.html"&gt;not supported in IE6 or IE7&lt;/a&gt;. I haven’t investigated whether or not this might be solved using other means (CSS expressions) yet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Safari asks for permission to use the font with a scary popup box, which I assume is a security precaution gleaned from the Windows Vista playbook.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Demo&lt;/h2&gt;

&lt;p&gt;The following &lt;a href="http://jquery-ui.googlecode.com/svn/trunk/tests/static/icons.html"&gt;jQuery UI Icons&lt;/a&gt; are currently used in jQuery UI and are stored in &lt;a href="http://jqueryui.com/themeroller/images/?new=888888&amp;amp;w=256&amp;amp;h=240&amp;amp;f=png&amp;amp;fltr[]=rcd|256&amp;amp;fltr[]=mask|icons/icons.png"&gt;one big CSS sprite&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It was pretty trivial to create &lt;a href="http://fontstruct.fontshop.com/fontstructions/show/jquery_ui_icons_1"&gt;a font&lt;/a&gt; with a subset of the jQuery UI icons (only the first 20, just a proof of concept here) using the wonderful &lt;a href="http://fontstruct.fontshop.com/"&gt;FontStruct&lt;/a&gt; utility. Then, I took the TTF generated by FontStruct and plugged it into the completely lovely &lt;a href="http://www.fontsquirrel.com/fontface/generator"&gt;FontSquirrel @font-face Kit Generator&lt;/a&gt;. That gave me everything I needed for a fully cross-browser test.&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://www.zachleat.com/test/fonts/font.html"&gt;View the Demo&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Let me know what you think!&lt;/p&gt;

&lt;p&gt;Successfully tested on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Google Chrome 4 (Mac)&lt;/li&gt;
&lt;li&gt; Safari 4 (Mac)&lt;/li&gt;
&lt;li&gt; Firefox 3.5 (Mac and Windows)&lt;/li&gt;
&lt;li&gt; Internet Explorer 8&lt;/li&gt;
&lt;li&gt; With documented limitations above: Internet Explorer 6 and 7 (Compatibility Mode in IE8)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Does not work on (no @font-face support):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Google Chrome 3 and prior&lt;/li&gt;
&lt;li&gt; Firefox 3 and prior&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Read more about &lt;a href="http://paulirish.com/2009/bulletproof-font-face-implementation-syntax/"&gt;@font-face support from Paul Irish&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/Gtxj5KHGO1Q" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Don’t Give Up on Internet Explorer Yet</title>
		<link href="http://www.zachleat.com/web/dont-give-up-on-ie/" />
		<updated>2009-12-09T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/dont-give-up-on-ie</id>
		<content type="html">&lt;p&gt;These days, the browser landscape is more fragmented than ever. Were times easier back when IE6 and Firefox ruled the internet? Easier perhaps in terms of the number of browsers you had to launch for testing, but &lt;strong&gt;not better&lt;/strong&gt; for any user’s experience. We are in a new world, where more web browsers are causing developers to become &lt;strong&gt;increasingly pragmatic&lt;/strong&gt; with their designs and code. Sure, standards have created a safe haven under the newest versions of the Big 3 (Firefox, IE, Safari), but the lay majority are still using whatever default has been installed onto their computer, and they probably can’t tell you &lt;a href="http://googlesystem.blogspot.com/2009/06/browser-is-search-engine.html"&gt;the difference between their web browser and a search engine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We must be resilient to resist the transformation from development pragmatism to user abandonment, especially considering a developer’s trend of being insulated with the latest equipment. We use the newest hardware and download the most sophisticated browser software because we want the best experiences. We stack the cards in our favor. The difficulty lies with the populace that &lt;strong&gt;want a good experience&lt;/strong&gt; (they can tell a fast site from a slow site), but they &lt;strong&gt;don’t want to buy new equipment or install a better browser.&lt;/strong&gt; So the question has become: Where do you place your chips on the spectrum balancing modern hardware/software and the user experience?&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2009/12/zombies.png" title="zombie" alt="zombie" /&gt;&lt;/p&gt;

&lt;p&gt;As web developers, it has become increasingly easy to become disenfranchised with the lay majority’s computing environment. I’ve witnessed this personally after purchasing my first Apple computer, a device curiously immune to the plague of IE 6/7 (8 as well, but I would hesitate to label it as a plague, more like a normal run of the mill flesh eating virus). It’s an interesting phenomenon, being cutoff from the Windows environment (save virtualization) during development. It’s delightfully tempting to declare damnation upon the plague ridden Internet Explorer Zombies, and develop your web presence to standards alone, allowing less focus on the harshest development environment imaginable and more on actual problem solving.&lt;/p&gt;

&lt;p&gt;When developers engage in quasi-web development, perhaps in the form of an iPhone specific web application or an Adobe AIR desktop application, it fosters similar feelings. The work shares many languages and technologies with real (wide-open) web development, but is targeted towards a single web browser. This benefits of this sort of tunnel vision device targeting must be carefully weighed against the penalties you’re paying in narrowed default-install client compatibility. At that point, it’s just &lt;strong&gt;friends with benefits&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2009/12/google-wave-ie8.png" title="Denial of Access with Internet Explorer Screenshot" alt="Denial of Access with Internet Explorer Screenshot" /&gt;&lt;br/&gt;
Google Wave, in fact, requires the use of Safari, Firefox, Chrome, or the Google Chrome Frame plugin (which doesn’t count as actual browser support). As of the time this article was written, as many as &lt;strong&gt;64% of all users&lt;/strong&gt; (&lt;a href="http://en.wikipedia.org/wiki/Usage_share_of_web_browsers"&gt;source&lt;/a&gt;) are met with the above screen when trying to access Google Wave. Let’s be clear: &lt;strong&gt;Ease of development is not an excuse to abandon users.&lt;/strong&gt; Whatever happened to &lt;a href="http://www.zachleat.com/web/2009/08/29/device-independence/"&gt;Device Independence&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Not surprisingly, Google Wave’s stand against Internet Explorer &lt;strong&gt;has not started a trend&lt;/strong&gt;. Instead of all out war, the community at large has decided that subtlety is what’s needed to win this fight. Let’s hold back the &lt;a href="http://en.wikipedia.org/wiki/Sexual_Healing"&gt;sexual healing&lt;/a&gt; of rounded corners, even though perhaps users will call our design harsh or cold. Let’s give them plain buttons instead of nice three dimensional buttons with text and box shadows, even though they may be less actionable.&lt;/p&gt;

&lt;p&gt;Let’s make it easier on ourselves at the expense of the user experience of The Zombie Majority. We make this sacrifice because we assume that Zombies won’t be able to tell the difference between eating a big juicy Einstein brain and a smaller but nonetheless still tasty brush clearing George W. And you know what, &lt;strong&gt;I think we’re right.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Updated&lt;/strong&gt; to include a few more thoughts on Adobe AIR and the iPhone.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/bmvA4Lj81h4" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Device Independence on the Open Web</title>
		<link href="http://www.zachleat.com/web/device-independence/" />
		<updated>2009-08-29T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/device-independence</id>
		<content type="html">&lt;p&gt;Open Web advocacy can get pretty lonely working in Big Enterprise. Armed with slow moving standards bodies, and held back by antiquated browser support, architectural battles over tools and frameworks can get pretty hairy if you don’t approach them with the right frame of mind.&lt;/p&gt;

&lt;p&gt;Big Enterprise is traditionally known for creating development environments that foster a “get it done” mentality, often rewarding results over correctness (mileage, of course, may vary).&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;My company uses IE6, and the application works in IE6, so it’s done!&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;This little quagmire is amplified by the fact that when using Open Web technology, there are many ways to get things done, and most of them are incorrect. But those mistakes don’t manifest themselves until the project is in the hands of the end user, whom we often punish for our oversight.&lt;/p&gt;

&lt;p&gt;But there is hope. Using the power of web standards and Open Web best practices, we can achieve something panoramically, not microscopically, beautiful.&lt;/p&gt;

&lt;p&gt;The secret sauce of building for the Web isn’t its distribution model, in which updates are managed on the web server without the need to update software on the client (although the Anti-IE6 vigilantes would tell you differently). It most certainly isn’t development efficiency, as most people new to the game will so readily inform you of. Cross browser quirks due to non-standard browser implementations of CSS and JavaScript, or vague standards specifications have seen to that.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;When I was writing Visual Basic, I got my job done so much quicker and easier!&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;The power of the Open Web is Device Independence.&lt;/h2&gt;

&lt;p&gt;Visitors to our sites &lt;strong&gt;shouldn’t be met with warnings&lt;/strong&gt; about what device they’ve chosen to use.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;This site viewable only in IE7 , Firefox, Chrome, or Safari, and at minimum 1024×768 resolution.&lt;/p&gt;

&lt;p&gt;This site requires Flash or Silverlight&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;I realize that this is a controversial stance, especially given that most sites are dropping support for IE6, and more are relying on Flash and Silverlight plugins. &lt;strong&gt;Architect applications to your client device usage statistics, and don’t let your tools shape the statistics for you.&lt;/strong&gt; Using techniques like progressive enhancement, we can ensure that our sites degrade gracefully to the capabilities of the client device. At it’s truest form, this is basic accessibility. But, Device Independence might be a more accurate term, since accessibility is unfortunately an overloaded term scoped solely with devices tied to disabilities (screen readers, for example). While screen readers are a very important piece, there is a bigger picture.&lt;/p&gt;

&lt;p&gt;When the iPhone came out, there was an uproar because it didn’t support Flash, for battery life and other reasons. But the uproar was from developers who had designed applications specifically for Flash! Would you say that those Flash applications were designed with device independence in mind? YouTube got around this by encoding their videos in MP4 format, which arguably has a higher device independence rating than the Flash format.&lt;/p&gt;

&lt;p&gt;Keep in mind that we’re &lt;strong&gt;not attempting to handle every permutation of end user browser settings&lt;/strong&gt;, since most don’t change the defaults. Instead we are trying to scoop up the largest base of supported devices with the least amount of effort! Who cares if an end user disabled JavaScript in their preferences? I’m more worried about the mobile browser that doesn’t even support JavaScript at all. But when you use Open Web properly, you get support for both!&lt;/p&gt;

&lt;h2&gt;Output Device Independence&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Full Web Browsers: Does your site work in Opera? Don’t worry about pixel perfection, that’s something completely different — does it work?&lt;/li&gt;
&lt;li&gt;Web Browsers on Mobiles&lt;/li&gt;
&lt;li&gt;Search Engine Spiders and other Screen Scrapers&lt;/li&gt;
&lt;li&gt;Screen Readers&lt;/li&gt;
&lt;li&gt;Printers: Ever had to make an entirely separate page for print-friendly version of your application? Flash/Silverlight &lt;strong&gt;do not&lt;/strong&gt; print well&lt;/li&gt;
&lt;li&gt;Televisions: Xbox 360, Wii, and Other Media Center Devices&lt;/li&gt;
&lt;li&gt;Projectors&lt;/li&gt;
&lt;li&gt;&lt;em&gt;and more…&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Take a look at the &lt;a href="http://www.w3.org/TR/CSS21/media.html#media-types"&gt;CSS specification for media types&lt;/a&gt;. The standards are there! Support for CSS media types isn’t fool proof by any means, but the end goal is clearly visible.&lt;/p&gt;

&lt;h2&gt;Input Device Independence&lt;/h2&gt;

&lt;p&gt;But I’m not just talking about output device independence either. User interfaces should be adaptable to different input devices as well.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mouse&lt;/li&gt;
&lt;li&gt;Keyboard (often overlooked in web applications)&lt;/li&gt;
&lt;li&gt;Touch Screens (Single and &lt;a href="http://hacks.mozilla.org/2009/08/multi-touch-firefox/"&gt;Multi-touch&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Voice, Motion Capture, and Facial Recognition (the standards and technology aren’t quite there yet, but &lt;a href="http://hacks.mozilla.org/2009/06/connecting-html5-video/"&gt;progress is being made&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;and more…&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The world is developing the Open Web, and it isn’t limited by a single company’s goals and timelines. At times, Open Web may seem like it’s a very slow moving &lt;strong&gt;glacier&lt;/strong&gt; headed our way, but what else can you do but laugh when companies try to &lt;strong&gt;power their Titanic right through it&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Article originally inspired by &lt;a href="http://developer.yahoo.com/yui/articles/gbs/#history"&gt;Yahoo’s Graded Browser Support&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/7DuAU_bNDAc" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Quick Performance Tip: jQuery and addClass</title>
		<link href="http://www.zachleat.com/web/quick-performance-tip-jquery-and-addclass/" />
		<updated>2009-06-30T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/quick-performance-tip-jquery-and-addclass</id>
		<content type="html">&lt;p&gt;Abstractions are helpful and dangerous. But the more we know about a library’s internals, the less danger we’ll be in later. Here’s an issue I ran into where I had assumed that jQuery would be optimized for this case, but it wasn’t. I’ll go over my bad assumption and how to workaround it.&lt;/p&gt;

&lt;p&gt;As of jQuery 1.3.2, adding multiple HTML classes to an element using jQuery’s addClass method will add them one at a time, modifying the className property of an element for each class.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$('#myElement').addClass('myFirstClass mySecondClass');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s the original code inside of jQuery 1.3.2. Note how the classNames string is split, and elem.className is changed for each split entry.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;add: function( elem, classNames ) {
jQuery.each((classNames || "").split(/\s+/), function(i, className){
    if ( elem.nodeType == 1 &amp;amp;&amp;amp; !jQuery.className.has( elem.className, className ) )
        elem.className += (elem.className ? " " : "") + className;
    });
},
// ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This may cause longer than needed delays, as reflow may occur after every class is added individually. If absolutely necessary, you can always fall back to modifying the className yourself, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$('#myElement').each(function() {
   this.className += ' myFirstClass mySecondClass';
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Most likely, this isn’t a tip that will be needed, but it is useful to be aware of.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/XlR53g7P94o" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>Performance Caveat with jQuery Selectors and Live Events</title>
		<link href="http://www.zachleat.com/web/performance-caveat-with-jquery-selectors-and-live-events/" />
		<updated>2009-05-08T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/performance-caveat-with-jquery-selectors-and-live-events</id>
		<content type="html">&lt;p&gt;&lt;em&gt;Prerequisite: Knowledge/Experience with &lt;a href="http://docs.jquery.com/Events/live"&gt;jQuery Live Events&lt;/a&gt; (new in jQuery 1.3), and the concept of &lt;a href="http://icant.co.uk/sandbox/eventdelegation/"&gt;Event Delegation&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When developing on the front end, it’s easy to prioritize correctness over performance. Performance is the step child that gets lost while you’re pulling your hair out worrying about cross browser compatibility. It’s very important to regularly benchmark your JavaScript code, using a &lt;a href="http://getfirebug.com/js.html"&gt;profiler&lt;/a&gt; or some form of benchmarking code paired with a cross browser logging utility (see &lt;a href="http://getfirebug.com/lite.html"&gt;Firebug Lite&lt;/a&gt;, &lt;a href="http://developer.yahoo.com/yui/logger/"&gt;YUI Logger&lt;/a&gt;, or &lt;a href="http://log4javascript.org/"&gt;log4javascript&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Event delegation is a great way to program for performance. The &lt;code&gt;live&lt;/code&gt; jQuery method was a great addition to the jQuery core, it makes event delegation really easy (see also the &lt;code&gt;closest&lt;/code&gt; method). Unfortunately, it isn’t quite what I expected.&lt;/p&gt;

&lt;p&gt;For example, say you have a page containing approximately 500 custom tooltip components on it (not typical, but stick with me, this is to prove a point). How might one go about adding a simple live event to activate each tooltip when the user hovers over it?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$('span.myTooltip').live('mouseover', function(event) {
    // activate tooltip
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;See the problem? jQuery will actually run the selector on the document, resulting in unnecessary overhead. jQuery is only assigning a single event handler to top level of the document, why does it need to know what nodes it will be binding to before assigning the callback?&lt;/p&gt;

&lt;p&gt;What can we do? Let’s create a jQuery function, instead of a method, so it won’t query the document. Try this on for size:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$.live = function(selector, type, fn) {
    var r = $([]);
    r.selector = selector;
    if(type &amp;amp;&amp;amp; fn) {
        r.live(type, fn);
    }
    return r;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Usage&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;// Single event type
$.live('span.myTooltip', 'mouseover', function(event) {
    // activate tooltip
});

// Multiple event types (you can call the jQuery live method on the return value from the function)
$.live('span.myTooltip')
    .live('mouseover', function(event) {
        // activate tooltip
    })
    .live('mouseout', function(event) {
        // deactivate tooltip
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also, as a side note, keep in mind that jQuery &lt;code&gt;live&lt;/code&gt; &lt;strong&gt;doesn’t&lt;/strong&gt; support space separated events, like &lt;code&gt;bind&lt;/code&gt; does.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Will not work.
$('span.myTooltip').live('mouseover mouseout', function() {});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Have fun!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/sQKZKewqecQ" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>ALARMd Unix Time Format for 1234567890 Day</title>
		<link href="http://www.zachleat.com/web/alarmd-unix-time-format-for-1234567890-day/" />
		<updated>2009-02-13T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/alarmd-unix-time-format-for-1234567890-day</id>
		<content type="html">&lt;p&gt;In honor of &lt;a href="http://www.1234567890day.com/"&gt;1234567890 day&lt;/a&gt;, I’ve added the Unix time format to &lt;a href="http://www.alarmd.com/"&gt;ALARMd&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hit &lt;strong&gt;Options&lt;/strong&gt;, then the &lt;strong&gt;Clock Format tab&lt;/strong&gt; to change to Unix Time. Enjoy!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/Y6Sro-uE3Ec" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Registration Forms Suck, Let’s Mitigate Suckiness</title>
		<link href="http://www.zachleat.com/web/registration-forms-suck-lets-mitigate-suckiness/" />
		<updated>2009-01-10T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/registration-forms-suck-lets-mitigate-suckiness</id>
		<content type="html">&lt;p&gt;&lt;img src="/web/wp-content/uploads/2009/01/signup-form.png" title="signup-form" alt="Signup Form" /&gt;&lt;/p&gt;

&lt;p&gt;A lot of people &lt;strong&gt;complain about registration forms&lt;/strong&gt;. Some people have suggested getting rid of them altogether, allowing users to utilize login credentials from accounts they already have through OpenID. But even with a highly technical audience, OpenID adoption is &lt;a href="http://blog.stackoverflow.com/2008/10/stack-overflow-openid-case-study/"&gt;problematic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, some sites have gone two ways, allowing OpenID, but also a proprietary registration system. This too, &lt;a href="http://www.wetpaintcentral.com/page/OpenID?t=anon"&gt;is problematic&lt;/a&gt;. It would seem that given a choice, the &lt;strong&gt;John Doe the Plumber style user will choose a proprietary account&lt;/strong&gt; over the confusing user experience presented to them through OpenID.&lt;/p&gt;

&lt;p&gt;But the annoyance doesn’t just lie with account registration for web applications. Typing your personal information on every blog you comment at is also repetitive and unnecessary. &lt;a href="http://www.ajaxian.com"&gt;Some sites&lt;/a&gt; even require account registration for something so minor and transient as a blog comment.&lt;/p&gt;

&lt;p&gt;Unfortunately, for the time being, it looks like &lt;strong&gt;registration forms are here to stay&lt;/strong&gt;. So, what can we do to make those registration forms more usable, more efficient, and ultimately downright friendly? I know that you’re ahead of me on this one: &lt;strong&gt;Let’s auto-complete information for the user&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Please keep in mind that this power can be used for both good and evil. Essentially what we’re discussing here is data mining available information from various social networking sites on the internet, trying to glean personal information about an end user that has volunteered a piece of their data already. What can we get from what we already have?&lt;/p&gt;

&lt;p&gt;Once a user has typed in their &lt;strong&gt;e-mail address&lt;/strong&gt;, we can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve Twitter profile information (&lt;a href="http://www.wait-till-i.com/2009/01/08/using-twitter-as-a-data-provider-to-automatically-fill-forms/"&gt;example shown on Chris Heilmann’s blog&lt;/a&gt;):

&lt;ul&gt;
&lt;li&gt;Full Name&lt;/li&gt;
&lt;li&gt;Short Personal Description&lt;/li&gt;
&lt;li&gt;Location&lt;/li&gt;
&lt;li&gt;Web site URL&lt;/li&gt;
&lt;li&gt;Time Zone&lt;/li&gt;
&lt;li&gt;Favorite Colors (used on their profile)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Retrieve an &lt;strong&gt;avatar&lt;/strong&gt; if they’ve registered for the Gravatar web service (&lt;a href="http://www.zachleat.com/web/2009/01/08/scare-your-visitors-with-this-javascript-gravatar-plugin/"&gt;See my earlier post discussing this&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Get their &lt;a href="http://gdata-javascript-client.googlecode.com/svn/trunk/samples/calendar/simple_sample/simple_sample.html"&gt;upcoming calendar events&lt;/a&gt; from a public Google Calendar. (Perhaps not as useful for autocompleting forms, but interesting)&lt;/li&gt;
&lt;li&gt;Find their &lt;a href="http://www.flickr.com/services/api/flickr.people.findByEmail.html"&gt;UID on Flickr&lt;/a&gt;, which gives you &lt;a href="http://www.flickr.com/services/api/flickr.people.getInfo.html"&gt;a source&lt;/a&gt; for:

&lt;ul&gt;
&lt;li&gt;Full Name&lt;/li&gt;
&lt;li&gt;Location&lt;/li&gt;
&lt;li&gt;Flickr Avatar&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;If you know any of their social networking usernames, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://developer.yahoo.com/mybloglog/V1/member_find_byservice.html"&gt;find their MyBlogLog profile&lt;/a&gt;, if they’ve linked the service to their account (&lt;a href="http://mybloglog.yahooapis.com/v1/user/service/twitter/zachleat?AppId=YahooDemo&amp;amp;format=xml"&gt;Sample query, I added my twitter&lt;/a&gt;). Now we have:

&lt;ul&gt;
&lt;li&gt;MyBlogLog Screen Name and ID, from which you get their &lt;a href="http://developer.yahoo.com/mybloglog/V1/member_find_byid.html"&gt;MyBlogLog profile&lt;/a&gt;:

&lt;ul&gt;
&lt;li&gt;Nickname&lt;/li&gt;
&lt;li&gt;Picture&lt;/li&gt;
&lt;li&gt;Age&lt;/li&gt;
&lt;li&gt;Sex&lt;/li&gt;
&lt;li&gt;Location&lt;/li&gt;
&lt;li&gt;A list of tags they use to describe themselves.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MyBlogLog Avatar&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Those are only some of the proof of concept API’s that I’ve listed here. The interesting piece of this, is that once you have a small piece of information, it &lt;strong&gt;opens up the door to other searches&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One can only imagine how many leaves are in this tree. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Facebook’s &lt;a href="http://wiki.developers.facebook.com/index.php/Users.getInfo"&gt;Users.getInfo&lt;/a&gt; (&lt;a href="http://wiki.developers.facebook.com/index.php/JavaScript_Client_Library"&gt;in JavaScript&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Yahoo’s Social Tools, get an &lt;a href="http://developer.yahoo.com/social/rest_api_guide/introspective-guid-resource.html"&gt;end user’s GUID&lt;/a&gt; and go to town on &lt;a href="http://developer.yahoo.com/social/rest_api_guide/social_dir_api.html"&gt;their profile&lt;/a&gt;.

&lt;ul&gt;
&lt;li&gt;Google Contacts, I didn’t even start to look through &lt;a href="http://code.google.com/apis/contacts/"&gt;their API’s&lt;/a&gt;.
Before you start jumping the privacy fence to a self induced heart attack, remember that &lt;strong&gt;all this information has been volunteered&lt;/strong&gt; by each individual participating in each of these services. Remember, with great power comes great responsibility.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;What do you think? Scary or useful?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/v79jSN60FI8" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Scare Your Visitors with this JavaScript Gravatar Plugin</title>
		<link href="http://www.zachleat.com/web/scare-your-visitors-with-this-javascript-gravatar-plugin/" />
		<updated>2009-01-08T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/scare-your-visitors-with-this-javascript-gravatar-plugin</id>
		<content type="html">&lt;h2&gt;&lt;a href="/javascript/gravatar/index.html"&gt;See the Demo&lt;/a&gt;&lt;/h2&gt;

&lt;h2&gt;&lt;a href="/javascript/gravatar/jquery.gravatar.js"&gt;Download the Source Code&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2009/01/blog-comment.png" title="blog-comment" alt="Tournology Blog Comment Form" /&gt;&lt;/p&gt;

&lt;p&gt;Here’s a use case. An unregistered visitor visits your blog, and decides that your &lt;strong&gt;content is so good that it merits a comment&lt;/strong&gt;! Congratulations, you’ve fooled them! Now you can &lt;a href="http://www.centernetworks.com/twply-twitter-replies-auction"&gt;twply their account details for $1200 on Sitepoint&lt;/a&gt;! Just kidding. But generally, when you visit a blog’s commenting section (such as the &lt;a href="http://www.tournology.com/blog/"&gt;Tournology Blog&lt;/a&gt; shown above), you’ll see a simple form to authenticate you’re not a spammer, generally including (among other things) an e-mail address field.&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2009/01/blog-comment-after.png" title="blog-comment-after" alt="Tournology Blog Comment Form With Gravatar" /&gt;&lt;/p&gt;

&lt;p&gt;Well, since they’re typing their e-mail address, wouldn’t it be cool if we could &lt;strong&gt;show them their gravatar&lt;/strong&gt; right there, inline with the blog comment form? Well, that’s now possible with my new &lt;strong&gt;&lt;a href="http://www.zachleat.com/javascript/gravatar/jquery.gravatar.js"&gt;JavaScript Gravatar Plugin&lt;/a&gt;&lt;/strong&gt;! It doesn’t have any server side language dependencies.&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2009/01/gravatar-signup.png" title="gravatar-signup" alt="Gravatar Signup Page" /&gt;&lt;/p&gt;

&lt;p&gt;Hell, &lt;a href="http://en.gravatar.com/"&gt;gravatar.com&lt;/a&gt; could even use this to &lt;strong&gt;improve the user experience of registering your e-mail account&lt;/strong&gt;. Right now it does a full page refresh and doesn’t even show you a preview!&lt;/p&gt;

&lt;h2&gt;&lt;a href="/javascript/gravatar/index.html"&gt;See the Demo&lt;/a&gt;&lt;/h2&gt;

&lt;h2&gt;&lt;a href="/javascript/gravatar/jquery.gravatar.js"&gt;Download the Source Code&lt;/a&gt;&lt;/h2&gt;

&lt;h2&gt;Licensing&lt;/h2&gt;

&lt;p&gt;Licensed under the &lt;a href="http://sam.zoy.org/wtfpl/"&gt;WTFPL&lt;/a&gt;, as highly recommended by &lt;a href="http://foohack.com/"&gt;Isaac Schleuter&lt;/a&gt; (&lt;a href="/web/2007/04/05/google-using-yui-grids-css/"&gt;see discussion&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;JavaScript Dependencies:&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Requires &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt; (Feel free to port and post a link!)&lt;/li&gt;
&lt;li&gt;Requires &lt;a href="http://pajhome.org.uk/crypt/md5/md5.js"&gt;md5.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Example Usage:&lt;/h2&gt;

&lt;p&gt;Easiest form, onblur of email text input field:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$('#emailTextField').blur(function(event) {
    $(this).after($.gravatar($(this).val()));
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Showing all options, again onblur of email text input field.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$('#email').blur(function(event) {
    $('body').append($.gravatar($(this).val(), {
        // integer size: between 1 and 512, default 80 (in pixels)
        size: 200,
        // maximum rating (in order of raunchiness, least to most): g (default), pg, r, x
        rating: 'pg',
        // url to define a default image (can also be one of: identicon, monsterid, wavatar)
        image: 'identicon'
    }));
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; This script has been moved to &lt;a href="http://github.com/zachleat/jQuery-Gravatar"&gt;Github&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/At_cT5es3b0" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>DOMContentLoaded Inconsistencies (in Browsers and JavaScript Libraries)</title>
		<link href="http://www.zachleat.com/web/domcontentloaded-inconsistencies/" />
		<updated>2008-12-04T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/domcontentloaded-inconsistencies</id>
		<content type="html">&lt;p&gt;&lt;strong&gt;Quick Summary&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Prototype and Dojo are the only major JavaScript frameworks that correctly time the DOMContentLoaded inside of an iframe in Internet Explorer. MooTools comes close and both YUI and jQuery both exhibit incorrect behavior.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Usually, browsers that have a native DOMContentLoaded event will fire it after both JavaScript and CSS (external script, link tags) have loaded. But Opera fires prior to CSS link tags loading.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;We all know the problem, but we may not all call it the same thing. Every popular JavaScript library has its own name for the DOMContentLoaded event.&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;JavaScript Library&lt;/th&gt;
&lt;th&gt;Event Name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;YUI&lt;/td&gt;
&lt;td&gt;&lt;a href="http://developer.yahoo.com/yui/docs/YAHOO.util.Event.html#method_onDOMReady"&gt;DOMReady&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;jQuery&lt;/td&gt;
&lt;td&gt;&lt;a href="http://docs.jquery.com/Events/ready"&gt;ready&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MooTools&lt;/td&gt;
&lt;td&gt;&lt;a href="http://mootools.net/docs/Utilities/DomReady"&gt;domready&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prototype&lt;/td&gt;
&lt;td&gt;&lt;a href="http://www.prototypejs.org/api/document/observe"&gt;dom:loaded&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dojo&lt;/td&gt;
&lt;td&gt;&lt;a href="http://api.dojotoolkit.org/jsdoc/dojo/1.2/dojo.addOnLoad"&gt;addOnLoad&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;But the naming scheme isn’t the only part about this event that’s inconsistent. There are a few hacks strewn around the net that have been bastardized (read: modified to the will of library authors) into each individual framework. These have been posted time and time again, but for post completeness are the following:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;IE DOMContentLoaded Hack&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&lt;a href="http://javascript.nwbox.com/IEContentLoaded/"&gt;doScroll&lt;/a&gt;&lt;/code&gt; by Diego Perini&lt;/td&gt;
&lt;td&gt;Uses a &lt;code&gt;doScroll&lt;/code&gt; method call, which will throw an error if the &lt;code&gt;ondocumentready&lt;/code&gt; event hasn’t fired on the &lt;strong&gt;primary document&lt;/strong&gt; (take note of the usage of the word primary).  Once &lt;code&gt;doScroll&lt;/code&gt; doesn’t throw an error, it is assumed the DOM has loaded.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms536957(VS.85).aspx"&gt;onreadystatechange&lt;/a&gt;&lt;/code&gt; and &lt;code&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms534359.aspx"&gt;readyState&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;onreadystatechange&lt;/code&gt; &lt;em&gt;“fires when the state of the object has changed,”&lt;/em&gt; and changes the &lt;code&gt;readyState&lt;/code&gt; property of the object through the following states (not all apply to every type of element): &lt;code&gt;uninitialized&lt;/code&gt;, &lt;code&gt;loading&lt;/code&gt;, &lt;code&gt;loaded&lt;/code&gt;, &lt;code&gt;interactive&lt;/code&gt;, and &lt;code&gt;complete&lt;/code&gt;.  (source: MSDN) Usually set on the document object, or a script element (as used in the Script Defer method described next.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="http://dean.edwards.name/weblog/2005/09/busted/"&gt;Script Defer&lt;/a&gt; by Dean Edwards&lt;/td&gt;
&lt;td&gt;document.write’s a script tag with a &lt;code&gt;defer&lt;/code&gt; attribute.  Defer will cause the browser to delay execution of the script until the DOM has successfully loaded (using onreadystatechange on the script tag until its readyState is “complete”).  Without defer, the browser would execute any script tag immediately.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="http://dean.edwards.name/weblog/2005/09/busted2/"&gt;HTC Behavior&lt;/a&gt; by Dean Edwards&lt;/td&gt;
&lt;td&gt;Much less popular approach using proprietary HTC Behavior files.  Generally avoided due to the addition of an extra HTTP request to the page in order to download the external .htc file.  As a side note, if using this approach, the &lt;code&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms531021.aspx"&gt;"oncontentready"&lt;/a&gt;&lt;/code&gt; event will work better than the &lt;a href="http://msdn.microsoft.com/en-us/library/ms531024.aspx"&gt;“ondocumentready”&lt;/a&gt; event used by Mr. Edwards.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ghetto Method&lt;/td&gt;
&lt;td&gt;Of course, the easiest way to do it is to put a script tag right above your ending &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt; tag that triggers the event manually.  This really only works if you have full control of the content, and isn’t really a library solution.  Worth noting though.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;&lt;a href="http://zachleat.com/Projects/domcontentloaded/"&gt;&lt;img src="/web/wp-content/uploads/2008/12/domcontentloaded.png" alt="Benchmark for Library DOMContentLoaded Implementations" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://zachleat.com/Projects/domcontentloaded/"&gt;&lt;em&gt;Benchmark for Library DOMContentLoaded Implementations&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I created a benchmark trying to answer the simple question: when does the DOMContentLoaded event fire? Each implementation has different effects, especially in iframes and with stylesheets.&lt;/p&gt;

&lt;h2&gt;What Works&lt;/h2&gt;

&lt;p&gt;The Internet Explorer hacks presented above are reliable when used on a standalone document (not inside of an iframe).&lt;/p&gt;

&lt;p&gt;Mozilla Firefox, Safari, Chrome, and Opera all contain a native DOMContentLoaded event that each framework uses to consistently fire at the correct time. So, it isn’t even worth summarizing the results for tests in every browser with a native DOMContentLoaded event, except Opera. Opera took a different design approach with their DOMContentLoaded event (certainly not wrong, just different), which we’ll analyze below.&lt;/p&gt;

&lt;h3&gt;Internet Explorer inside an Iframe&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;All libraries below did no branching based on IE versions, all used the same method for IE6, IE7, or IE8. I performed no tests in IE8, however.&lt;/em&gt;&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th rowspan="2"&gt;JavaScript Library&lt;/th&gt;
&lt;th rowspan="2"&gt;Method&lt;/th&gt;
&lt;th colspan="4"&gt;Waited for:&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;&amp;lt;body&amp;gt; &amp;lt;script&amp;gt;&lt;/th&gt;
&lt;th&gt;&amp;lt;head&amp;gt; &amp;lt;script&amp;gt;&lt;/th&gt;
&lt;th&gt;&amp;lt;link&amp;gt; CSS&lt;/th&gt;
&lt;th&gt;&amp;lt;img&amp;gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;YUI 2.6.0&lt;/td&gt;
&lt;td&gt;doScroll, setTimeout&lt;/td&gt;
&lt;td colspan="4"&gt;Incorrect: Fires almost immediately (~20ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;jQuery 1.2.6&lt;/td&gt;
&lt;td&gt;window onload&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prototype 1.6.0.3&lt;/td&gt;
&lt;td&gt;Script Defer&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MooTools 1.2.1&lt;/td&gt;
&lt;td&gt;doScroll and set innerHTML, setTimeout&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dojo 1.2.0&lt;/td&gt;
&lt;td&gt;Script Defer&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="http://javascript.nwbox.com/IEContentLoaded/"&gt;IEContentLoaded&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;doScroll, document.onreadystatechange&lt;/td&gt;
&lt;td colspan="4"&gt;Incorrect: JavaScript error.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="http://www.thefutureoftheweb.com/blog/adddomloadevent"&gt;addDOMLoadEvent&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Script Defer&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;ul&gt;
&lt;li&gt;&lt;em&gt;For some reason, not only did the MooTools library not wait for the body script to trigger DOMContentLoaded, the body script never executed at all.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The &lt;strong&gt;most important takeaway&lt;/strong&gt; from this blog post are the successful methods of faking DOMContentLoaded in Internet Explorer. The obvious &lt;strong&gt;library winners here are Prototype and Dojo&lt;/strong&gt;, with the addDOMLoadEvent script also exhibiting correct behavior. MooTools is a close runner up, and I would be interested to find out why it didn’t execute the body script (that’s left for another day, or perhaps a generous commenter).&lt;/p&gt;

&lt;h3&gt;Opera 9.6&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th rowspan="2"&gt;JavaScript Library&lt;/th&gt;
&lt;th rowspan="2"&gt;Method&lt;/th&gt;
&lt;th colspan="4"&gt;Waited for:&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;&amp;lt;body&amp;gt; &amp;lt;script&amp;gt;&lt;/th&gt;
&lt;th&gt;&amp;lt;head&amp;gt; &amp;lt;script&amp;gt;&lt;/th&gt;
&lt;th&gt;&amp;lt;link&amp;gt; CSS&lt;/th&gt;
&lt;th&gt;&amp;lt;img&amp;gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;YUI 2.6.0&lt;/td&gt;
&lt;td&gt;Native DOMContentLoaded&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;jQuery 1.2.6&lt;/td&gt;
&lt;td&gt;Native DOMContentLoaded + Code to wait for Stylesheets&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prototype 1.6.0.3&lt;/td&gt;
&lt;td&gt;Native DOMContentLoaded&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MooTools 1.2.1&lt;/td&gt;
&lt;td&gt;Native DOMContentLoaded&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dojo 1.2.0&lt;/td&gt;
&lt;td&gt;Native DOMContentLoaded&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="http://javascript.nwbox.com/IEContentLoaded/"&gt;IEContentLoaded&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;N/A to Opera&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="http://www.thefutureoftheweb.com/blog/adddomloadevent"&gt;addDOMLoadEvent&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Native DOMContentLoaded&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;As you can see above, &lt;strong&gt;Opera typically will fire DOMContentLoaded prior to stylesheets loading&lt;/strong&gt; successfully (ignoring the jQuery specific code to provide consistency cross-browser)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="http://www.adamkoch.com/"&gt;Adam Koch&lt;/a&gt; for first pointing me in the direction of jQuery in an iframe ignoring DOMContentLoaded in IE.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; There is an open ticket for &lt;a href="http://sourceforge.net/tracker/index.php?func=detail&amp;amp;aid=2008289&amp;amp;group_id=165715&amp;amp;atid=836476"&gt;YUI on Sourceforge&lt;/a&gt;, and I’ve opened a ticket for &lt;a href="http://dev.jquery.com/ticket/3693"&gt;jQuery on their Trac site&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/x6MVAwl_g9w" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>Dear IE6: Please Cache my Images.</title>
		<link href="http://www.zachleat.com/web/dear-ie6-please-cache-my-images/" />
		<updated>2008-10-18T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/dear-ie6-please-cache-my-images</id>
		<content type="html">&lt;p&gt;A few months ago, I took on a new role at &lt;a href="http://www.unionpacific.jobs/careers/explore/prof/index.shtml"&gt;Union Pacific Railroad&lt;/a&gt; as the lead architect for an internal project: a Union Pacific UI Library used in our IT department on all new web-based projects.  Based on &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;, it is similar to a project like &lt;a href="http://ui.jquery.com/"&gt;jQuery UI&lt;/a&gt;, but it has a few more components and they’re branded to our color scheme and programmed to our usability requirements.&lt;/p&gt;

&lt;p&gt;The project has allowed me to expand my knowledge of browser quirks, improving my frontend-fu with every closed support ticket.  What does that mean for you?  More blogs posts.  Learn from my mistakes (and from those I’ve inherited).&lt;/p&gt;

&lt;p&gt;This week presented an interesting, albeit decreasingly relevant scenario, where a customer was seeing performance problems when loading a simple web page in Internet Explorer 6.  The only hint to the root cause was a claim that he witnessed “400 items remaining” in his status bar.  Naturally, this took awhile, but at least we had somewhere to start: Apache access logs.&lt;/p&gt;

&lt;p&gt;Consider the following (jQuery) code to &lt;strong&gt;add three new images&lt;/strong&gt; to the page using JavaScript:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
    &amp;lt;script type="text/javascript" src="jquery-1.2.6.min.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;style type="text/css"&amp;gt;
    img.bacon { width: 100px; height: 67px; background-image: url(bacon.png); }
    &amp;lt;/style&amp;gt;
   &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;script type="text/javascript"&amp;gt;
        jQuery(function() {
          jQuery('body').append('&amp;lt;img src="spacer.png" class="bacon"/&amp;gt;');
          jQuery('body').append('&amp;lt;img src="spacer.png" class="bacon"/&amp;gt;');
          jQuery('body').append('&amp;lt;img src="spacer.png" class="bacon"/&amp;gt;');
        });
        &amp;lt;/script&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note how each image being added dynamically has a &lt;strong&gt;background-image&lt;/strong&gt; as well.&lt;/p&gt;

&lt;p&gt;In a &lt;strong&gt;normal&lt;/strong&gt; web browser (read: Internet Explorer 7+, Firefox *), this would result in the following Apache &lt;code&gt;access.log&lt;/code&gt; (with an empty browser cache) with only &lt;strong&gt;4 HTTP requests&lt;/strong&gt; (ignoring favicon.ico, which is irrelevant to this study):&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;127.0.0.1 – - [18/Oct/2008:22:59:09 -0500] “GET /ie6cache/ HTTP/1.1″ 200 657&lt;/p&gt;

&lt;p&gt;127.0.0.1 – - [18/Oct/2008:22:59:09 -0500] “GET /ie6cache/jquery-1.2.6.min.js HTTP/1.1″ 200 55774&lt;/p&gt;

&lt;p&gt;127.0.0.1 – - [18/Oct/2008:22:59:09 -0500] “GET /ie6cache/spacer.png HTTP/1.1″ 200 207&lt;/p&gt;

&lt;p&gt;127.0.0.1 – - [18/Oct/2008:22:59:09 -0500] “GET /ie6cache/bacon.png HTTP/1.1″ 200 5416&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;In Internet Explorer 6, however, this is the resulting Apache &lt;code&gt;access.log&lt;/code&gt; (empty browser cache) with &lt;strong&gt;8 HTTP requests&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;127.0.0.1 – - [18/Oct/2008:22:57:48 -0500] “GET /ie6cache/ HTTP/1.1″ 200 657&lt;/p&gt;

&lt;p&gt;127.0.0.1 – - [18/Oct/2008:22:57:48 -0500] “GET /ie6cache/jquery-1.2.6.min.js HTTP/1.1″ 200 55774&lt;/p&gt;

&lt;p&gt;127.0.0.1 – - [18/Oct/2008:22:57:48 -0500] “GET /ie6cache/spacer.png HTTP/1.1″ 200 207&lt;/p&gt;

&lt;p&gt;127.0.0.1 – - [18/Oct/2008:22:57:48 -0500] “GET /ie6cache/spacer.png HTTP/1.1″ 200 207&lt;/p&gt;

&lt;p&gt;127.0.0.1 – - [18/Oct/2008:22:57:48 -0500] “GET /ie6cache/bacon.png HTTP/1.1″ 200 5416&lt;/p&gt;

&lt;p&gt;127.0.0.1 – - [18/Oct/2008:22:57:48 -0500] “GET /ie6cache/bacon.png HTTP/1.1″ 200 5416&lt;/p&gt;

&lt;p&gt;127.0.0.1 – - [18/Oct/2008:22:57:48 -0500] “GET /ie6cache/spacer.png HTTP/1.1″ 200 207&lt;/p&gt;

&lt;p&gt;127.0.0.1 – - [18/Oct/2008:22:57:48 -0500] “GET /ie6cache/bacon.png HTTP/1.1″ 200 5416&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;When a web browser parses your markup and sees three image tags with identical src attributes, it makes only one HTTP request to the server for that image, and the rest of the images are loaded from the local web browser cache (no more HTTP requests are made).  This is standard behavior for all modern web browsers.  But in IE6, as you can see from the above log, made 3 requests to the server for both &lt;code&gt;spacer.png&lt;/code&gt; and &lt;code&gt;bacon.png&lt;/code&gt;.  Why?&lt;/p&gt;

&lt;p&gt;Turns out there are two independent issues at play here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The classic &lt;em&gt;&lt;a href="http://www.mister-pixel.com/#Content__state=is_that_simple"&gt;IE6 background-image flicker&lt;/a&gt;&lt;/em&gt; problem.  This has been documented extensively, and the problem is that IE6 bypasses its local web browser cache for any image requests made for CSS background-images inserted on the page dynamically.  The good news for this one is that the fix is a simple one.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if(jQuery.browser.msie &amp;amp;&amp;amp; parseInt(jQuery.browser.version, 10) == 6) {
  try {
    document.execCommand("BackgroundImageCache", false, true);
  } catch(err) {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the simple check for IE 6 execution only.  This is optional, but keep in mind that this problem is not present in IE7+.  During your testing, also keep in mind that Mister Pixel reports (and I can confirm) that once you run this command, this setting &lt;strong&gt;will persist in your browser&lt;/strong&gt;, even if you empty your cache and remove the code from your scripts.  You’ll need to close your browser window to reset the setting to default.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;See also &lt;a href="http://dean.edwards.name/my/flicker.html"&gt;Dean Edwards’&lt;/a&gt; and &lt;a href="http://www.hedgerwow.com/360/bugs/dom-fix-ie6-background-image-flicker.html"&gt;Hedger Wang’s&lt;/a&gt; studies on this issue for more information.&lt;/em&gt;  But this is really only half the problem.  This will fix the duplicate bacon.png HTTP requests, but we’ll still see 3 spacer.png HTTP requests in our logs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The other issue is a separate but equal problem with IE6 caching.  When inserting images with identical &lt;code&gt;src&lt;/code&gt; attributes, IE6 will always go to the server (which means an extra HTTP request) for a new image.  This is a &lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;319546"&gt;documented &lt;em&gt;feature&lt;/em&gt; in IE6&lt;/a&gt;, and the fix they have listed on their page isn’t ideal.  The best solution here is to &lt;strong&gt;eliminate the need for &lt;code&gt;spacer.png&lt;/code&gt;&lt;/strong&gt; altogether.  I can put these bacon background’s on a div tag just as easily, emphasizing pragmatism over semantics in this case (it’s a small sacrifice, you’ll live).  If you have an &lt;code&gt;&amp;amp;lt;img&amp;amp;gt;&lt;/code&gt; tag with a source you actually need, why not move it to the background image on a div tag?  Unfortunately here, the takeaway is that &lt;strong&gt;your logic may need to be restructured&lt;/strong&gt; to workaround this issue.&lt;br/&gt;
See also &lt;a href="http://www.bazon.net/mishoo/articles.epl?art_id=958"&gt;Mihai Bazon’s study&lt;/a&gt; for more information, but do keep in mind that grouping this issue with the background flicker problem is an incorrect categorization.  They are two separate issues and the fixes represented on that page don’t really fix the issue at all.  Implementing server side caching as a “fix” is like using a bandaid for a tourniquet. You don’t want an HTTP request to go to the server &lt;strong&gt;at all&lt;/strong&gt;, I don’t care if the response is a 200 OK or a 304 Not Modified.  No HTTP request is always going to be faster than a server side cached response.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;These issues will present themselves more frequently if you have the “Every visit to the page” caching option enabled in your Internet Tools in Internet Explorer.  Good luck.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/QIM0vmc5irY" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Relative URLs including the Domain</title>
		<link href="http://www.zachleat.com/web/relative-urls-including-the-domain/" />
		<updated>2008-10-16T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/relative-urls-including-the-domain</id>
		<content type="html">&lt;p&gt;Just a neat little trick I saw while browsing the source code of Google Calendar. In some of their CSS files, they link to background-images using URLs that include everything but the protocol, which is something I hadn’t seen before.&lt;/p&gt;

&lt;p&gt;The most common usage of a relative URL is linked from the root (note the slash at the beginning), like so:&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/themes/hemingway/images/title.png" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;You can also use &lt;code&gt;../&lt;/code&gt; to navigate up a directory in your path, but that’s boring. The interesting question is: what if I wanted to load content from a separate domain, while at the same time transparently using the protocol used on my page?&lt;/p&gt;

&lt;p&gt;Do what Google Calendar does and use the following style:&lt;br/&gt;
&lt;img src="//calendar.google.com/googlecalendar/images/calendar_sm2_en.gif" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;Note the lack of &lt;code&gt;http:&lt;/code&gt; or &lt;code&gt;https:&lt;/code&gt; from the URL. If this page &lt;a href="https://www.zachleat.com/web/2008/10/16/relative-urls-including-the-domain/"&gt;were hosted on https&lt;/a&gt; (we don’t pay for certificates around here, so you’ll have to put up with the security warning), the last image source will load from https as well at no additional development cost.&lt;/p&gt;

&lt;p&gt;This seems like it would be especially useful if you were using the YDN Performance tip to &lt;a href="http://developer.yahoo.com/performance/rules.html#split"&gt;Split Components Across Domains&lt;/a&gt;. Remember, we’re not just talking images. This involves how the browser resolves URLs, so could be used inside href tags, css urls (as Google Calendar did), etc.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/7NYMNhK_uF0" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>ALARMd is a Google Code Project</title>
		<link href="http://www.zachleat.com/web/alarmd-is-a-google-code-project/" />
		<updated>2008-10-08T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/alarmd-is-a-google-code-project</id>
		<content type="html">&lt;p&gt;&lt;strong&gt;Update: &lt;a href="/web/alarmd-is-now-on-github/"&gt;ALARMd has been moved to GitHub&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I received a request this week to participate in development of the internet alarm clock I developed awhile back called &lt;a href="http://www.alarmd.com/"&gt;ALARMd&lt;/a&gt;. It has gone through two major revisions, and my interest in contributing additional source code to the project is waning. I’ve got &lt;a href="http://www.tournology.com/"&gt;other projects&lt;/a&gt;. So, I’ve decided to publish it to Google Code. I won’t be doing new development on the project, but will accept patches and commits to the repository. Feel free to ask me for project member status.&lt;/p&gt;

&lt;p&gt;See &lt;a href="http://code.google.com/p/alarmd/"&gt;ALARMd on Google Code&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/G8-pzC0JKe0" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Fight Registrastination. Register to vote!</title>
		<link href="http://www.zachleat.com/web/fight-registrastination-register-to-vote/" />
		<updated>2008-09-07T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/fight-registrastination-register-to-vote</id>
		<content type="html">&lt;p&gt;&lt;em&gt;Apologies to international readers, this spam message is intended for citizens of the USA only. Thanks for understanding.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Have a friend that hasn’t registered to vote yet? Do your civic duty by guilting them into action. Help them fight registrastination by sharing a link to a big bold deadline.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.zachleat.com/registrastination/"&gt;Fight Registrastination. Register to vote NOW!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For those demanding technical content from each blog post, the page does use a nice &lt;a href="http://www.maxmind.com/app/javascript_city"&gt;JavaScript IP Address Geocoder hosted by MaxMind&lt;/a&gt; that’s worth a look. It also uses a previously mentioned &lt;a href="http://www.zachleat.com/web/2008/03/23/yet-another-pretty-date-javascript/"&gt;JavaScript Pretty Date Difference&lt;/a&gt; script.&lt;/p&gt;

&lt;p&gt;Here’s a few other things that one might also look at if they were making a location aware application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://code.google.com/apis/maps/documentation/services.html#Geocoding"&gt;Google Maps API: Geocoding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/gears/wiki/GeolocationAPI"&gt;Gears GeoLocation API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiki.developers.facebook.com/index.php/Users.getInfo"&gt;Parse a Facebook user’s location.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://apiwiki.twitter.com/REST"&gt;Twitter’s API only provides update_location&lt;/a&gt;, not a way to get the current location.&lt;/li&gt;
&lt;li&gt;As mentioned above, &lt;a href="http://www.maxmind.com/app/ip-location"&gt;MaxMind’s IP Address Geocoding Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://fireeagle.yahoo.net/"&gt;Yahoo’s FireEagle&lt;/a&gt;, &lt;a href="http://brightkite.com/"&gt;BrightKite&lt;/a&gt;, &lt;a href="http://plazes.com/"&gt;Plazes&lt;/a&gt;, and &lt;a href="http://www.dopplr.com/"&gt;Dopplr&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;MaxMind’s seemed the best fit for my use case: guessing the State of an anonymous user.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/Te1ZT5eAnYs" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Writing a Front End Engineer’s Resume (or CV)</title>
		<link href="http://www.zachleat.com/web/resume/" />
		<updated>2008-09-04T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/resume</id>
		<content type="html">&lt;p&gt;&lt;em&gt;In the United States, we usually call this document a resume, but it would appear that the international term is actually CV. There are differences, but the tips used here can be applied to both.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Everyone is trying to sell something nowadays, and the most important product you can sell is yourself. My high school counselor used to tell all of her students that same advice, and unfortunately most of them became hookers. But if you’re not into prostitution, by now you’ve probably realized why so many people have said that blogs are &lt;a href="http://www.darowski.com/tracesofinspiration/2007/03/06/the-blog-is-the-new-resume/"&gt;the&lt;/a&gt; &lt;a href="http://bokardo.com/archives/the-blog-is-the-new-resume/"&gt;new&lt;/a&gt; &lt;a href="http://greengaloshes.cc/2007/04/the-blog-as-the-new-resume/"&gt;resume&lt;/a&gt;. It’s true – I’ve had a few pretty meaty hooks dangled in front of my fish brain since I started this web site, and a lot of large companies are using blogs as a means of finding new talent.&lt;/p&gt;

&lt;p&gt;But a blog will only get you in the front door, many employers still want to see a real resume prior to entry into the screening process. So, why not kick your resume up a notch? Let’s iron its pages, shave its hairy regions, and spray some web-based musk on that bad boy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tips for Putting your Resume on the Web&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Don’t use anything that generates code (that means no DreamWeaver or heaven forbid, Microsoft Word). You want your “view source” to look like a marine’s hair cut: everything should be indented uniformly.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sprinkle some microformats in there! There is even a specific &lt;a href="http://microformats.org/wiki/hresume"&gt;hresume&lt;/a&gt; microformat. Some other good microformats to use are: &lt;a href="http://microformats.org/wiki/hcard"&gt;hcard&lt;/a&gt; (like a personal business card, but can also be used to describe an organization as well), &lt;a href="http://microformats.org/wiki/hcalendar"&gt;hcalendar&lt;/a&gt; (for any dates, or date ranges: like when you were employed), &lt;a href="http://gmpg.org/xfn/"&gt;XFN&lt;/a&gt; (to describe relationships between people, think references), &lt;a href="http://microformats.org/wiki/adr"&gt;adr&lt;/a&gt; (for addresses).
 Of course, the good part about microformats it that there is overlap between them. hcard uses adr and hcalendar, and hresume uses hcard, etc.&lt;/p&gt;

&lt;p&gt; Some social web sites have already provided some microformats that you can use as a starting point: &lt;a href="http://www.linkedin.com/pub/7/b8a/237"&gt;Linked-in has an hresume&lt;/a&gt; for every profile, and &lt;a href="http://twitter.com/zachleat"&gt;twitter has a hcard&lt;/a&gt; that you can pilfer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Add a favicon. As the &lt;a href="http://developer.yahoo.com/performance/rules.html#favicon"&gt;Yahoo Performance team suggests&lt;/a&gt;, the browser is still going to request one, even if one isn’t in the markup, so you might as well have one.&lt;/li&gt;
&lt;li&gt;Pick your DOCTYPE carefully. Make sure it’s not one of the “loose” ones, for obvious prostitution-based reasons described above — the stricter the better. Whatever DOCTYPE you decide to use, make sure your markup validates properly. No mistakes here. I chose to serve my document using HTML 4.01 Strict as text/html with UTF-8 encoding.&lt;/li&gt;
&lt;li&gt;Your handwritten CSS should validate as well. If you have some library code that misses the mark in a few places, I think that’s okay. Remember: &lt;em&gt;a good coder codes, a great coder re-uses.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Make sure it looks good when your future employer prints out 500 copies to pass around the company as an example of the best resume he’s ever laid his eyes on. Add a media=”print” stylesheet to beautify the print layout.&lt;/li&gt;
&lt;li&gt;Make sure it all validates, loads fast, and doesn’t have any broken links. I like to use YSlow to test my page weight and see my ranking.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Bombs away! Those are the tips I followed to create &lt;a href="http://www.zachleat.com/resume/"&gt;my web-based resume&lt;/a&gt;. It has a YSlow score of 89, is 17.2K in size with 5 HTTP requests, and validates as &lt;a href="http://validator.w3.org/check?uri=http://www.zachleat.com/resume/"&gt;HTML 4.01 Strict&lt;/a&gt;, and my non-library CSS is valid &lt;a href="http://jigsaw.w3.org/css-validator/validator?uri=http://www.zachleat.com/resume"&gt;CSS 2.1&lt;/a&gt; (I’m also using YUI CSS for layout, which doesn’t validate).&lt;/p&gt;

&lt;p&gt;Once you’re finished, hresume even has a &lt;a href="http://microformats.org/wiki/hresume-examples-in-wild"&gt;public wiki page&lt;/a&gt; where they let you post your resume. Have fun, or get rich trying!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: grammar nazi cullination.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/WL1WPL8hk48" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Emulating onhashchange without setInterval</title>
		<link href="http://www.zachleat.com/web/onhashchange-without-setinterval/" />
		<updated>2008-08-21T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/onhashchange-without-setinterval</id>
		<content type="html">&lt;p&gt;There is one limitation that all of the major JavaScript browser history management plugins have to hack around:  How to tell when there is a change to the &lt;code&gt;location.hash&lt;/code&gt;?  Sure, you can tell when you’re modifying the hash yourself, but what if the user hits the back/forward button?&lt;/p&gt;

&lt;p&gt;&lt;a href="http://developer.yahoo.com/yui/history/"&gt;YUI’s History component&lt;/a&gt; and Really Simple History both use setInterval with an internal variable to compare and find changes.  But this isn’t really an optimal solution.  As proper front end engineers, we should avoid timeouts as much as possible.  Internet Explorer 8 will have an &lt;a href="http://msdn.microsoft.com/en-us/library/cc288209(VS.85).aspx"&gt;onhashchange event&lt;/a&gt; that clients will be able to subscribe to.  That will be nice.  But surely, a cross browser solution without the use of setInterval exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Look, a cross browser solution without the use of setInterval:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On initialization, we load an iframe onto the page that is positioned absolutely at -500px,-500px so the user can’t see it. It is a skeleton page that only needs cross browser code to add an “&lt;code&gt;onscroll&lt;/code&gt;” event, and to be able to calculate the scrolled position of the iframe itself.  For my example, I use jQuery and the dimensions plugin to accomplish this, but it could easily be trimmed down to only the bare essentials (or ported to a different library).&lt;/li&gt;
&lt;li&gt;To add an AJAX history entry into the browser’s history under an assigned hash string, we first add a &lt;code&gt;&amp;lt;a name="hashString"&amp;gt;hashString&amp;lt;/a&amp;gt;&lt;/code&gt; to the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tag of the iframe.  Using css to increase the size of the a tag proportional to the iframe’s height, we can guarantee scrolling will happen.&lt;/li&gt;
&lt;li&gt;Then, we change the &lt;code&gt;location.hash&lt;/code&gt; of the iframe to point to that &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag.  This will scroll the iframe to the content, and create a new entry in the browser’s &lt;code&gt;history&lt;/code&gt; object.&lt;/li&gt;
&lt;li&gt;Inside the iframe, we have our &lt;code&gt;onscroll&lt;/code&gt; event that fires when the scrolling in the previous step took place.  (Minor IE-related workaround: The browser’s &lt;code&gt;history&lt;/code&gt; object is changed, but the hash property doesn’t when attempting to read it later.  Instead, we find the &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; that matches up with the scrollY/pageOffsetY property inside of the iframe, and retrieve the matching hash from the &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag.)&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;The nice thing about this approach is that you don’t even need a history manager anymore.  This little iframe will do all of your dirty work for you.  And it will even maintain your history alongside any other iframe browsing on the page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can serve as back button support and full AJAX history manager.&lt;/li&gt;
&lt;li&gt;Page Weight: the test page and iframe HTML files together weigh in at 2.76 KB.  That includes the non-jQuery JavaScript needed to do everything.&lt;/li&gt;
&lt;li&gt;Cross browser: Tested in FF3, IE7, IE6, Opera 9.5, (not Safari — see below)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Limitations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No bookmarking support.  We aren’t changing the top hash, we’re changing the iframe hash, so these aren’t bookmarkable.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Sample Example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/Projects/history/"&gt;My Test Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/Projects/history/history.zip"&gt;Download the test page (2 HTML files, and jQuery 1.2.6 and dimensions)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Given time for more rigorous testing, it doesn’t look like Safari supports this approach.  So, until WebKit fixes &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=9166"&gt;#9166&lt;/a&gt;, we’ll have to stick to timers in Safari.  A more pragmatic programmer than I might hack around this approach by exploiting &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=19202"&gt;#19202&lt;/a&gt;, but that certainly wouldn’t be a long term solution.  I’ve also updated the test page above, at &lt;a href="http://dean.edwards.name/"&gt;Dean Edwards&lt;/a&gt; humble request, to support dynamic client size text size changes.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/B3tmqA0NdwU" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Double Whammy: OpenID and Microformats</title>
		<link href="http://www.zachleat.com/web/double-whammy-openid-and-microformats/" />
		<updated>2008-05-23T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/double-whammy-openid-and-microformats</id>
		<content type="html">&lt;h2&gt;Microformategery&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://www.ownyouridentity.com/2008/04/30/get-satisfactions-nice-import-profile-feature/"&gt;Own your Identity had a great post today&lt;/a&gt; detailing a great feature on the signup form of the &lt;a href="http://getsatisfaction.com/people/new"&gt;Get Satisfaction&lt;/a&gt; site.&lt;/p&gt;

&lt;p&gt;They rely on the fact that sites like Twitter and Flickr publish an &lt;a href="http://microformats.org/wiki/hcard"&gt;hCard microformat&lt;/a&gt; for all of their users publicly on their website.  If you go to &lt;a href="http://twitter.com/zachleat/"&gt;my twitter page&lt;/a&gt; and view the source, you’ll find the following code available to anyone (without authentication):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;address&amp;gt;
   &amp;lt;ul class="about vcard entry-author"&amp;gt;
      &amp;lt;li&amp;gt;&amp;lt;span class="label"&amp;gt;Name&amp;lt;/span&amp;gt; &amp;lt;span class="fn"&amp;gt;Zach Leatherman&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;&amp;lt;span class="label"&amp;gt;Location&amp;lt;/span&amp;gt; &amp;lt;span class="adr"&amp;gt;Omaha, NE USA&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
      &amp;lt;li&amp;gt;&amp;lt;span class="label"&amp;gt;Web&amp;lt;/span&amp;gt; &amp;lt;a href="http://www.zachleat.com/" class="url" rel="me"&amp;gt;http://www.zachle...&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
      &amp;lt;li id="bio"&amp;gt;&amp;lt;span class="label"&amp;gt;Bio&amp;lt;/span&amp;gt; &amp;lt;span class="bio"&amp;gt;UI Programmer, JavaScript Enthusiast, Soccer Hooligan&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;
   &amp;lt;/ul&amp;gt;
&amp;lt;/address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The premise here is that hCard tells you how to parse this markup to get usable information.  The &lt;code&gt;adr&lt;/code&gt; CSS class tells you what my address is.  The &lt;code&gt;fn&lt;/code&gt; CSS class tells you what my name is, and so on.  So, Get Satisfaction goes and spiders this page behind the scenes and autopopulates your profile with what it can find.  Pretty sweet.&lt;/p&gt;

&lt;p&gt;Now, they don’t limit you to the services they provide, which are: Flickr, Technorati, Twitter, Upcoming, and last.fm.  They provide an Other category for any hCard enabled URL (your personal homepage or perhaps an &lt;a href="http://microformats.org/wiki/hresume"&gt;hResume&lt;/a&gt; you have posted on the web).&lt;/p&gt;

&lt;h2&gt;Integrate with OpenID&lt;/h2&gt;

&lt;p&gt;However, why not take it to the next level?  Why not integrate this microformat functionality WITH an openid login system?  You’d be able to kill two birds (not a twitter joke) with one stone in some cases, since both Twitter and Technorati are also OpenID producers (re-echo: We need more consumers).&lt;/p&gt;

&lt;p&gt;So, not only do you get the benefits of having OpenID authentication on your website, but you’d be able to prepopulate a certain amount of profile data with an hCard parser.  And the best part is, if you already have a &lt;a href="http://remysharp.com/2008/04/24/stop-using-openid-why-how/"&gt;nice clean user interface&lt;/a&gt; set up to handle different OpenID producers, there wouldn’t be any additional clutter on the interface to get this benefit.  It’d be transparent to the user when it works, and fall back to a normal empty profile form when it doesn’t.&lt;/p&gt;

&lt;p&gt;What I’d like to see, is more sites that are OpenID producers, also serve hCard microformats as well.  If we can get all the major producers on board, we’d have a nice tidy little system going.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/xnAFb3TyAF8" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Selecting XML Nodes with JavaScript (Peril of getElementsByTagName)</title>
		<link href="http://www.zachleat.com/web/selecting-xml-with-javascript/" />
		<updated>2008-05-10T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/selecting-xml-with-javascript</id>
		<content type="html">&lt;p&gt;&lt;em&gt;There are two popular camps for ajax data formats right now: XML and JSON. Both have their (dis-)advantages. The purpose of this article is to show you how to effectively parse XML in the browser.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;Super Fast Beginner’s Primer&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Case 1: &lt;strong&gt;Node&lt;/strong&gt; (or un-namespaced node, null-namespaced node): a node without a prefix, such as child here:&lt;br/&gt;
&lt;code&gt;&amp;lt;child/&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Case 2: &lt;strong&gt;Default namespaced node&lt;/strong&gt;: a node without a prefix, but a parent node (or itself) has a xmlns attribute, like both root and child here:&lt;br/&gt;
&lt;code&gt;&amp;lt;root xmlns="http://example.com/"&amp;gt;&amp;lt;child/&amp;gt;&amp;lt;/root&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Case 3: &lt;strong&gt;Namespaced node&lt;/strong&gt;: a node with a prefix, and a parent node (or itself) declaring a xmlns with that prefix attached, like both child and root here:&lt;br/&gt;
&lt;code&gt;&amp;lt;prefix:root prefix:xmlns="http://example.com/"&amp;gt;&amp;lt;prefix:child/&amp;gt;&amp;lt;/root&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;/End Primer&lt;/h3&gt;

&lt;p&gt;Parsing XML in the browser can be a tricky beast. There are many different wrong ways to do it, which can leave you cold and naked in a snowstorm if you’re not careful. So, let’s put on the metaphorical electric one-sie of standards based code and let the power of Edison heat our JavaScript code like the innards of a &lt;a href="http://starwars.wikia.com/wiki/Tauntaun"&gt;tauntaun&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If there is one thing you can take away from this article, its that the problems with XML in JavaScript have already been solved, and there is library code out there to do the job for you. But libraries aren’t a substitute for knowledge (abstraction is a dangerous thing during education), so let’s learn &lt;strong&gt;why&lt;/strong&gt; these problems are occurring so we can wrinkle our gray matter and increase our productivity at the same time.&lt;/p&gt;

&lt;h2&gt;Use Cases&lt;/h2&gt;

&lt;p&gt;These are the main use cases that takes place when selecting a node inside of an XML document:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Case 1&lt;/strong&gt;: Selecting un-namespaced nodes (or nodes in the null namespace):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;root&amp;gt;&amp;lt;child/&amp;gt;&amp;lt;/root&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This one is easy. If you can guarantee that your XML will never have any namespaces, you’re home free. Take your get out of jail free card and run for the hills. Using this assumption, you can query nodes inside of your XML Document object using nothing other than &lt;code&gt;getElementsByTagName()&lt;/code&gt;. Lucky bastard.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// assume oDocEl is the documentElement inside of an XML Document 
var correctForCase1 = oDocEl.getElementsByTagName('child');
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Case 2&lt;/strong&gt;: Selecting default namespaced nodes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;root xmlns="http://example.com/"&amp;gt;&amp;lt;child/&amp;gt;&amp;lt;/root&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Tread lightly, this is about to get serious. In most cases, historically I had thought that using the solution described for Case 1 would be sufficient in this case. I had learned awhile back that Internet Explorer treats node names (including namespace prefix and local name together) as one string. So, the method for Case 1 should work for Internet Explorer, especially in the case of node sans prefix. In Firefox, you’d have to use getElementsByTagNS(), but that would be just a simple wrapper.&lt;/p&gt;

&lt;p&gt;Then I met an Internet Explorer exception. The only unique thing about this installation of Internet Explorer 7 was that it had MSXML 6 installed, when all the other computers I had tested on were using MSXML 3. The obvious conclusion here is that MSXML 6 won’t select child nodes for Case 2.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var incorrectForCase2 = oDocEl.getElementsByTagName('child');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s the right way to select nodes for Case 2. Fair warning, to keep the code examples here simple, this solution requires Sarissa (sarissa.js and sarissa_ieemu_xpath.js) to be included on the page prior to usage.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// assume oDoc is an XML Document object.
oDoc.setProperty("SelectionNamespaces", "xmlns:whatever='http://example.com/'");
var oDocEl = oDoc.documentElement;
var correctForCase2A = oDocEl.selectNodes('whatever:child');
var correctForCase2B = oDocEl.selectSingleNode('whatever:child');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note how we’ve mapped what was the default namespace (without a prefix) to be a namespace WITH a prefix during the node selection.&lt;/p&gt;

&lt;p&gt;It should be noted that when the resultant XML has a namespace attached (Case 2 and 3), Firefox works fine using getElementsByTagNameNS. IE doesn’t include support for that method, however, so we’re forced to find a more complete solution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Case 3&lt;/strong&gt;: Select a non-default namespaced node:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;root prefix:xmlns="http://example.com/"&amp;gt;&amp;lt;prefix:child/&amp;gt;&amp;lt;/root&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As I mentioned in Case 2, normally (pre-MSXML 6), you’d be able to perform a &lt;code&gt;getElementsByTagName('prefix:child')&lt;/code&gt; in IE and use getElementsByTagNameNS in Firefox as usual. But that has changed now. We need to set up the SelectionNamespaces property for IE, and we’ll use Sarissa to take it cross-browser for us.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// assume oDoc is an XML Document object.
oDoc.setProperty("SelectionNamespaces", "xmlns:whatever='http://example.com/'");
var oDocEl = oDoc.documentElement;
var correctForCase3A = oDocEl.selectNodes('whatever:child');
var correctForCase3B = oDocEl.selectSingleNode('whatever:child');
// Note, this is the same code as Case 2 (which is a good thing)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that we did &lt;em&gt;not&lt;/em&gt; have to use the same prefix that was defined by the result XML. We can map it to whatever we want (literally).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;Why is this important?&lt;/h2&gt;

&lt;p&gt;Because most libraries don’t handle Case 2 and Case 3, which are important parts of XML. Here’s some code straight from YUI 2.5.1 (DataSource component):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Line 1394
var xmlNode = result.getElementsByTagName(key);
if(xmlNode &amp;amp;&amp;amp; xmlNode.item(0) &amp;amp;&amp;amp; xmlNode.item(0).firstChild) {
    data = xmlNode.item(0).firstChild.nodeValue;
}
else {
       data = "";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice how they just do getElementsByTagName. For shame :( jQuery doesn’t handle Case 2 or Case 3 either. (Proof is an exercise to the reader :P) So, if you have XML data sources with namespaces, it would do you well to use the solution presented in this article, or you’re going to have headaches later.&lt;/p&gt;

&lt;h2&gt;Springer’s Final Word&lt;/h2&gt;

&lt;p&gt;Don’t use getElementsByTagName. If you do, PLEASE include a note saying that your code isn’t going to support namespaced XML. Branch your selection code to check if Sarissa has been included on the page, and use Sarissa for namespaced XML if it’s there. It’s not fun to be pidgin-holed into the simplest case of XML.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/BONPlmlgwaI" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Javascript Objects are NOT JSON</title>
		<link href="http://www.zachleat.com/web/javascript-objects-are-not-json/" />
		<updated>2008-05-09T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/javascript-objects-are-not-json</id>
		<content type="html">&lt;p&gt;&lt;em&gt;The headline should more accurately read “Javascript Objects are not &lt;strong&gt;necessarily&lt;/strong&gt; JSON.” But that waters it down a bit, don’t you think?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I know this has been posted a few times before, but this is not something I knew until recently, and after learning it, have noticed quite a few other people doing it wrong as well. So, to risk adding another reverb to the echo chamber, I’ll post a link to a &lt;a href="http://www.thefutureoftheweb.com/blog/json-is-not-just-object-notation"&gt;good explanation&lt;/a&gt; by Jesse Skinner on the specifics of the JSON specification.&lt;/p&gt;

&lt;p&gt;The main point here is that &lt;strong&gt;all object keys and strings in JSON must have double quotes.&lt;/strong&gt; I encourage you to look through the &lt;a href="http://json.org/"&gt;train track specification&lt;/a&gt; to verify for yourself.&lt;/p&gt;

&lt;p&gt;If you try to use Captain &lt;a href="http://www.json.org/json2.js"&gt;Crockford’s JSON Parser&lt;/a&gt;, it won’t parse your string with single quotes or (un/single)-quoted object keys. His parser has a nice regex checker built-in (and a walker callback to let you parse date strings into Date() objects). It’s a good way to verify that external data, or a data source not under your control, is safe to eval and use in your own code.&lt;/p&gt;

&lt;p&gt;Here are a few quick examples:&lt;/p&gt;

&lt;h2&gt;Valid JSON&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;{"myKey": "myString"}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Don’t use single quotes. Don’t use unquoted object keys.&lt;/p&gt;

&lt;h2&gt;Invalid JSON&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;{myKey: "myString"}
{'myKey': 'myString'}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Credits to Jonathan Snook for the &lt;a href="http://www.snook.ca/archives/javascript/json_is_a_subse/"&gt;initial write-up&lt;/a&gt; and Crockford for formalizing JSON.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/DO2Se-UQW2s" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Surnamespacing</title>
		<link href="http://www.zachleat.com/web/surnamespacing/" />
		<updated>2008-05-07T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/surnamespacing</id>
		<content type="html">&lt;p&gt;Everyone has a library. Everyone has their own utility classes and functions they’re using in their own personal and contracted projects. And now that everyone has a blog too, they’re all releasing their libraries as open source, using the commando underoo philosophy of wild, free, and unrestricted naming schemes for their code. Not anymore. Let’s surnamespace.&lt;/p&gt;

&lt;p&gt;What does surnamespacing give me?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Accountability&lt;/strong&gt;: Your code is directly linked to your family honor. You’d be surprised how hard people work at test cases and increased code coverage when the respect of their lineage is at stake.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connect&lt;/strong&gt; with your Extended Family: Connect with programmers sharing your namespace, your family is now your development team.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Minimize Collisons&lt;/strong&gt;: The ball and chain associated with an imposed naming scheme means that we won’t have everyone using foo and bar to hold their code, unless you’re the lucky son of a bitch that has inherited that top notch surnamespace real estate.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Faster&lt;/strong&gt; Initial Development Cycle: Sometimes naming your library is the hardest part. Skip this step and just surnamespace it.
Jesus Christ, please show me some examples:&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;JavaScript Surnamespacing&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var Christ = {
    Jesus: {
        walkOn: function(obj) {},
        turn: function(from, to) {},
        respawn: function() {}
    }
};
// Sample Usage
Christ.Jesus.walkOn('water');
Christ.Jesus.turn('water', 'wine');
Christ.Jesus.respawn();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Java Surnamespacing&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package Christ;
public class Jesus {
    public void walkOn(String s) {}
    public void turn(String from, String to) {}
    public void respawn() {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;PHP 6 Surnamespacing (&lt;a href="http://php.net/~derick/meeting-notes.html"&gt;projected usage&lt;/a&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namespace Christ {
    class Jesus {
        public function walkOn($obj) {}
        public function turn($from, $to) {}
        public function respawn() {}
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Apparently I can’t write Java code. Don’t tell work.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/1vYzcqGgi1M" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Don’t Let the Door Hit You Onunload and Onbeforeunload</title>
		<link href="http://www.zachleat.com/web/dont-let-the-door-hit-you-onunload-and-onbeforeunload/" />
		<updated>2008-04-22T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/dont-let-the-door-hit-you-onunload-and-onbeforeunload</id>
		<content type="html">&lt;p&gt;Many people attempt a last ditch effort to save page state in the browser by using the onunload or onbeforeunload events. This has been studied at great length by &lt;a href="http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript"&gt;Patrick Hunlock&lt;/a&gt;, who uses the perhaps now common knowledge of using a Synchronous Ajax call to perform the page state save.&lt;/p&gt;

&lt;p&gt;Another use for the onbeforeunload event to allow the user to cancel the action that initiated the user leaving in the first place. Gmail uses this technique when the user is in the middle of writing a draft of an e-mail and attempts to leave the page.&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2008/04/gmail-confirm.png" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Gmail pops up this prompt when the user attempts to leave the page while drafting an email.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Worthy to note, however, is that Opera &lt;a href="http://www.quirksmode.org/bugreports/archives/2004/11/load_and_unload.html"&gt;doesn’t fire the unload event&lt;/a&gt; when the browser refreshes the page, or uses the back/forward buttons to browse off of the page (I had no success with the fix posted in the comments on that page). What’s worse, Opera never fires the onbeforeunload event. This creates a serious problem with attempting to save page state prior to a user leaving your page.&lt;/p&gt;

&lt;p&gt;Browser support aside, I believe that the onbeforeunload prompt is not an ideal way to protect the user from lost work (or unsaved page state). Humanized has argued, and I agree, that &lt;a href="http://www.alistapart.com/articles/neveruseawarning"&gt;an undo operation is much easier on the end user than a warning message&lt;/a&gt;. The strange thing is, Gmail could save the draft in a synchronous Ajax request in the onunload event. They aren’t using the prompt to save Opera users from losing their drafts, since the Opera web browser doesn’t even fire the onbeforeunload event. (Interestingly enough, they are using some sort of browser history management to fire a warning to the user when they press back, or forward, in Opera — but Reload can’t be caught using this method, so your draft email could be lost).&lt;/p&gt;

&lt;p&gt;From a User Interface design standpoint, I would recommend just sticking with onunload. You can still perform your synchronous Ajax call in the method to save the state of your page, so that the user can later resume their state or undo the operation. (Except for Back/Forward/Refresh in Opera, until they support a better onunload or any onbeforeunload). The onbeforeunload prompt is an unnecessary evil, and doesn’t do much besides annoy the end user with another warning message and a mouse click.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/boQFaGyPPAA" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>Rethinking JavaScript Grids and DataTables</title>
		<link href="http://www.zachleat.com/web/rethinking-javascript-grids-and-datatables/" />
		<updated>2008-04-13T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/rethinking-javascript-grids-and-datatables</id>
		<content type="html">&lt;p&gt;In the world of front end engineering, one must consider the end-user of the interface first, and above all other things. The priorities should not start with development ease, nor external library preference. The priorities should start with the needs of the consumer of your end product.&lt;/p&gt;

&lt;p&gt;Evolution of your engineering skill is also a vital trait in this world, which means that as a developer increases his knowledge of good practices and proper methods, sometimes he must shirk his previous assertions about the world as he previously knew it. And today I’m shirking a staple of the front end as all web users know it: The Grid (DataTable) Component.&lt;/p&gt;

&lt;p&gt;Of course, I’ve written a few articles in the past about the &lt;a href="http://developer.yahoo.com/yui/datatable/"&gt;YUI DataTable&lt;/a&gt;, during my long love affair with Yahoo’s User Interface library. Another popular one is jQuery’s &lt;a href="http://tablesorter.com/docs/"&gt;TableSorter&lt;/a&gt;. Then there’s the &lt;a href="http://dojotoolkit.org/book/dojo-book-0-9/docx-documentation-under-development/grid"&gt;Dojo Grid&lt;/a&gt;, a component &lt;a href="http://www.sitepen.com/blog/2007/09/16/the-dojo-grid/"&gt;inherited from TurboAjax&lt;/a&gt;. ExtJS has a variety of nice examples as well for their &lt;a href="http://extjs.com/deploy/dev/examples/#sample-1"&gt;Ext 2.0 Grid&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And after using these Grids and DataTables, I certainly respect the programming that went into developing these components. But let’s take a step back for a second. Why do the users need the bells and whistles in these components? Are they worth the extra load time and complexity they add to the interface?&lt;/p&gt;

&lt;p&gt;All we’re doing here is putting a nice coat of paint on a  tag. Sure, it might have some nice ancillary features like Ajax Data Loading, but those don’t really matter – they are things that can be easily performed with some good Ajax and DOM insert utility functions. In fact, most of the core features included in these components could be described as feature creep, and not beneficial to the end user at all. Feature creep contributes to code bloat, which means the user is downloading bytes to their web browser that they don’t need, which can hamper performance. Libraries usually have online examples of their components, and the include sizes are seen below. (Gzip compression not considered)&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;JavaScript Size&lt;/th&gt;
&lt;th&gt;Minimized&lt;/th&gt;
&lt;th&gt;Link&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;YUI DataTable&lt;/td&gt;
&lt;td&gt;216.6 KB&lt;/td&gt;
&lt;td&gt;Minimized&lt;/td&gt;
&lt;td&gt;&lt;a href="http://developer.yahoo.com/yui/examples/datatable/dt_basic_clean.html"&gt;Example&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dojo Grid&lt;/td&gt;
&lt;td&gt;338.4 KB&lt;/td&gt;
&lt;td&gt;Unminimized&lt;/td&gt;
&lt;td&gt;&lt;a href="http://dojotoolkit.org/book/dojo-book-0-9/docx-documentation-under-development/grid/simple-grid"&gt;Example&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ext Grid&lt;/td&gt;
&lt;td&gt;545.5 KB&lt;/td&gt;
&lt;td&gt;Minimized&lt;/td&gt;
&lt;td&gt;&lt;a href="http://extjs.com/deploy/dev/examples/grid/array-grid.html"&gt;Example&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;jQuery TableSorter&lt;/td&gt;
&lt;td&gt;66 KB&lt;/td&gt;
&lt;td&gt;Minimized&lt;/td&gt;
&lt;td&gt;&lt;a href="http://www.tablesorter.com/"&gt;Example&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;The JavaScript include sizes listed above are directly proportional to the feature set that the components provide, and should give you an idea of the overhead involved with using them. Do we need 545.5 KB of features coming down the pipe to give our users an extra bell, or an extra whistle? Let’s analyze the features to rationalize their usage, and remove items from the feature set.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sorting&lt;/li&gt;
&lt;li&gt;Modifying column order and display&lt;/li&gt;
&lt;li&gt;Resizing columns&lt;/li&gt;
&lt;li&gt;Editing of row data directly on the grid itself&lt;/li&gt;
&lt;li&gt;Scrolling&lt;/li&gt;
&lt;li&gt;Pagination&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Sorting&lt;/h3&gt;

&lt;p&gt;Data should be used in the context of its usefulness. You have a list of messages in your e-mail inbox. What’s the most useful context for this list? In order of date received. The default sort order provided by the application, to facilitate proper use of the application. Is comparing the rows in the grid by any other method as useful? Does the user need to see the list of messages ordered alphabetically by subject? In these cases where the user is in need of a specific message, &lt;em&gt;searching and filtering&lt;/em&gt; is more useful than sorting. The default sort is useful, but allowing the user to resort on the client, in most cases, is not as useful as other methods of finding a row.&lt;/p&gt;

&lt;h3&gt;Modifying column order and display&lt;/h3&gt;

&lt;p&gt;The same argument can be made for any of the other methods of customization provided to the end user. Does the user need to reorder or hide columns? The context provided by the application should be sufficient to use the applications data in the way it was intended. Don’t overcomplicate your user interface with needless features or a deluge of useless data. Provide succinct, appropriate data, and the user needn’t reorder or change the interface.&lt;/p&gt;

&lt;h3&gt;Resizing columns&lt;/h3&gt;

&lt;p&gt;The default HTML  tag expands to fit the data inside of its cells. Even when you set the width of the table explicitly, the cells adjust themselves accordingly to fit the data. This should be the behavior of your table. You needn’t monkey around with widths, the browser is smart enough to do it for you. You can even customize a cell to wrap its text to multiple lines with CSS, if need be.&lt;/p&gt;

&lt;h3&gt;Editing of row data directly on the grid itself&lt;/h3&gt;

&lt;p&gt;If you’re providing an Excel spreadsheet interface for the end user to customize your data, you haven’t designed your interface correctly. Rethink how the user needs to interact with the data you’ve provided, and give them a better, simpler way to edit the data.&lt;/p&gt;

&lt;h3&gt;Scrolling&lt;/h3&gt;

&lt;p&gt;Everyone knows that internal scrollbars on a page are evil. I don’t even like scrollbars on textareas, to be honest. Previously, I had worked and reworked the YUI DataTable to handle horizontal scrolling. Looking back on this, it was a mistake. There are better ways to handle lots of data in a table, without the heavy mouse interaction and scanning that scrolling require. Which brings me to my next point.&lt;/p&gt;

&lt;h3&gt;Pagination&lt;/h3&gt;

&lt;p&gt;This is the one exception to the feature set cutting board. This is the one feature that’s is a requirement, when the data set has too many records to fit on a single page.&lt;/p&gt;

&lt;p&gt;Keep these in mind, and look at the feature set provided by a few sites using tabular data centric interfaces that know a thing or two about interface design:&lt;/p&gt;

&lt;h2&gt;Examples&lt;/h2&gt;

&lt;h3&gt;Google Mail&lt;/h3&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2008/04/gmail.png" alt="Google Mail" /&gt;&lt;/p&gt;

&lt;h3&gt;WordPress Admin&lt;/h3&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2008/04/wordpress-admin.png" alt="Wordpress 2.5 Admin Interface" /&gt;&lt;/p&gt;

&lt;h3&gt;Google Reader&lt;/h3&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2008/04/google-reader.png" alt="Google Reader List View" /&gt;&lt;/p&gt;

&lt;h2&gt;So, what should we include?&lt;/h2&gt;

&lt;p&gt;A simple CSS class to style your table is sufficient, with links to paginate the table (properly) and/or a hover for row selection if needed. You’re looking at 10-20 lines of jQuery code, maximum, and a few CSS declarations. In lieu of sorting, of course, you’ll need to program in a mechanism for searching and filtering as well. But really, the difficulty with programming this component is knowing what to leave out.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/TfWvFuXmmJY" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>ALARMd 2 Beta, with Google Calendar Integration</title>
		<link href="http://www.zachleat.com/web/alarmd-2-beta-with-google-calendar-integration/" />
		<updated>2008-04-06T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/alarmd-2-beta-with-google-calendar-integration</id>
		<content type="html">&lt;p&gt;&lt;a href="http://www.zachleat.com/Projects/alarmd-beta/"&gt;Take a look: ALARMd 2 Beta&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update&lt;/strong&gt;: added Metric and Unit Circle time formats.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I know, some of you are reading this and thinking to yourself — genital herpes is more appealing than yet another online alarm clock. But to that I say, congratulations, that’s one of the new features in ALARMd 2!&lt;/p&gt;

&lt;p&gt;Why did I make another online alarm clock? Mostly due to missing features and limitations in the old version, but also because it’s a good exercise in JavaScript programming and User Interface design. Everyone likes to hone their skills, and this is my publicly viewable work desk. But the real reason I went back to rewrite the old version is that I’m hooked on &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt;. I can’t get enough of that sweet, sweet, source code, and couldn’t stand to see my old, crusty, handwritten DOM manipulations polluting web browsers across the world. Users of the Yahoo User Interface Library (what I used for the original version of ALARMd) would do well to consider jQuery a nice plugin to be used alongside YUI. It will clean up your code MAX_INT-fold.&lt;/p&gt;

&lt;p&gt;Here are a few new features and addressed limitations in ALARMd 2.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy Alarm Mode: No more fumbling around when you just want one simple easy-to-add alarm.&lt;/li&gt;
&lt;li&gt;Google Calendar Alarm Mode: Customize your alarm schedule to your heart’s content, it will load your alarms straight from a publicly available Google Calendar. There are some great features with this:

&lt;ul&gt;
&lt;li&gt;Load only the first calendar event of every day&lt;/li&gt;
&lt;li&gt;Day Limiter (Example: Only load calendar events within the next 3 days)&lt;/li&gt;
&lt;li&gt;Minute Adjuster (Example: Alarm me 90 minutes before work without adding a separate event)&lt;/li&gt;
&lt;li&gt;Google does a nice job of normalizing dates as well, so you don’t have to worry about calendar time syncing. If it says 8AM on your calendar, it’s going to alarm you at 8AM on your computer’s local time.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;New Clock Formats:

&lt;ul&gt;
&lt;li&gt;Human Readable Clock Format: Think “Half Past Two”, or “Quarter Til Twelve”. This idea is from &lt;a href="http://www.insightoutsight.co.uk/viewproject.php?cid=2&amp;amp;pid=3&amp;amp;iid=2"&gt;Laurence Willmott’s Project “It’s about Time”&lt;/a&gt;. I took some liberties with his labeling scheme, I hope he doesn’t mind too much.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://zapatopi.net/metrictime/"&gt;Metric Time Format&lt;/a&gt;: Shows the measurement Centi-days in Local Metric Time. Basically, it’s a percentage of much of the day has passed. If it’s 80.000, 80 percent of the day has passed, which coincides with 7:12 PM.&lt;/li&gt;
&lt;li&gt;Unit Circle Time Format: Displays the time in radians that would be shown if a clock were &lt;a href="http://www.cafepress.com/poofietomato.49111330"&gt;pasted on top of a unit circle&lt;/a&gt;. If it’s 12 o’clock, it will read π/2. After programming this one, it’s starting to seem normal in my brain. Oh, it’s 3π/2? Time to eat dinner. How the hell did it get 2π/3??&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/web/2008/03/23/yet-another-pretty-date-javascript/"&gt;Human Readable Alarm Dates&lt;/a&gt;: Think “29 Minutes”, “1 Hour”, “2 Days Ago”.&lt;/li&gt;
&lt;li&gt;Much cleaner interface, using a jQuery accordion to display the options.&lt;/li&gt;
&lt;li&gt;The old ALARMd required an internet connection for all sources, and provided no safeguard if your internet went down whilst you were sleeping. ALARMd 2 preloads all Youtube videos in the background when the page loads using the new &lt;a href="http://apiblog.youtube.com/2008/03/something-to-write-home-about.html"&gt;Youtube JavaScript API&lt;/a&gt;. A nice benefit of this is that the browser window no longer requires focus to play the YouTube video.&lt;/li&gt;
&lt;li&gt;Less clunky interface for adding new alarm sources.&lt;/li&gt;
&lt;li&gt;Repeat option for YouTube videos and MP3′s. Turn infinite loop on or off. Careful with this one. Don’t leave ALARMd going if you’re not going to be home when it goes off.&lt;/li&gt;
&lt;li&gt;CSS Skins, Use the really simple ones I’ve included for Red, Green, or Blue, or include your own URL to your own hosted CSS file. Have a good skin? I’ll include it in the select list and give you some props here, just link to it in the comments below. Use some CSS class hooks to spice up your skins (they are mutually exclusive). These are CSS classes that are added to the body tag to allow you to style the alarm differently depending on the alarm clock’s current state. &lt;em&gt;Future enhancements&lt;/em&gt; might include more than just alarm-based hooks: Year, day of the year, and hour of the day might be useful, that way you could style the clock to show a lighter background during the day and a darker background at night.

&lt;ul&gt;
&lt;li&gt;.alarmWithin30Minutes&lt;/li&gt;
&lt;li&gt;.alarmWithin15Minutes&lt;/li&gt;
&lt;li&gt;.alarmWithin5Minutes&lt;/li&gt;
&lt;li&gt;.alarmWithin1Minute&lt;/li&gt;
&lt;li&gt;.alarmActive (Alarm is being played)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Still has all the old favorites:

&lt;ul&gt;
&lt;li&gt;Test Button to make sure the video or source is working and to check your volume.&lt;/li&gt;
&lt;li&gt;Count Down mode to show the time between now and the first alarm.&lt;/li&gt;
&lt;li&gt;Store your own list of alarm sources, using YouTube, MP3, Last.FM, or any URL (Pandora is included).&lt;/li&gt;
&lt;li&gt;Military time (24 hour clock) and seconds toggle.&lt;/li&gt;
&lt;li&gt;Naked mode (get rid of the extras)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Finished reading? I’m surprised you didn’t click the link at the top: &lt;a href="http://www.zachleat.com/Projects/alarmd-beta/"&gt;ALARMd 2 Beta&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remember, this is BETA. That means it’s new. I’ve done my best to test and code out all the kinks, but there may be a few that slipped through. Try it out and please report any bugs. And once again, this code is released under the BSD license.&lt;/p&gt;

&lt;p&gt;I’ll probably move this to the main ALARMd.com domain shortly.&lt;/p&gt;

&lt;p&gt;Alarmd has been personally tested with Firefox 2, Firefox 3, Internet Explorer 7, Safari 3.1, and Opera 9.27, all on Windows. Google GDATA reports an unsupported browser error on Safari and Opera, which you can hide using custom CSS.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/F14zUpH0O_8" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>20000 Leagues Under the API: YouTube JavaScript</title>
		<link href="http://www.zachleat.com/web/20000-leagues-under-the-api-youtube-javascript/" />
		<updated>2008-04-05T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/20000-leagues-under-the-api-youtube-javascript</id>
		<content type="html">&lt;p&gt;Today, children, we’ll be exploring the wonderful world of the official JavaScript API published by YouTube a few weeks ago. I read a &lt;a href="http://apiblog.youtube.com/2008/03/something-to-write-home-about.html"&gt;few&lt;/a&gt; &lt;a href="http://blogoscoped.com/archive/2008-03-14-n11.html"&gt;interesting&lt;/a&gt; &lt;a href="http://www.wait-till-i.com/2008/03/12/video-captioning-made-easy-with-the-youtube-javascript-api/"&gt;posts&lt;/a&gt; on the subject when it first came out, and it’s been on my list of things to explore for the next (and hopefully last) version of &lt;a href="http://www.alarmd.com/"&gt;Alarmd&lt;/a&gt;. This isn’t going to be a long post so much as a laundry list of points worth mentioning and limitations there-of regarding the API itself.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you want to change videos dynamically by loading a new video into an existing player, you must use the Chromeless player (which requires an API key). The loadVideoById() method is only available in the Chromeless player. Whatever you do, don’t try to dynamically destroy and create a new player, this will cause JavaScript errors in Internet Explorer (although not Firefox).&lt;/li&gt;
&lt;li&gt;CSS properties: When the player has the css &lt;code&gt;display: none&lt;/code&gt; applied, it will not play. When the css &lt;code&gt;visibility: hidden&lt;/code&gt; is applied, the video will still play, but will not be shown on the screen. If you wanted a headless player, like what the music search engine &lt;a href="http://humanized.com/weblog/2007/11/13/songza-launch/"&gt;Songza&lt;/a&gt; does, you’d want to take this approach. Word of warning, there’s some tricky shit going on when you try to dynamically change these properties on a player and run commands on the player at the same time (or close to the same). For instance, I got into a sticky situation where I’d try to show the player and load a new video into the player in the same method. I had to separate these with a timeout to get both to run without error.&lt;/li&gt;
&lt;li&gt;To load, you must play. Unfortunately, I wanted to pre-load the video without actually playing the video. This is unsupported. To handle this, I had to play, then pause after a timeout (using window.setTimeout). Not the prettiest, but it seems to work. Obviously the API in this case has very low cohesion, as the loadVideoById method ALSO plays the video, not simply doing ONLY what the method name suggests.&lt;/li&gt;
&lt;li&gt;Forcing a global? When the player first loads after you’ve used the SWFObject embedSWF() command, it will call the function onYouTubePlayerReady(), which you can’t customize. It must be that function name, and it must be in the global namespace. Keep in mind that onYouTubePlayerReady() is called every time the player is shown (when it was otherwise hidden using the css &lt;code&gt;display: none&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Unfortunately, there is some voodoo going on here that I don’t fully understand. I’m not a flash guru, nor have I ever claimed to be. But there have been a few bugs in my experience with the API that have led me to believe that it’s not quite there yet. Maybe my use cases were a bit unique, but they weren’t that extreme. I should be able to hide and show the player without error. I should be able to destroy the player without error. I should be able to load a video without playing it.&lt;/p&gt;

&lt;p&gt;But hey, it works.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/6R1Gm4jP4DU" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Code Like the Big Boys: Flickr</title>
		<link href="http://www.zachleat.com/web/code-like-the-big-boys-flickr/" />
		<updated>2008-03-30T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/code-like-the-big-boys-flickr</id>
		<content type="html">&lt;p&gt;&lt;em&gt;Code like the Big Boys is a series of posts about code solutions used by major websites. What can we learn from these professional websites to use in our own code?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JavaScript&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Looking at the source code of the Flickr home page is actually pretty strange. For one, there is only one JavaScript source code file (other than the advertising scripts), a solution for &lt;a href="http://webfx.eae.net/dhtml/pngbehavior/pngbehavior.html"&gt;PNG Alpha Transparency in Internet Explorer&lt;/a&gt;, included as an &lt;a href="http://msdn2.microsoft.com/en-us/library/ms531018(VS.85).aspx"&gt;HTML Component&lt;/a&gt;. The source for the PNG Behavior script (credit to Erik Arvidsson) is unchanged, with the exception of the removal of some extraneous comments, but curiously enough no whitespace removed (a suggestion to save them a few bucks in bandwidth). Looking at their HTML source, they seem to emphasize whitespace and readability over bandwidth savings, which seems fine to me. At least their visitors (you and I) can more easily learn something from their code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSS&lt;/strong&gt;&lt;br/&gt;
They’ve taken the same route as one of the tips from &lt;a href="http://snook.ca/archives/html_and_css/top_css_tips/"&gt;Jonathan Snook&lt;/a&gt;, and declared all styles for an element on a single line. They use your standard css to reset to a base starting point, much like YUI’s Reset CSS we’re all familiar with. One interesting declaration I noticed prominently inside of their CSS was the .Butt css class, declared on their primary Search form button. I’m curious to know the semantic meaning behind that one.&lt;/p&gt;

&lt;p&gt;They use the &lt;a href="http://www.info.com.ph/~etan/w3pantheon/style/starhtmlbug.html"&gt;tan hack&lt;/a&gt; as well to isolate a CSS declaration for IE browsers:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;* html #featured-image cite {bottom: -1px;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is to workaround for an IE limitation to absolutely positioning content at the bottom of a relatively positioned div, in this case the black box containing the credits (or citation, hence the cite tag) inside of the feature image.&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2008/03/flickr_cite.jpg" title="flickr_cite" alt="Flickr Citation Tag" /&gt;&lt;/p&gt;

&lt;p&gt;Another interesting CSS Hack they’ve employed involves the line-height for  tags containing Unicode characters to select different languages. It starts out like &lt;a href="http://www.dustindiaz.com/min-height-fast-hack/"&gt;Dustin Diaz’s min-height hack&lt;/a&gt;, but throws a loop.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;height: 0px !important;
height /**/:13px;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’m not familiar with the &lt;code&gt;/**/&lt;/code&gt; syntax, and would really appreciate any information someone has on what platform this is targeting. A comment would be nice!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Editors Note (2013): The &lt;code&gt;/**/&lt;/code&gt; syntax is to target &lt;a href="http://browserhacks.com/"&gt;everything but IE6&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTML&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Standard here, and they have some nice meta tags for the I-phone:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;meta name="viewport" content="width=950" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All in all, it’s short and sweet code for a home page. It’s nice to see such clean code with an eye towards standards on a commercially successful site, many props to their programmers. I’m scared to do my next in the series, because I’m 100% sure it won’t be as nice of a read as Flickr was.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/DN9YydR5dr8" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Tips for Programming JavaScript Functions</title>
		<link href="http://www.zachleat.com/web/tips-for-programming-javascript-functions/" />
		<updated>2008-03-28T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/tips-for-programming-javascript-functions</id>
		<content type="html">&lt;p&gt;&lt;em&gt;This article is about my personal coding style, given little tips and tricks that I use to make my code cleaner and more readable.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Required and Optional Arguments&lt;/h2&gt;

&lt;p&gt;There are generally two styles used when programming a new function in JavaScript. The first, most obvious, and least extensible method is putting each argument as its own argument in the function definition, as so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// For our purposes, assume arg1 is required, and arg2 and arg3 are optional.
function myFunction(arg1, arg2, arg3) {
   arg2 = arg2 || 'defaultValue';
   arg3 = arg3 || 'defaultValue';
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;One obvious downside to this method is that it requires a line of code for each optional argument to define a default value. What if you want to pass in an arg3, but not an arg2? Your call could end up like: &lt;code&gt;myFunction('myArg1', null, 'myArg3');&lt;/code&gt;. This might work in the beginning, but what about when you have more than 3 arguments defined? That’s going to get messier than a Dick Cheney hunting party.&lt;/p&gt;

&lt;p&gt;The next method people generally move to when they have a lot of optional arguments in their function definition is to put all the arguments into a single object argument, like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// taken from jQuery
 $.ajax({
   type: "POST",
   url: "some.php",
   data: "name=John&amp;amp;location=Boston",
   success: function(msg){}
 });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The benefit to this method is that you can populate all the defaults easily by using jQuery.extend, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// simulated code, not from jQuery
$.ajax = function(args)
{
    var defaultArgs = {
        type: 'GET',
        data: '',
        dataType: 'text'
    };
    // overwrites defaultArgs with args values, stores result into args.
    args = jQuery.extend({}, defaultArgs, args);
    if(!args['url']) {
          return;
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The args object would end up with the following value:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
   type: "POST",
   url: "some.php",
   data: "name=John&amp;amp;location=Boston",
   success: function(msg){},
   dataType: 'text'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This method can be easily seen as extensible. You could put a metric shit ton of optional arguments in your function (the option is there, I won’t judge you), and you could define them in any order inside of the object without having to put in null spacers like the previous method.&lt;/p&gt;

&lt;p&gt;But what about required arguments? The Ajax method above requires a URL, and the script can’t guess a default for that variable. But it isn’t immediately obvious to the end-user that URL is always required. And what’s more, you’ll have to put specific code inside your function to check that the required arguments were sent in the object. (Think &lt;code&gt;if(!args['url']) { return; }&lt;/code&gt; as shown two code blocks up.)&lt;/p&gt;

&lt;p&gt;Which leads me to my favorite way to define functions: a combination of the two methods. Declare your required arguments as explicit arguments, and pile the rest into an optional arguments object. Here I’ll show you how I would define the Ajax function using this method:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// jQuery doesn't use this argument structure, so don't copy and paste this.
 $.ajax('some.php', {
   type: "POST",
   data: "name=John&amp;amp;location=Boston",
   success: function(msg){}
 });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This way, it is immediately obvious which is a required argument and which is optional, and your required arguments will never be accidentally assigned a default value in your code. If the end-user doesn’t send in all of the required arguments, the resulting error message will be obvious and easily fixed, without a ton of code inside of your function to check that the end-user obeyed the function defintion.&lt;/p&gt;

&lt;h2&gt;Setting Default Values for Optional Arguments&lt;/h2&gt;

&lt;p&gt;When developing code, sometimes it is obvious that the method described above for optional arguments may be overkill for a tiny little utility method. Sometimes you just want a boolean flag, or a single optional argument. When that occassion arrives, it’s time to put on your robe and coding hat, because we’re going to town.&lt;/p&gt;

&lt;p&gt;In the beginning of JavaScript maturity, my &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; was going through a lot of changes. I was confused about a lot of things, and you’d see a lot of lines of code like this (embarrassingly enough):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function myFunction(runDoSomething)
{
     if(runDoSomething == null) {
          // never make your default true, as I'll show you below
          runDoSomething = true;
     }
     if(runDoSomething) {
          doSomething();
     }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ugh, checking against null? Janet Reno looked better in the morning. But now that I’m a full grown man that can open his own pickle jars, I’ve got some guidelines:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;When the argument is optional and might be left out, define it in your code in such a way that if it does have a value, it will not evaluate to boolean false (0, false, undefined, null, ”, NaN). In other words, don’t make the value the user passes in for this argument be false. False is the value it should have when it’s empty. See the example below:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// runDoSomething is still optional
function myFunction(runDoSomething)
{
     if(runDoSomething) {
          doSomething();
     }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We didn’t have to assign a default value to arg1, because if it’s &lt;code&gt;null&lt;/code&gt;, then &lt;code&gt;doSomething()&lt;/code&gt; won’t execute. Don’t ever use arg1 in a way that would have you passing in false, because false and null are the same in a boolean comparison.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When using non-boolean optional arguments, another way to avoid assigning a default value to an optional argument is to use the OR operator to give you a default value where you’re using it. This is really only useful when you use the argument in one single place inside of your function. If you’re using it more than once, it’s best to define the default value at the top of the function.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; function myFunction(arg1)
 {
      // arg1 is used only once
      jQuery('#myId').html(arg1 || 'myDefaultValue');
 }
 function myFunction(arg1)
 {
      arg1 = arg1 || 'myDefaultValue;
      // arg1 is used multiple times
      jQuery('#myId').html(arg1);
      jQuery('#myOtherId').html(arg1);
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Hopefully you’ve learned something from this post. It is the byproduct of many mistakes and overcomplicated functions that I’ve refactored to end up with this result.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/3Cw_eAK2m8M" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Architecture Choices: Callbacks and Events in JavaScript</title>
		<link href="http://www.zachleat.com/web/architecture-choices-callbacks-and-events-in-javascript/" />
		<updated>2008-03-28T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/architecture-choices-callbacks-and-events-in-javascript</id>
		<content type="html">&lt;p&gt;&lt;em&gt;Warning: Blog Post written for Beginner and Intermediate JavaScript Developers&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Like any well intentioned programmer, you’re writing reusable code in JavaScript. Maybe it’s a simple widget, maybe it’s a higher level plug-in for your favorite JavaScript library. But now you want to provide a mechanism for your friendly neighborhood developer to extend your code by hooking into it with a little bit of code of their own. How do you accomplish this?&lt;/p&gt;

&lt;p&gt;Generally, it can be done one of two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A callback function&lt;/li&gt;
&lt;li&gt;A custom event&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;A callback function is a function passed into your code as an argument that will be executed at the time the library code specifies. For instance, callback functions are usually supplied for for Ajax XmlHttpRequest’s to execute, one callback if the Ajax Request is successful, and another on failure. See the following code as an example:&lt;/p&gt;

&lt;p&gt;End-Developer’s Code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; $.ajax({
   type: "POST",
   url: "some.php",
   data: "name=John&amp;amp;location=Boston",
   success: function(msg){
     alert( "Data Saved: " + msg );
   }
 });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Library Code (from jQuery):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// taken out of context, just know that s stands for the options object passed into $.ajax() above.
if ( s.success )
  s.success( data, status );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the above code example taken straight from the &lt;a href="http://docs.jquery.com/Ajax/jQuery.ajax#options"&gt;jQuery documentation&lt;/a&gt;, the success key of the object being passed into the ajax() function is a callback function. It will be executed after the Ajax request has successfully completed.&lt;/p&gt;

&lt;p&gt;The other mechanism you can use for controlling dependent function execution is a custom event. Custom events provide more flexability because they use the publish/subscribe mechanism. That means, instead of the library author deciding how many callbacks he or she is going to allow you to pass into their method as arguments, he or she will just trigger a custom event, which will fire all functions the end-developer has said they want to subscribe to that event. See the following example from the jQuery documentation.&lt;/p&gt;

&lt;p&gt;End-Developer’s Code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$(document).bind("myCustomEvent", function(e, msg){
   alert( "Data Saved: " + msg );
});
$(document).bind("myCustomEvent", function(e, msg){
   alert( "More Data Saved: " + msg );
});
// We can subscribe as many functions as we want to myCustomEvent.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Library Code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// again, no context here
$(document).trigger("myCustomEvent", [ "My Message" ]);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see above, custom events are much more extensible and customizable to your needs. Want to attach 10 functions to myCustomEvent? Sure, go right ahead. Want to try to attach 10 callbacks to the ajax success method above, that’s going to be a bit more work. The benefit to using callbacks lies in their disposability and isolation. Perhaps you don’t want to publish to the world when your Ajax Request completes — maybe you just want to handle the completion and be done with it.&lt;/p&gt;

&lt;p&gt;Let’s Review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Callback Functions&lt;/strong&gt;: Private Disposable – Limited by Design of Parent Code (Number of callbacks)&lt;br/&gt;
&lt;strong&gt;Custom Events&lt;/strong&gt;: Extensible (Any number of functions attached) – Public – Not Disposable (Functions stay attached after execution, and continue to fire when triggered)&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/GXAarzgFx78" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Yet Another Pretty Date JavaScript</title>
		<link href="http://www.zachleat.com/web/yet-another-pretty-date-javascript/" />
		<updated>2008-03-23T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/yet-another-pretty-date-javascript</id>
		<content type="html">&lt;p&gt;I can’t let this Pretty Date thing go. I decided to use a modification of &lt;a href="http://ejohn.org/blog/javascript-pretty-date/"&gt;John Resig’s Pretty Date JavaScript implementation&lt;/a&gt; written by Dean Landolt and shared in the comments on John’s page. The script was an obvious choice for the next iteration of &lt;a href="http://www.zachleat.com/web/2007/06/18/wake-up-to-youtube-on-my-internet-alarm-clock/"&gt;Alarmd&lt;/a&gt;, which is nearing completion as I type.&lt;/p&gt;

&lt;p&gt;The more I used &lt;a href="http://deanlandolt.com/archives/163"&gt;Dean Landolt’s script&lt;/a&gt;, the more problems I began to see with his implementation. It was a good start, but definitely had bugs. His assumptions translating from integer second differences to human readable labels stretched too far at times (there is an error in logic to say anything between 24 hours and 48 hours from now can be labeled “Tomorrow”), and he was a bit loose with his difference categories (assumed average month length was 28 days, and always used Math.floor instead of rounding — 47 hours from now would be labeled “1 Day”). It was great code otherwise, and I definitely liked the way he used the while loop to run through the comparisons.&lt;/p&gt;

&lt;p&gt;So, I’ve cleaned up his great start, and am releasing it to the world in the spirit of cooperation and open sauce. You just read that typo out loud didn’t you?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Download&lt;/strong&gt;: &lt;a href="http://www.zachleat.com/Lib/jquery/humane.js"&gt;Yet Another Pretty Date Implementation&lt;/a&gt; (2 KB)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Dates for this script must have a specific &lt;a href="http://en.wikipedia.org/wiki/ISO_8601"&gt;ISO8601 format&lt;/a&gt;: &lt;em&gt;YYYY-MM-DDTHH:MM:SSZ&lt;/em&gt; (in UTC) where T and Z are literals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: This script has been moved to &lt;a href="http://github.com/zachleat/Humane-Dates"&gt;Github&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/-Z7h535-pVA" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Minor Annoyances with Firefox Development</title>
		<link href="http://www.zachleat.com/web/minor-annoyances-with-firefox-development/" />
		<updated>2008-03-23T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/minor-annoyances-with-firefox-development</id>
		<content type="html">&lt;p&gt;When you’re developing web applications in Firefox, do you find yourself constantly clearing your cache? Cache is a useful facet of web browsing for everything but the continuous testing environment of web development. Here’s a nice alternative so that you don’t have to disable your cache entirely:&lt;/p&gt;

&lt;p&gt;Use the Firefox Plug-In called (humorously enough) &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/3817"&gt;&lt;strong&gt;JohnnyCache&lt;/strong&gt;&lt;/a&gt;. I added the pattern ‘http://localhost/’ to my preferences and now I don’t have to worry about cache on my local machine anymore. Simple, easy, effective.&lt;/p&gt;

&lt;p&gt;Now only if I knew how to disable the Firefox preference that autopopulates form fields with default values when F5 is hit to refresh the page. Try creating a page with a single text field, type a value into the form, and then hit F5 to refresh the page. Your value will be prefilled into the form.&lt;/p&gt;

&lt;p&gt;I find myself always hitting “CTRL L” (goes to the Location Bar) and “Enter” to avoid that one. I looked through about:config, but only found: signon.prefillForms (related to usernames and passwords), and browser.formfill.enable (related to autocomplete dropdowns for forms, not default values).&lt;/p&gt;

&lt;p&gt;Anyone know an easier method?&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/BBmc1OggC_g" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Specific Inheritance with TIBCO’s General Interface</title>
		<link href="http://www.zachleat.com/web/specific-inheritance-with-tibcos-general-interface/" />
		<updated>2008-03-03T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/specific-inheritance-with-tibcos-general-interface</id>
		<content type="html">&lt;p&gt;&lt;em&gt;Sorry about the title, I couldn’t resist.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;TIBCO created the General Interface (GI) toolkit for one-page in-browser applications back before I was in my JavaScript diapers. I hadn’t even graduated from high school yet when they were building Rich Internet Applications using some of the most feature crippled browsers in Internet history, back when cross browser meant Internet Explorer and Netscape Navigator, not the Firefox/WebKit/Opera’s of today. But when I did finally start to get my feet wet in the world of JavaScript, this is the tool I started on. I learned what a DOM was, earned my stripes in XSL, and discovered the power of the browser.&lt;/p&gt;

&lt;p&gt;But just like any programmer nearing the end of their relationship with a tool, I must take a few moments to evaluate my experiences with it, not only for my benefit, but so that you, the reader, might also gain a golden nugget of wisdom from the treasure troves of its sparkling source code.&lt;/p&gt;

&lt;p&gt;When I first started using General Interface almost two years ago (~June 2006) on version 3.1, it wasn’t a cross browser tool. It had support for Internet Explorer 6, and that was it. Truthfully, it was an executive decision to use the tool, and we were using it for an intranet application. Looking back on that decision raises a huge red flag now — internally supported web browsers are subject to change, and so are audiences — applications may turn out to be more external that previously suggested. And while Firefox support was included with version 3.2, to this day I hear complaints that the application doesn’t work on the Safari browser (or, in turn, the iPhone).&lt;/p&gt;

&lt;p&gt;General Interface relies heavily on a JavaScript XSLT interface (this is why they won’t ever have support for Safari 2, or the iPhone, neither of which support a JavaScript XSLT interface), leveraging XSLT stylesheets to generate markup for the page, which turns out to be quite the speed demon when generating large amounts of markup from XML documents (or GUI components serialized into XML documents). However, a large chunk of that speediness is lost due to a heavy reliance on inline CSS. A majority of the style associated with components is generated on the fly and inserted inline using the browser native style attribute. This can cause a lot of problems when attempting to do a simple restyling of a GUI component using CSS. For example, in a DataTable/Grid component, there is no option to style the background-color of a selected row. The only option for the style of a selected row is a background-image, which I believe resulted from the inline style limitation and the background color already being specified for zebra-stripe row coloring. If you specified the background-color for the selected row, it wouldn’t know which background-color to go back to when the row was unselected, due to an unfortunate avoidance of the CSS class construct.&lt;/p&gt;

&lt;p&gt;Another drawback to General Interface is development of the GUI. I won’t get into it too much, but will just meantion that to create interfaces in GI, you must create your GUI components and layouts using the an in-browser IDE developed using the power of dog food. That’s right, it’s written in GI itself.&lt;/p&gt;

&lt;p&gt;However, General Interface has got it right in some cases. They were (I believe) the first JavaScript library/toolkit to include a mechanism for large result set DataTables/Grids. In fact, their Matrix component (the equivalent of a YUI DataTable, or a Dojo Grid) supports more features that most libraries have even begun to plan for: complete inline editing with great keyboard navigation support, clientside sorting, column reordering, dynamic column hiding and adding, hierarchical tree grids, easy options for pagination caching, as well as 4 different rendering modes (the latest YUI DataTable 2.5.0 just added their first rendering mode, what GI calls “Chunked” rendering). They were the first toolkit to include a very sophisticated client side charting package, with support for more charting types than you’d even want to put into a single demo. They’ve been developing the package with a clearly object oriented methodology in mind, and that can be easily seen in their source code. They have taken the package open source and released it with a BSD license (which is a delight of course, muddling through that obfuscated source the first year was a pain).&lt;/p&gt;

&lt;p&gt;If nothing else, TIBCO is a company with some great ideas, and you can see those ideas represented in General Interface. This tool has shaped a lot of my views on clientside development, and I’ve learned a lot from its developers. For instance, I feel like XSLT is one of the most underrated tools for speed improvements in clientside DOM manipulation (using innerHTML to insert the result of an XSL transform), especially with Safari 3 including a JavaScript XSLT interface. If you’re developing an application that deals a lot with XML web services (SOA) and you want to create a single-page in-browser application (RIA), why not give it a look? Just keep those caveats I’ve meantioned in mind and you’ll be fine. Trying something new can change your perspective, and if you keep an open mind, you might learn something.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/yU6v4iNKSwA" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>PHP Pretty Date</title>
		<link href="http://www.zachleat.com/web/php-pretty-date/" />
		<updated>2008-02-10T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/php-pretty-date</id>
		<content type="html">&lt;p&gt;This class is pretty much a direct port of &lt;a href="http://ejohn.org/blog/javascript-pretty-date/"&gt;John Resig’s JavaScript Pretty Date&lt;/a&gt; to PHP 5. A few notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires PHP &gt;= 5.10, due to the usage of PHP’s new &lt;a href="http://us3.php.net/manual/en/function.date-create.php"&gt;DateTime&lt;/a&gt;class.&lt;/li&gt;
&lt;li&gt;The new DateTime object parses strings using PHP’s &lt;a href="http://us3.php.net/manual/en/function.strtotime.php"&gt;strtotime&lt;/a&gt;, so you don’t need to pass in an ISO8601 formatted date, as in JavaScript Pretty Date. Try “now”, or “next Wednesday”, or “ 2 weeks 4 days 23 hours 9 seconds”.&lt;/li&gt;
&lt;li&gt;Extended to handle Months and Years in the past (JavaScript version only goes to weeks)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Usage:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// pass in a String DateTime, compared to another String DateTime (defaults to now)
$myString = Date_Difference::getStringResolved('-7 weeks');
$myString = Date_Difference::getStringResolved('-7 weeks', '+1 week');

// pass in a DateTime object, compared to another DateTime object (defaults to now)
// useful with the Propel ORM, which uses DateTime objects internally.
$myString = Date_Difference::getString(new DateTime('-7 weeks'));
$myString = Date_Difference::getString(new DateTime('-7 weeks'), new DateTime('+1 week'));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://www.zachleat.com/Projects/phpPrettyDate/Date_Difference.phps"&gt;Download PHP Pretty Date&lt;/a&gt; (PHP 5.10 , 1.86KB)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.zachleat.com/Projects/phpPrettyDate/Date_Difference.phps"&gt;http://www.zachleat.com/Projects/phpPrettyDate/Date_Difference.phps&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/CklLgEUUfIw" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>Quine using XHTML and JavaScript</title>
		<link href="http://www.zachleat.com/web/quine-using-xhtml-and-javascript/" />
		<updated>2007-12-28T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/quine-using-xhtml-and-javascript</id>
		<content type="html">&lt;p&gt;Programming Hilarity! He has a &lt;a href="http://www.xn--kllberg-5wa.net/quine/quinegen.html"&gt;generator&lt;/a&gt;, and a pre-generated &lt;a href="http://xn--kllberg-5wa.net/quine/quine.html"&gt;example&lt;/a&gt;. Wait, what’s a quine, you say?&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;In computing, a quine is a program, a form of metaprogram, that produces its complete source code as its only output.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;– Courtesy of &lt;a href="http://en.wikipedia.org/wiki/Quine_(computing)"&gt;Wikipedia: Quine (computing)&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/V65gMaiCCwo" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Faster YUI DataTable with 5 Lines of Code</title>
		<link href="http://www.zachleat.com/web/faster-yui-datatable-with-5-lines-of-code/" />
		<updated>2007-12-27T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/faster-yui-datatable-with-5-lines-of-code</id>
		<content type="html">&lt;p&gt;Holy Reflows Batman! The typical usage of a DataTable in the Yahoo User Interface JavaScript library involves passing a string into the constructor signifying the ID attribute of the container you want to attach the DataTable to. However, the YUI DataTable loves the DOM and creating nodes individually using DOM methods. Normally that’d be fine, but one of the first things it does in the constructor is create the table element and attach it to the live DOM. This is a no-no. Now, every time they append a new node (for a new row or a new cell inside of a row), it causes a reflow in the browser! What does this mean? Really bad lag when you insert 40 or 50 rows. Recognize this piece of code?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var myDataTable = new YAHOO.widget.DataTable("myContainer", myColumnDefs, myDataSource);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Straight from the docs. No no no!&lt;/p&gt;

&lt;p&gt;Instead, you should pass in an unattached DOM node instead of a string!&lt;/p&gt;

&lt;p&gt;Try this code on for size:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var myDataTable = new YAHOO.widget.DataTable(document.createElement('div'), myColumnDefs, myDataSource); 
myDataTable.subscribe('initEvent',function() {
    // CHANGE THIS -- match the id of the container you want.
    var d = document.getElementById('myContainer');
    // remove previous DataTables
    while(d.firstChild) { d.removeChild(d.firstChild); };
    d.appendChild(this._elContainer); });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/tzP6_hbxbdQ" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>enterval, an automatic setInterval chainer.</title>
		<link href="http://www.zachleat.com/web/enterval-an-automatic-setinterval-chainer/" />
		<updated>2007-12-23T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/enterval-an-automatic-setinterval-chainer</id>
		<content type="html">&lt;p&gt;Hello internet. Today we’ll be exploring the magical wonders of setInterval. Have you ever worked on a project that needed multiple timers going simultaneously? Have you ever wanted to bind all of those timer callbacks into just one timer without restructuring your code manually? Well, being the Curious George that I am, I wanted to know the performance benefits of the grouping callbacks and eliminating unnecessary timers. Here’s the code I used to do it:&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;window.setInterval(function(){ /* Payload! */ }, 100);
window.setInterval(function(){ /* Payload! */ }, 100);
window.setInterval(function(){ /* Payload! */ }, 100); 
// results in three separate timers.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;enterval.set(function(){ /*Payload */ }, 100);
enterval.set(function(){ /*Payload */ }, 100); // combines with the first 100ms interval.
enterval.set(function(){ /*Payload */ }, 100); // combines with the first two 100ms intervals.
// results in one timer, containing all three callbacks.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s the code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var enterval = (function()
{
    var intervals   = {};

    function add(callback, interval)
    {
        var index = 0;
        if(intervals[interval]) {
            index = intervals[interval].length;
            intervals[interval].push(callback);
        } else {
            intervals[interval] = [callback];
            window.setTimeout(call, interval, interval);
        }
        return interval+':'+index;
    }

    function call(interval)
    {
        var d = intervals[interval];
        for(var j=0,k=d.length;j&amp;lt;k ;j++) {
            if(typeof d[j] == 'function' &amp;amp;&amp;amp; d[j]() === false) return;
        }
        window.setTimeout(call, interval, interval);
    }

    return {
        set: function(callback, interval, data)
        {
            return add(callback, interval, data);
        },
        clear: function(id)
        {
            var s = id.split(':');
            delete intervals[s[0]][s[1]];
        }
    };
})();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Unfortunately, in the limited benchmarks that I performed, it didn’t seem to operate all that much differently from recursive setTimeout calls, even with (10ms, 100ms, or 1000ms) intervals and (50, 100, 1000) timers (with the payload doing nothing other than creating a date for benchmarking purposes. This code does get around the oddly performing &lt;a href="http://www.zachleat.com/web/2007/12/23/problems-with-looping-through-windowsetinterval/"&gt;setInterval inside of a loop bug&lt;/a&gt;. There may be some other benefit in ordering the interval callbacks after assignment, but I haven’t included that in the functionality above. Feel free if you wish.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/Oihmmim0gSc" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>Obscurity, Security, and Captcha</title>
		<link href="http://www.zachleat.com/web/obscurity-security-and-captcha/" />
		<updated>2007-11-01T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/obscurity-security-and-captcha</id>
		<content type="html">&lt;p&gt;On Ajaxian recently, there have been a few posts touting new and inventive replacements for the more traditional distorted and discolored “What does this image say?” Captcha gatekeeper for your web form. Of course these are all intended to provide a mechanism to tell the difference between an automated web bot that is spamming your web form and a human being.&lt;/p&gt;

&lt;p&gt;Obviously there are some accessibility issues with Captcha images, in that they are useless to those that are vision impaired. Some sites provide an alternate link to an audio file that speaks a random word that you must then enter into the form.&lt;/p&gt;

&lt;p&gt;One of the easiest ways to implement a Captcha on your site is to use the &lt;a href="http://recaptcha.net/"&gt;reCAPTCHA plugin&lt;/a&gt;. But that’s not what I’m going to talk about here. What I want to talk about is these new methods being introduced.&lt;/p&gt;

&lt;p&gt;The first that was recently linked was &lt;a href="http://ajaxian.com/archives/preventing-spam-with-drag-and-drop"&gt;a method that involved drag and drop&lt;/a&gt; to authenticate the user. Obviously this method is flawed, especially if the automated robot has access to fire JavaScript events. It does nothing but introduce a different door that the spammer may not have seen before. When this method gains any sort of popularity, or if a spammer decides to attack the site implementing this method specifically, it would not be difficult to bypass the Captcha. This is referred to in the computer world as “&lt;a href="http://en.wikipedia.org/wiki/Security_through_obscurity"&gt;Security through Obscurity&lt;/a&gt;“. This is not good practice.&lt;/p&gt;

&lt;p&gt;The next post I read was &lt;a href="http://almaer.com/blog/are-you-human"&gt;regarding an implementation that presented the user with 8 boxes&lt;/a&gt;, with one of those boxes colored differently with an invitation to find and click on the differently colored box. The was implemented by &lt;a href="http://www.passpack.com/info/home/"&gt;Passpack&lt;/a&gt; (a password hosting service — should be focused on security, right?). Correctly me if I’m wrong, but how is this difficult for the Spammer at all? The whole point of a Captcha is to distort the text inside the image so much that the image can’t be read by an &lt;a href="http://en.wikipedia.org/wiki/Optical_character_recognition"&gt;Optical Character Recognition (OCR)&lt;/a&gt; program. Basically, they’ve simplified it down to a one pixel image, which is an infinitely easier optical recognition problem. You don’t even have to recognize characters, you can just see if the pixel is a 1 or a 0. Forgive me for asking, but is that problem NP complete?&lt;/p&gt;

&lt;p&gt;I am all for having more friendly humane methods of Spam Bot detection. Just be wary of the methods you’re using. Are they actually secure, or are they just obscure?&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/I4l2MfSd7a8" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Forward Compatibility and JavaScript</title>
		<link href="http://www.zachleat.com/web/forward-compatibility-and-javascript/" />
		<updated>2007-11-01T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/forward-compatibility-and-javascript</id>
		<content type="html">&lt;p&gt;Many developers (myself included) complain endlessly about the problematic ECMAScript implementation that Internet Explorer uses called JScript. And after reading &lt;a href="http://blogs.msdn.com/dmassy/archive/2006/11/30/vpc-to-run-ie6-and-ie7-on-the-same-machine.aspx"&gt;one such very detailed complaint&lt;/a&gt; in the comments on Dave Massy’s website at MSDN, and reading &lt;a href="http://blogs.msdn.com/ie/archive/2007/10/30/ecmascript-3-and-beyond.aspx"&gt;Chris Wilson’s post about ECMAScript 3&lt;/a&gt;, it has become increasingly obvious of Microsoft’s opinion on the subject of Forward Compatibility with JavaScript. It’s something they keep pounding their fists on the ground about, how they are adamant that new versions of their browser not “Break the Web.”&lt;/p&gt;

&lt;p&gt;Of course, “Breaking the Web” refers to the amount of code on the internet today that is an equal and opposite reaction to the broken bug-ridden JavaScript implementation of their browser. It describes the unimaginable future in which Internet Explorer fixed the many well documented &lt;em&gt;intricacies&lt;/em&gt; of JScript and thereby ruins the code that was originally written to support the problem. What a conundrum.&lt;/p&gt;

&lt;p&gt;But haven’t we already been through this problem? Isn’t this the same exact thing we saw in the early days of CSS? And how did the major browser players react? By implementing both a &lt;a href="http://www.quirksmode.org/css/quirksmode.html"&gt;Quirks and Standards mode for CSS through DocType switching&lt;/a&gt;. Now my question is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why haven’t we seen a Quirks and Standards Compatibility Mode for JavaScript?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m not necessarily encouraging the Quirks and Standards modes to be toggled with the DocType (as with CSS), but why not have these two modes? To enable your site to use the Standards mode of JavaScript, the browser might require a certain DocType to be declared, or it might require a different script type in the browser:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;script type="text/javascript" mode="standards"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Either that, or &lt;a href="http://dean.edwards.name/weblog/2007/03/yet-another/"&gt;I could just use Base2&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/LT1BOwP_L-k" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Nursery Rhyme Code Poem [CSS]</title>
		<link href="http://www.zachleat.com/web/nursery-rhyme-code-poem-css/" />
		<updated>2007-10-27T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/nursery-rhyme-code-poem-css</id>
		<content type="html">&lt;p&gt;Code Poems are fun! The trick is to take a &lt;a href="http://en.wikipedia.org/wiki/List_of_nursery_rhymes_in_English"&gt;nursery rhyme&lt;/a&gt; (but really, it could be any commonplace work of writing – Famous Speeches, Bible Verses, Famous Quotes, etc.), and then turn it into pseudocode. The code must follow both the programming or markup language you’re using and the rhyme as closely as possible. See how precise you can make your rhyme fit. I accept critiques and suggestions for improving me rhyme code (or you could just rewrite my rhyme as you see fit).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#theChurch {}
#theChurch #theSteeple {}
#theChurch .door[state="open"] .people { visibility: visible; }
#theChurch #theParson { display: none; }
#theChurch &amp;gt; .upstairs #theParson:active { display: block; }
#theChurch #theParson:lang(prayers) { display: block; }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;The above code poem is released under the BSD license.&lt;/em&gt; To use in production environment without error, do not include an element with an id attribute of “theChurch”. Obviously I’m kidding, don’t use this code. Not even for enterprise software.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/_fUfQyOYEak" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Nursery Rhyme Code Poem [PHP]</title>
		<link href="http://www.zachleat.com/web/nursery-rhyme-design-patterns-php/" />
		<updated>2007-10-26T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/nursery-rhyme-design-patterns-php</id>
		<content type="html">&lt;pre&gt;&lt;code&gt;&amp;lt;?php
class I {
    public __construct()
    {
        $star = new Star();
        $star-&amp;gt;size = 'little';
        $star-&amp;gt;twinkle();
        $star-&amp;gt;twinkle();

        self::wonder($star, 'What are you?');

        $world = new World();
        $world-&amp;gt;elevation = 'So High';
        $star-&amp;gt;setAbove($world);

        $d = new Diamond();
        $d-&amp;gt;position = 'In the sky';
        $star-&amp;gt;setLike($d);

        $star-&amp;gt;twinkle();
        $star-&amp;gt;twinkle();
        $star-&amp;gt;size; // returns 'little'

        self::wonder($star, 'What are you?');
    }

    public static function wonder($obj, $query)
    {
        $obj-&amp;gt;query($query);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;The above &lt;strong&gt;code poem&lt;/strong&gt; is released under the BSD license.&lt;/em&gt; To use in production environment without error, please precede with the following command: &lt;code&gt;error_reporting(0);&lt;/code&gt; Obviously I’m kidding, don’t use this code. Not even for enterprise software.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/ylUty9q8W3U" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Nursery Rhyme Code Poem [JavaScript]</title>
		<link href="http://www.zachleat.com/web/nursery-rhyme-code-poem-js/" />
		<updated>2007-10-26T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/nursery-rhyme-code-poem-js</id>
		<content type="html">&lt;pre&gt;&lt;code&gt;(function()
{
    function BlindMouse() {}
    BlindMouse.prototype.tail = true;
    BlindMouse.prototype.run = function(after) {};

    function Mice(mouse1, mouse2, mouse3)
    {
        this.mice = [];
        this.mice.push(mouse1, mouse2, mouse3);
        this.declare = function()
        {
            return this.mice.length + ' Blind Mice';
        };
        this.run = function(after)
        {
            for(var j=0,k=this.mice.length;j&amp;lt;k ;j++) {
                this.mice[j].run(after);
            }
        };
        this.cutOff = function(prop, weapon)
        {
            for(var j=0,k=this.mice.length;j&amp;lt;k;j++) {
                this.mice[j][prop] = false;
            }
        };
    }

    var mice = new Mice(new BlindMouse(), new BlindMouse(), new BlindMouse());
    alert(mice.declare());
    alert(mice.declare());

    function seeHow(they, func)
    {
        they[func]();
    }

    seeHow(mice, 'run');
    seeHow(mice, 'run');

    var farmersWife = function()
    {
        var weapon = 'Carving Knife';
        return {
            cutOff: function(creatures, prop)
            {
                creatures.cutOff('tail', weapon);
            }
        }
    }();

    mice.run(farmersWife);

    farmersWife.cutOff(mice, 'tail');

    function haveYouSeen(obj, timeSpan)
    {
        return true;
    }

    if(haveYouSeen('Such a Thing', 'Your Life')) {
        alert('as ' + mice.declare() + '?');
    }
}());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;The above &lt;strong&gt;code poem&lt;/strong&gt; is released under the BSD license. To use in production environment without error, please enclose with a try-catch block. Obviously I’m kidding, don’t use this code. Not even for enterprise software.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/sH-ZKv1MvYg" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	
	
	<entry>
		<title>Namespacing outside of the YAHOO Namespace</title>
		<link href="http://www.zachleat.com/web/namespacing-outside-of-the-yahoo-namespace/" />
		<updated>2007-08-28T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/namespacing-outside-of-the-yahoo-namespace</id>
		<content type="html">&lt;p&gt;YAHOO.namespace(). A lovely little utility function subject that &lt;a href="http://www.zachleat.com/web/2007/08/09/yui-code-review-yahoonamespace/"&gt;I’ve written about before&lt;/a&gt;. If you’ve never heard of YAHOO.namespace or aren’t even familiar with namespacing, I’d read that article first.&lt;/p&gt;

&lt;p&gt;I’ll be honest, using the YAHOO namespace to store my own code makes my bunghole tighten just a little bit. What if I had written code stored under YAHOO.tool, which was unused prior to YUI 2.3.0? What would I do now? I’d have to rewrite my code, or never include any of the wonderful &lt;code&gt;YAHOO.tool.TestCase&lt;/code&gt;, put together by &lt;a href="http://www.nczonline.net/"&gt;Nicholas Zakas&lt;/a&gt;. As is traditional with most of my weblog posts, I try not to just complain about a problem without giving you a solution (but let’s be honest, only if it doesn’t take too much work).&lt;/p&gt;

&lt;p&gt;Let’s rewrite the YAHOO.namespace function to work outside of the YAHOO Namespace, so we can do things like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namespace( 'zachsWorld.partyTime' );
zachsWorld.partyTime = function() {
  alert( 'Excellent.' );
}
zachsWorld.partyTime(); // obviously would alert: Excellent.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s some code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function namespace() {
    var a=arguments, o=null, i, j, d;
    for (i=0; i&amp;lt;a.length; i=i+1) {
        d=a[i].split(".");
        o=window;
        for (j=0; j&amp;lt;d.length; j=j+1) {
            o[d[j]]=o[d[j]] || {};
            o=o[d[j]];
        }
    }
    return o;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Obviously this is just a modification of the YAHOO.namespace function. I’d recommend putting this under your own namespace (I’m trying to put most of the code I write on this website under the Y2 namespace, but everyone should have their own parent namespace), like so (any namespaces you create using this function won’t use the parent namespace assigned here by default):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if (typeof Y2 == "undefined") {
    var Y2 = {};
}
Y2.namespace = function() { /* copy function contents from above. */ };
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But you can do whatever you want. This is one of the functions that I think separates YUI from the other frameworks out there, giving an easy utility to organize your code. This is something I think jQuery seriously lacks, noting from the code inside the many jQuery plugins contributed by end users. Many jQuery contributors do not organize their code, putting multiple unnecessary top level functions into jQuery.fn as methods, or into the jQuery object itself as functions. People whine about polluting the global namespace… I suppose it might be considered nitpickey to whine about the jQuery namespace. Okay you whiney bastard, let’s help out and put this into jQuery!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// include jQuery first.
jQuery.namespace = function() {
    var a=arguments, o=null, i, j, d;
    for (i=0; i&amp;lt;a.length; i=i+1) {
        d=a[i].split(".");
        o=window;
        for (j=0; j&amp;lt;d.length; j=j+1) {
            o[d[j]]=o[d[j]] || {};
            o=o[d[j]];
        }
    }
    return o;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Please note, this method does NOT work using jQuery methods with an element context, such as jQuery(‘div’).myNamespace.myMethod(). Your element context won’t be carried through to myMethod().&lt;/p&gt;

&lt;p&gt;However, you can use it for jQuery functions, such as this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// definition
jQuery.namespace( 'jQuery.debug' );
jQuery.debug.test1 = function()
{
    alert( 'test1 function' );
};
jQuery.debug.test2 = function()
{
    alert( 'test2 function' );
};
// usage
jQuery.debug.test1();
jQuery.debug.test2();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For more information, you can read &lt;a href="http://yuiblog.com/blog/2006/06/01/global-domination/"&gt;Global Domination&lt;/a&gt;, an article written by Douglas Crockford, or &lt;a href="http://docs.jquery.com/Plugins/Authoring"&gt;Best Practices for Writing jQuery plugins&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Updated&lt;/strong&gt;: fixed some weird source parsing errors introduced by the code formatting plugin.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/reul28hUUtI" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>ALARMd now supports URLs</title>
		<link href="http://www.zachleat.com/web/alarmd-now-supports-urls/" />
		<updated>2007-08-21T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/alarmd-now-supports-urls</id>
		<content type="html">&lt;p&gt;When you add an alarm source to &lt;a href="http://www.zachleat.com/Projects/alarmd/"&gt;ALARMd, the Internet Alarm Clock&lt;/a&gt;, it will now default to opening the input URL in a new window, if the URL is determined not to be an MP3, Youtube video, or a LAST.FM user or tag.&lt;/p&gt;

&lt;p&gt;I added this to use &lt;a href="http://www.zachleat.com/Projects/Malarquee/"&gt;maLArquee&lt;/a&gt; as an alarm. For instance you can try adding this one to your ALARMd for a nice wake up message.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.zachleat.com/Projects/Malarquee/index.html?text=Jnxr%2520hc!!!"&gt;http://www.zachleat.com/Projects/Malarquee/index.html?text=Jnxr%2520hc!!!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course the obvious downfall of this approach is that your target website would need sound if you wanted to actually use it to wake up. But you could also use it to open up a new window at a specific time to prank a friend, coworker, or loved one. Try setting up ALARMd to use a naked lady website as a target url on your coworkers computer and set the time for right after lunch! Or open ALARMd up on your colleague’s computer and get it to open a competitor’s website during a big presentation to the company president.&lt;/p&gt;

&lt;p&gt;Fun to be had by all, I’m sure.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/gF1_EzcbfCc" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>maLArquee, Bringing Back the Marquee</title>
		<link href="http://www.zachleat.com/web/malarquee-bringing-back-the-marquee/" />
		<updated>2007-08-20T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/malarquee-bringing-back-the-marquee</id>
		<content type="html">&lt;p&gt;What did you spend your Saturday afternoon on? Did you kick up your feet in your hammock with a nice glass of lemonade in the shade of your favorite tree and read the HTML specification? Me too! Who knew that we’d have so much in common? Since you’re obviously like me, you’ve probably wondered to yourself: where did the marquee tag go? Why isn’t the internet graced with scrolling text gently flowing like a babbling brook across the pixels of your web browser? Well since you spent your Saturday reading the HTML specifications, you would know that the &lt;code&gt;tag was only supported by Internet Explorer, and wasn’t even a part of the HTML spec. Unbelievable right? And to think the&lt;/code&gt; tag I came to know and love wasn’t part of the spec either! I’m just offended as you, let me reassure you.&lt;/p&gt;

&lt;p&gt;Well today, we’re going to solve all of that. Today, I’m going to show you a full screen web browser marquee that will both amaze and excite you. Here we go:&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://www.zachleat.com/Projects/Malarquee"&gt;Malarquee&lt;/a&gt;&lt;/h2&gt;

&lt;div class="fluid-width-video-wrapper"&gt;&lt;object width="425" height="350"&gt;param name="movie" value="http://www.youtube.com/v/9OiF8Hd6Db0"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/9OiF8Hd6Db0" type="application/x-shockwave-flash" width="425" height="350"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;


&lt;h2&gt;What is it for?&lt;/h2&gt;

&lt;p&gt;There are a few obvious uses, I suppose. You can send someone a nice greeting in an email link (it does a ROT13 encoding to mask the text inside the link). Try one of these:&lt;/p&gt;

&lt;p&gt;For a spouse: &lt;a href="http://www.zachleat.com/Projects/Malarquee/index.html?text=V%20jnag%20n%20qvibepr."&gt;I want a divorce.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For an employee: &lt;a href="http://www.zachleat.com/Projects/Malarquee/index.html?text=Lbh'er%20sverq."&gt;You’re fired.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a doctor: &lt;a href="http://www.zachleat.com/Projects/Malarquee/index.html?text=V'z%20fbeel%7Cohg%20lbh%20unir%7Cnany%20jnegf."&gt;I’m sorry but you have anal warts.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For your son or daughter: &lt;a href="http://www.zachleat.com/Projects/Malarquee/index.html?text=Lbh%20jrer%20nqbcgrq."&gt;You were adopted.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;So, what else does it do?&lt;/h2&gt;

&lt;p&gt;I knew you’d ask. If you click the Options link in the top right corner, you can scroll your text across &lt;strong&gt;multiple web clients&lt;/strong&gt;! Input the number of clients you’d like to use and the number of your current client. Hit the update and save button to refresh your page. It will automatically parse your text accordingly (adding extra spaces at the end as blank slides if needed). You can test this using one computer by bringing up the following two links in separate windows side by side (you can use a different web browser for each link if you’d like):&lt;/p&gt;

&lt;p&gt;&lt;a href="/Projects/Malarquee/index.html?c=1&amp;amp;n=2"&gt;maLArquee Client #1&lt;/a&gt;&lt;br/&gt;
&lt;a href="/Projects/Malarquee/index.html?c=2&amp;amp;n=2"&gt;maLArquee Client #2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You could also go into a computer lab and scroll some text on a couple different computers.&lt;/p&gt;

&lt;h2&gt;Why?&lt;/h2&gt;

&lt;p&gt;I think it’s fun to try new things on the web, experiment a bit. That’s also why I made &lt;a href="http://www.zachleat.com/web/2007/06/18/wake-up-to-youtube-on-my-internet-alarm-clock/"&gt;ALARMd, an Internet Alarm Clock&lt;/a&gt;. For this project, I think it might be fun to try a new JavaScript library, just to get a little bit more experience with a range of different coding types. So I decided to use &lt;a href="http://www.mootools.net/"&gt;MooTools&lt;/a&gt;, and wrote &lt;a href="http://www.zachleat.com/web/2007/07/22/what-sound-does-a-cow-make-mootools/"&gt;a little review&lt;/a&gt; on my experience, coming from a YUI and jQuery background.&lt;/p&gt;

&lt;h2&gt;How does it work?&lt;/h2&gt;

&lt;p&gt;Every 5 scrolls (I reserve the right to change this number at any time I so wish to conserve bandwidth), the page makes an XmlHttpRequest to the server, gets the server time, and adjusts the delay of the next scroll event to synchronize scrolling between multiple browsers. Ideally, if every computer were the same, we could just do a single XmlHttpRequest at page load and do a standard interval for scrolling. But we all know that every web browser is different, and just because you do a setInterval(yourFunction,1000) doesn’t mean it’s actually going to run yourFunction every second. It might run in 1010 ms or 990 ms. Thus, the XmlHttpRequest is needed to resynchronize all of the clients to a standard clock.&lt;/p&gt;

&lt;p&gt;If there is any interest, I’ll post the code to the time.php script that returns the JSON containing the server time.&lt;/p&gt;

&lt;h2&gt;What would you do different next time?&lt;/h2&gt;

&lt;p&gt;I told my gracious web host about this project after I was approximately 90% complete with it, and his response was: “Did you use NTP?”, with which I replied: “What is NTP?” Ugh. There is even a &lt;a href="http://jehiah.cz/archive/ntp-for-javascript"&gt;JavaScript implementation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In order to provide balance and order to the universe, please read &lt;a href="http://www.mcli.dist.maricopa.edu/tut/tut17.html"&gt;the following link&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/wlqiGuE4fRs" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>YUI Code Review: YAHOO.namespace</title>
		<link href="http://www.zachleat.com/web/yui-code-review-yahoonamespace/" />
		<updated>2007-08-09T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/yui-code-review-yahoonamespace</id>
		<content type="html">&lt;p&gt;&lt;em&gt;This is the first in a one part series of posts (the is optional) reviewing the actual code contained in the YUI library. This series is not intended for advanced JavaScripters, so if you’re insulted by reading things you already know, you probably aren’t a very good student.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;YAHOO.namespace. This is a great little utility function that gives you an easy way to encourage low coupling throughout your JavaScript code. Divide your functions into functional units! If you already know how to use this function, you can skip to the bottom to learn a few JavaScript tricks Yahoo has put in. If not, keep reading! Are you making a new package you want to put under the YAHOO namespace? Just declare it in a string argument passed into the YAHOO.namespace function:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;YAHOO.namespace( 'myNamespace' );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will create a YAHOO.myNamespace object that can be used many different ways. You can assign a single function to it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;YAHOO.myNamespace = function() {};

YAHOO.myNamespace();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or you can assign multiple functions to it (with private variables included) using the &lt;a href="http://yuiblog.com/blog/2007/06/12/module-pattern/"&gt;amazing Module Pattern&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;YAHOO.myNamespace = function() {
  var myPrivateVariable;

  return {
    myFirstFunction: function() { return myPrivateVariable; },
    mySecondFunction: function() {}
  }
}();

var hisOrHerPrivateVariable = YAHOO.myNamespace.myFirstFunction();
YAHOO.myNamespace.mySecondFunction();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Did you know that you can pass multiple arguments into YAHOO.namespace? I’ve been using YUI all this time and didn’t know about this feature. But the more I think about it, the more I doubt it’s usefulness. When are you going to declare two unrelated namespaces adjacently in code? For example, doing this is redundant in YUI:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;YAHOO.namespace( 'myNamespace' );
YAHOO.namespace( 'myNamespace.myNestedNamespace' );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The second call to YAHOO.namespace will reuse ‘myNamespace’ if it exists, and create it if it doesn’t. But the point here is that you can do something like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;YAHOO.namespace( 'myNamespace', 'myOtherNamespace' );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which will create YAHOO.myNamespace and YAHOO.myOtherNamespace, and return a reference to the last one created, in this case YAHOO.myOtherNamespace.&lt;/p&gt;

&lt;p&gt;Here’s the code from this nice little function:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;YAHOO.namespace = function() {
    var a=arguments, o=null, i, j, d;
    for (i=0; i&amp;lt;a .length; i=i+1) {
        d=a[i].split(".");
        o=YAHOO;

        // YAHOO is implied, so it is ignored if it is included
        for (j=(d[0] == "YAHOO") ? 1 : 0; j&amp;lt;d.length; j=j+1) {
            o[d[j]]=o[d[j]] || {};
            o=o[d[j]];
        }
    }

    return o;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;var a=arguments&lt;/code&gt;: They’re iterating over the arguments passed into the function to declare multiple simultaneously. Arguments is the variable passed into every function that you can use if you want to handle a variable number of arguments. You can also declare a few arguments in the function( myArg ) and use the arguments variable if you want.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;j=(d[0] == "YAHOO") ? 1 : 0&lt;/code&gt; They reuse the YAHOO top level object if not explicitly included into the declaration. Start the index at 1 if YAHOO was declared to skip defining it twice.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;o[d[j]]=o[d[j]] || {};&lt;/code&gt; They reuse existing namespaces if they have already been created. The OR || declaration means that Javascript will use {} (an empty object) if &lt;code&gt;o[d[j]]&lt;/code&gt; is undefined.&lt;/li&gt;
&lt;/ol&gt;

&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/vtxuukdA89E" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	
	
	<entry>
		<title>What Sound Does a Cow Make?  MooTools.</title>
		<link href="http://www.zachleat.com/web/what-sound-does-a-cow-make-mootools/" />
		<updated>2007-07-22T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/what-sound-does-a-cow-make-mootools</id>
		<content type="html">&lt;p&gt;Frameworks, Frameworks everywhere. There are the big six: Dojo, jQuery, prototype/scriptaculous, Ext, Mootools, and YUI. (Honorable meantion to Open Rico and Mochikit) I’ve had limited experience with all of these frameworks, but have actually worked on projects involving YUI and jQuery. So when I was shopping around for a framework that I didn’t have extensive experience with for my next project, I decided to with Mootools. They’ve been getting a lot of traffic lately for posting their &lt;a href="http://mootools.net/slickspeed/"&gt;SlickSpeed Selectors Test&lt;/a&gt;, so I figured why not try their wares.&lt;/p&gt;

&lt;p&gt;Originally coming from the YUI Library (a strictly namespaced, well organized package), and then learning jQuery (a language with object chaining, a more object oriented approach, and a much larger community), the Mootools package definitely caught me off guard.&lt;/p&gt;

&lt;p&gt;My first surprise was that it put functions EVERYWHERE! The Core file puts approximately ten functions in the global namespace, with the only indicator that they belong to Mootools being that they had a dollar sign prefix (e.g. $extend). Couldn’t these go into one global Mootools object? $E, $ES? These are given shortcuts with the normal $ and $$ functions. It just seems all over the place.&lt;/p&gt;

&lt;p&gt;That being said, there is a lot of good functionality in the base Mootools distribution. A built in class to do Json communication (something YUI is lacking, although I’m sure it wouldn’t be too hard to port it in from Captain Crockford’s Code on his website), a class to Scroll to elements with nice transitions. It seems like everytime I would hit a “functional” snag in my project, I could find the exact code I needed already included in the core file.&lt;/p&gt;

&lt;p&gt;I love their download page! Autopackaged code using Dean Edwards’ Packer. One small complaint is that there is no option to disable automatic include of dependencies. They want you to package Mootools into one single file everytime (which is unwieldy, considering I have to maintain my own text file of which packages I put into the source code, if I don’t want everything), and don’t let you download just a certain package for separate inclusion. But when the whole thing weighs in at 40KB, why does it even matter? I would recommend just downloading all the Components together and just not worrying about it.&lt;/p&gt;

&lt;p&gt;All in all, I’m quite happy with my Mootools experience. I’ve definitely found that their SmoothScroll class and easy Color fading techniques are used pretty heavily by developers using Mootools, which gives you a sixth sense that the page you’re viewing is using the Mootools library. Sometimes I can just tell without even looking at the source files, which in this case is a good thing, given that we’re talking about animation techniques and not raw widget style. But I plan on writing more about my pet peeves with framework widget styles later on.&lt;/p&gt;

&lt;p&gt;If you’ve been using one framework for a really long time, I would recommend checking out Mootools. Or any other framework. The more frameworks that you’ve tried, the better your perspective is on JavaScript in general, and what your framework’s strengths and weaknesses are. Mix it up!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/1Q5JsYvgPwo" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>20/20 Hindsight, a Look Back at ALARMd</title>
		<link href="http://www.zachleat.com/web/2020-hindsight-a-look-back-at-alarmd/" />
		<updated>2007-07-22T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/2020-hindsight-a-look-back-at-alarmd</id>
		<content type="html">&lt;p&gt;Now that the traffic has died down a little bit on ALARMd, I’d like to write a little bit about my experiences with something I don’t think anyone predicted would garner so much interest.&lt;/p&gt;

&lt;p&gt;The day I sent the link to the LifeHacker editor, I purchased the alarmd.com domain. My thoughts on the domain were that I should have it just in case I decided to host the clock on the domain for easy access, and I certainly didn’t want anyone else to have it. That turned out to be a good idea since an unnamed internet charlatan purchased a similar domain mere hours after I had purchased mine and pointed it to his website. This same person was going onto various blogs and websites where ALARMd had been posted saying that it was a ripoff of his site, which of course was not true. I’m sure he got some traffic from it, and certainly am curious about the liberties he takes with the truth just to make a buck. Obviously I am not going to post a link to his website, since I do not want him to receive any traffic to his Google Ads machine. I hope that you, as a reader of my website, will trust that anything linked to this guy’s name is not worth any of your time.&lt;/p&gt;

&lt;p&gt;The link was posted to LifeHacker, and my meager website went from an average of 50 hits a day to receiving 87000 hits in two weeks. In the end, I got more visitors from stumbleupon than LifeHacker, which is really a testament to that website’s popularity.&lt;/p&gt;

&lt;p&gt;It was on delicious popular bookmarks for a while. It actually also ended up being on television. I know, I know, it seems ridiculous to even put websites on television, but it was. A lady named Erin O’Hearn does a segment called “Right Now on the Net” for Channel 6 Action News in Philadelphia. She had a blurb about it and you can &lt;a href="http://rightnow.6abc.com/2007/06/great-discoveri.html"&gt;even watch it here&lt;/a&gt; [Skip to 1:07]. I guess it was also on an internet radio show called “Techtalk Radio” and was featured as their site of the week. You can &lt;a href="http://www.techtalkradio.com/podcast/07152007.mp3"&gt;listen to that podcast here&lt;/a&gt; [Skip to 47:09], even though they pronounce my name “Zach-A-Lot” and are obsessed with the “Naked” checkbox. But to be fair, who isn’t obsessed with Naked checkboxes?&lt;/p&gt;

&lt;p&gt;And just recently, I put up the alarmd.com domain as a redirect to the site for all the hard-core users still going to it and using it. It’s still getting a couple of hundred hits a day.&lt;/p&gt;

&lt;p&gt;So, hindsight. The alarm clock is a device that everyone uses and easily relates to, but also a device that people have low expectations for. Most alarms only have one or two times they go off for, and with only a few options for alerting: buzzer or radio. Most go off every day, even on the weekends when you want to sleep in. But people put up with their crappy alarm clocks because there is literally no good alarm clock hardware out there. And some of the features I’ve put into ALARMd can also be seen in alarm clocks that cost over $100 USD. Ridiculous. I would bet that there is a huge market for someone to come out with an alarm clock that doesn’t suck and costs $40, or maybe people just want to use their cell phones all the time. I wonder if the iPhone alarm is any good. Look for my next project, which will be just as, if not more, retarded as the Internet Alarm Clock.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/oQnerezgTfc" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>DOMDom, easy DOM Element Creation</title>
		<link href="http://www.zachleat.com/web/domdom-easy-dom-element-creation/" />
		<updated>2007-07-07T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/domdom-easy-dom-element-creation</id>
		<content type="html">&lt;p&gt;Generally when approaching a complex problem involving web programming in JavaScript, the first question I ask myself is ‘What would Jesus do?’ As much as I am entertained by a mental picture of Mr. Jesus himself sitting on his &lt;a href="http://www.geocities.com/ResearchTriangle/Node/4081/"&gt;Jesux Distro&lt;/a&gt; appending children (and parents) into his DOM, I am instead distracted by an intense “passionate” hatred for Mel Gibson swelling in my chest. It’s actually quite distracting to the problem I am having, but I calm myself by punching my 4 foot tall inflatable Mad Max and wonder how much time I waste doing this. I figure it happens about twice an hour. (Digression)&lt;/p&gt;

&lt;p&gt;The DOM. Arch-nemesis of web developers attempting to support the ultimately tiny (I think it’s down to about 5 or 8% now?) sliver of browser market share that Internet Explorer currently entails. Let’s make it easier on ourselves and make a little package to do it for us. Run a function, pass in an argument with a description of the DOM node(s) we wish to create, and have the package auto-correct any bugs we would have encountered during manual creation, and maybe even have it inserted or appended for us.&lt;/p&gt;

&lt;p&gt;But wait, why are we doing this when there are literally 80 billion other DOM element creation classes already out there? It’s all about syntax. The existing packages are incredibly verbose, focusing too much on a complex object structure to describe the nodes, in some cases even having separate objects for attributes inside a single node. Why not use the syntax we’ve already come to love in the various DOM query libraries that are available? Why not use DOMDom? Let’s see a few examples:&lt;/p&gt;

&lt;p&gt;Single Node String&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'div'

&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Single Node String with ID and Classes&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'div#id1.class1.class2'

&amp;lt;div id="id1" class="class1 class2"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Single Node String for a Form Element&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'input[name="myTextBox",type="text",maxlength="5"]'

&amp;lt;input name="myTextBox" maxlength="5" type="text"/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Single Node String with Style Syntax&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'div{height=80px,color=#f90,border=1px solid #000}'

&amp;lt;div style="border: 1px solid #000; height: 80px; color: #f90"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Complex Single Node String with ID, multiple classes, Style, and Namespaced Attribute)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'div#id1.class1.class2[style="width:60px;color:#f90",@class="class4",@att="true",@namespace:att="false"]'

&amp;lt;div id="id1" att="true" namespace:att="false" class="class1 class2 class4" style="width: 60px; color: #f90;"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Multiple Node String: Linear (Parents with one Child)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'div span div'

&amp;lt;div&amp;gt;
     &amp;lt;span&amp;gt;
          &amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;
     &amp;lt;/span&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Multiple Node String: Non-Linear (Parent with more than one Child)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{ 'div': [ 'span', 'span' ] }

&amp;lt;div&amp;gt;
     &amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;
     &amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;How Does It Work?&lt;/h2&gt;

&lt;p&gt;By default, it’s set up to do HTML Fragments (innerHTML) because they are much speedier than the manual DOM element creation (createElement). But if you desire, you can toggle a boolean in the code and it will switch back to DOM element creation. When in DOM element creation mode, it will account for the following browser bugs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(IE6) Standardized for attribute representation (pointer to htmlFor)&lt;/li&gt;
&lt;li&gt;(IE6) Standardized case for accesskey, usemap, maxlength, and frameborder attributes.&lt;/li&gt;
&lt;li&gt;(IE6) Standardized checked attribute for radio and checkboxes.&lt;/li&gt;
&lt;li&gt;(IE6) Special consideration for dynamic handling of name and type attributes (on form elements).&lt;/li&gt;
&lt;li&gt;(Firefox) &lt;a href="http://developer.mozilla.org/en/docs/Whitespace_in_the_DOM"&gt;Works with whitespace that is treated as a node.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Syntax&lt;/h2&gt;

&lt;p&gt;You should already be able to tell how to create a node from the examples above. Here are some more things you might not have guessed:&lt;/p&gt;

&lt;p&gt;Creating a node with an id&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'div#myId'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Creating a node with CSS classes&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'div.class1.class2'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Creating two nodes at the same level&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[ 'div', 'div' ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Creating a node with two children&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{ 'div': [ 'div', 'div' ] }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can mix the {} and [] syntax wherever you like, but if you want a node to have non-linear children, you have to use the {} object notation.&lt;/p&gt;

&lt;p&gt;Creating a text node (start the node declaration with a #, you can change this to another non-conflicting character in the code if you like)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'#Any Text Here'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Creating a node with attributes (the @ is optional)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'div[class="class3",style="width:60px;color:#f90",@att="true",@namespace:att="false"]'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Creating a node with a Style Shortcut (mixing with a style attribute is handled properly)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'div{color=#f90,border=1px solid #000}[style="height:80px;background:#fff"]'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A few notes on attributes. Quotes are required on attributes (single or double but be consistent), but are not required in the style shortcut declaration. Quotes are not allowed to be nested inside of attributes (a single quote cannot be inside of a double quote and vice versa).&lt;/p&gt;

&lt;p&gt;And of course, all of the above can be mixed together&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'div#myId.class1.class2{color=#f90}[customAttr="true",@customAttr2="false"] div#child1 div#child2'
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Usage&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Appending&lt;/strong&gt; at the end of a parent’s children:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;DOMDom.append( 'div', yourParentNode );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Replacing&lt;/strong&gt; the children of a parent:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;DOMDom.replace( 'div', yourParentNode );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Unshifting &lt;/strong&gt;(inserting at the beginning of a parent’s children):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;DOMDom.unshift( 'div', yourParentNode );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Inserting&lt;/strong&gt; before a certain integer index of a parent’s children:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// must have at least 3 children, the index is 0 based, if index is null with unshift by default
DOMDom.insert( 'div', yourParentNode, 2 );
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Templates&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;&amp;lt;$var&amp;gt;&lt;/code&gt; to indicate a variable, in this example &lt;code&gt;&amp;lt;$test&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// "Compile" the template
var str = DOMDom.compile( { 'div.test span': '#Test &amp;lt;$test&amp;gt;' } );

// Use your template in some context, notice the test variable being set.
for( var j = 0; j &amp;lt; 1000; j++ )
{
    // knows we're using a compiled template since we're passing in variables as a third argument.
    DOMDom.append( str, d, { test: j } );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Benchmarks&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;(If you have Firebug open, make sure it's not on the HTML tab, this will slow down the benchmark significantly)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most of my work here has been inspired by the DomQuery and DomHelper classes written by JavaScript rock star Jack Slocum (the guy's initials are J.S. for God's sake), so I modeled my benchmark after &lt;a href="http://www.jackslocum.com/blog/examples/domhelper.php"&gt;his benchmark hosted on his website to test the DomHelper class&lt;/a&gt;. I'm running the same nodes he's testing on his website, so the results should be comparable. You can &lt;a href="http://www.zachleat.com/Projects/DOMDom/benchmark.html"&gt;test my benchmark for DOMDom here&lt;/a&gt;. Here are some results, reporting the average of 3 results with the format of an uncompiled element first and the compiled template in square brackets.&lt;/p&gt;

&lt;h3&gt;DOMDom Results&lt;/h3&gt;

&lt;p&gt;Internet Explorer 6: 666 ms [328 ms]&lt;br/&gt;
Firefox 2.0.0.4: 1880 ms [666 ms]&lt;br/&gt;
Safari 3.0.2 [Windows]: 546 ms [151 ms]&lt;br/&gt;
Opera 9.21: 343 ms [140 ms]&lt;/p&gt;

&lt;h3&gt;Comparative numbers from Jack Slocum's DomHelper&lt;/h3&gt;

&lt;p&gt;Internet Explorer 6: 2458 ms [677 ms]&lt;br/&gt;
Firefox 2.0.0.4: 672 ms [458 ms]&lt;br/&gt;
Safari 3.0.2 [Windows]: 291 ms [119 ms]&lt;br/&gt;
Opera 9.21: 370 ms [166 ms]&lt;/p&gt;

&lt;p&gt;The thing to take away from this is the question of why Satan is haunting my benchmarks? Two 666 averages? Anyway, DOMDom is quite a bit faster in the most popular browser, Internet Explorer, although I haven't tested it on IE7 yet. In Firefox, the opposite is true, with DomHelper taking the lead. Opera is comparable and Safari is faster in DomHelper as well. You can run your own tests using the links above.&lt;/p&gt;

&lt;h2&gt;Dependencies&lt;/h2&gt;

&lt;p&gt;This library was built to work with Yahoo User Interface (YUI), but could be trivially ported to another library by changing the function dependencies listed in the ADAPTER variable in the code.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var ADAPTER = {
  setStyle: YAHOO.util.Dom.setStyle,
  addClass: YAHOO.util.Dom.addClass,
  isString: YAHOO.lang.isString,
  isArray: YAHOO.lang.isArray,
  isNumber: YAHOO.lang.isNumber,
  isObject: YAHOO.lang.isObject,
  get: YAHOO.util.Dom.get
}; // to port, change these references
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you're still reading this encyclopedia, here are some links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/Projects/DOMDom/DOMDom.js"&gt;DOWNLOAD DOMDom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/Projects/DOMDom/DOMDom-min-jsmin.js"&gt;DOWNLOAD DOMDom Minimized with JSMIN (10KB)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/Projects/DOMDom/DOMDom-min-packer.js"&gt;DOWNLOAD DOMDom Minimized with Packer (6KB)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/Projects/DOMDom/benchmark.html"&gt;See the benchmark&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/Projects/DOMDom/tests.html"&gt;See the test file with a bunch of examples of syntax&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;a href="http://www.encyclopedia.com/doc/1O27-dom1.html"&gt;&lt;em&gt;-dom suffix denoting condition or state, as in freedom, wisdom, or DOMDom&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: changed the variable syntax to allow variables inside of nodes (not just text).&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/2K5NvEH-744" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Wake up to YouTube on my Internet Alarm Clock</title>
		<link href="http://www.zachleat.com/web/wake-up-to-youtube-on-my-internet-alarm-clock/" />
		<updated>2007-06-18T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/wake-up-to-youtube-on-my-internet-alarm-clock</id>
		<content type="html">&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update&lt;/strong&gt;: Try the new &lt;a href="http://www.zachleat.com/web/2008/04/06/alarmd-2-beta-with-google-calendar-integration/"&gt;ALARMd 2 Beta&lt;/a&gt;, with Google Calendar integration and offline Youtube caching.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Did you take your contacts out last night and you can’t see the time on your alarm clock from all the way across the room?&lt;/p&gt;

&lt;p&gt;I’m here to calm your fears. Enter &lt;a href="http://www.zachleat.com/Projects/alarmd/"&gt;ALARMD, the Internet Alarm Clock&lt;/a&gt;. Wake up to any Youtube video (that allows embedding), a last.fm user stream or tag, or any mp3 hosted online. There are a few defaults in there, but you can add and modify your own.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/4650"&gt;&lt;img src="http://farm2.static.flickr.com/1067/531165035_d2ba407333.jpg" alt="Now that's an alarm clock" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports multiple alarms (ALT R to add an alarm or use the Add Alarm button).&lt;/li&gt;
&lt;li&gt;Options for 24 Hour (Military) time and Seconds display&lt;/li&gt;
&lt;li&gt;Supports MP3 (hosted online), YouTube videos (that allow embedding), and last.fm user or tag streams.&lt;/li&gt;
&lt;li&gt;Key Mash Mode to kill the alarm (hit five random keys in one second)&lt;/li&gt;
&lt;li&gt;Time Font Size customization (automatically size to the width of the window using the Max option)&lt;/li&gt;
&lt;li&gt;Typical alarm clock colors: Red, Green, or Blue&lt;/li&gt;
&lt;li&gt;Alarm Toggle based on the Day of the Week&lt;/li&gt;
&lt;li&gt;Test button to make sure your speaker volume is set correctly.&lt;/li&gt;
&lt;li&gt;Sleep Mode button to get rid of the extra GUI while you don’t need it.&lt;/li&gt;
&lt;li&gt;Save all of your settings, URL’s, and alarms locally in a cookie (you &lt;strong&gt;don’t&lt;/strong&gt; need yet another account to use this)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Things to think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Power Settings – disable your screen saver, or any sort of automatic suspend or sleep setting. In my testing, having your monitor go into power save mode is acceptable, and the alarms will still sound (but you might want to test this yourself and leave a comment with your result).&lt;/li&gt;
&lt;li&gt;You might not want to use with a CRT, for fear of burn in.&lt;/li&gt;
&lt;li&gt;Personally, I like to use this in Opera, just because their default full screen mode (F11) doesn’t have toolbars or a status bar. But you can use the &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/4650"&gt;Fuller Screen Firefox plug-in&lt;/a&gt; to soup up your Firefox for similar functionality.&lt;/li&gt;
&lt;li&gt;Word of warning, the window &lt;strong&gt;must&lt;/strong&gt; have focus to autoplay YouTube videos.&lt;/li&gt;
&lt;li&gt;Make sure your local time on your computer is correct, especially if you are traveling between time zones. It doesn’t do any server side validation on the time (yet?).&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Possible Future Improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Countdown mode, displays amount of time until next alarm in place of the clock (good for timed presentations, where you want to see how much time is left before you have to quit).&lt;/li&gt;
&lt;li&gt;Google Gears integration for offline mode (if your internet goes out during the night)&lt;/li&gt;
&lt;li&gt;Support customizing source URL’s on a per alarm basis.&lt;/li&gt;
&lt;li&gt;Support days of the week toggle on a per alarm basis.&lt;/li&gt;
&lt;li&gt;Support user specified color customization.&lt;/li&gt;
&lt;li&gt;A crescendo alarm MP3 that increases in volume for a more peaceful wake up experience.&lt;/li&gt;
&lt;li&gt;An alarm MP3 with especially violent noises for heavy sleepers.&lt;/li&gt;
&lt;li&gt;An alarm MP3 of my mom’s voice to get that nice feeling of childhood back.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This internet application was built using the Yahoo UI Libraries (YUI) and Jack Slocum’s Ext DomQuery class. It is written entirely without using any server side programming languages, and therefore can be saved to your local machine. Not that anyone might want to use the Internet Alarm Clock, but if you do, I declare it officially released under the BSD license. Just don’t forget to cite the source when you redistribute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: added a couple more things to think about.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/IQkdDBEzDJs" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>Screen Readers and Listening at the Speed of Sound</title>
		<link href="http://www.zachleat.com/web/screen-readers-and-listening-at-the-speed-of-sound/" />
		<updated>2007-05-17T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/screen-readers-and-listening-at-the-speed-of-sound</id>
		<content type="html">&lt;p&gt;Here is a &lt;a href="http://yuiblog.com/blog/2007/05/14/video-intro-to-screenreaders/"&gt;presentation&lt;/a&gt; given by a guy named Victor Tsaran on how he personally uses screen readers to browse the web. As web developers, accessibility is an important aspect of our work and cannot be ignored. How many websites have you browsed that had flash navigation? If you’re not a web developer, you need to skip ahead to time stamp 25:44 to see the mega-fast speed this guy uses the screen reader at. I couldn’t understand a single word coming out of my speaker.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/jFzmzEXC9Y4" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	
	
	
	
	
	
	<entry>
		<title>Google Using YUI Grids CSS</title>
		<link href="http://www.zachleat.com/web/google-using-yui-grids-css/" />
		<updated>2007-04-05T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/google-using-yui-grids-css</id>
		<content type="html">&lt;p&gt;Head over to the &lt;a href="http://www.google.com/ig?hl=en"&gt;Google Homepage&lt;/a&gt;. Log In using your Google Account. Make sure you’re at your &lt;a href="http://www.google.com/ig?hl=en"&gt;Personalized Homepage&lt;/a&gt;. Take a look at the source CSS file &lt;a href="http://www.google.com/ig/f/tB22vfBbv0g/ig.css"&gt;ig.css&lt;/a&gt; included on the page. There are a few peculiar lines of code that I recognized from another source, the Yahoo User Interface Grids CSS file. Yahoo has provided a set of standard CSS definitions under the BSD license that allow a developer to easily make fluid or fixed width column layouts. And on the Google Personalized Homepage, there are the following class definitions:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#modules .yui-b{position:static;display:block;margin:0 0 1em 0;float:none;width:auto;overflow:hidden;}
.yui-gb .yui-u{float:left;margin-left:2%;*margin-left:1.895%;width:32%;}
.yui-gb div.first{margin-left:0;}
#modules,.yui-gb{zoom:1;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This code includes identical Class names taken from the &lt;a href="http://developer.yahoo.com/yui/grids/"&gt;Yahoo User Interface library Grids CSS&lt;/a&gt; component. Here is the source in the &lt;a href="http://yui.yahooapis.com/2.2.0/build/grids/grids-min.css"&gt;grids.css&lt;/a&gt; file from Yahoo (truncated for simplicity).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#yui-main .yui-b{position:static;}
.yui-t7 #yui-main .yui-b {
  display:block;margin:0 0 1em 0;
}
#yui-main .yui-b {float:none;width:auto;}
.yui-gb .yui-u{float:left;margin-left:2%;*margin-left:1.895%;width:32%;}
.yui-gb div.first{margin-left:0;}
#bd,.yui-gb{zoom:1;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Obviously, it’s the same code, with a few minor differences.&lt;/p&gt;

&lt;p&gt;&lt;img src="/web/wp-content/uploads/2007/04/yuigrids-google1.jpg" alt="Screenshot proof" /&gt;&lt;/p&gt;

&lt;p&gt;The interesting thing to note is that the YUI Grids CSS source code is licensed under a &lt;a href="http://developer.yahoo.com/yui/license.html"&gt;BSD license&lt;/a&gt;, which includes the following provisions:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Redistributions of source code must retain the above copyright notice, this list of conditions and the&lt;br/&gt;
following disclaimer.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The copyright notice they’re referring to is not included anywhere on the Google Personalized Homepage (and would seem to be a violation of the license). Now this may seem like a small infraction when we’re just talking about 4 lines of CSS code. But really, if they think the code is good enough that they will use it in such a prominent way and not write it from scratch using their own means, they should follow the licensing agreements stipulated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;br/&gt;
Google has added the BSD license statement and attribution to Yahoo in their CSS file (&lt;a href="http://www.google.com/ig/f/tB22vfBbv0g/ig.css"&gt;ig.css&lt;/a&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/* ===============BEGIN BSD LICENSED PORTION============= */
/*
Copyright (c) 2007, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.2.0
*/

#modules .yui-b {
  position:static;
  display:block;
  margin:0 0 1em 0;
  float:none;
  width:auto;
  overflow:hidden;
}
.yui-gb .yui-u {
  float:left;
  margin-left:2%;
  *margin-left:1.895%;
  width:32%;
}
.yui-gb div.first {
  margin-left:0;
}
#modules,.yui-gb {
  zoom:1;
}
/* ===============END BSD LICENSED PORTION============= */
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sorry to everyone visiting the page for the extra millisecond or two it will take to load these comments.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/MU2kdh5HGdk" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	
	
	<entry>
		<title>Logical XOR in JavaScript</title>
		<link href="http://www.zachleat.com/web/logical-xor-in-javascript/" />
		<updated>2007-03-23T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/logical-xor-in-javascript</id>
		<content type="html">&lt;p&gt;Of course there wouldn’t be an XOR function in JavaScript when I needed one. So I googled around and found an implementation at &lt;a href="http://www.howtocreate.co.uk/xor.html"&gt;How To Create&lt;/a&gt;. But it only took two arguments. So I rolled my own supporting a variable number of arguments. In my personal stuff, I’ve put it into a Math library under the YAHOO namespace, and you can decide if you want to do that on your own.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function xor()
{
  var b = false;
  for( var j = 0; j &amp;lt; arguments.length; j++ )
  {
    if( arguments[ j ] &amp;amp;&amp;amp; !b ) b = true;
    else if( arguments[ j ] &amp;amp;&amp;amp; b ) return false;
  }
  return b;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Usage:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;xor( false, true ); // true
xor( true, true ); // false
xor( false, false, true, true, true, false, true, false ); // false
xor( false, false, false, true, false, false, false, false ); // true
&lt;/code&gt;&lt;/pre&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/V433pJGAPbA" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Conservative Design Example: Hierarchical Options</title>
		<link href="http://www.zachleat.com/web/conservative-design-example-hierarchical-options/" />
		<updated>2007-03-23T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/conservative-design-example-hierarchical-options</id>
		<content type="html">&lt;p&gt;Welcome, one and all, to the second installment of actual code examples for the Conservative Design series. The decision was made (by me) to rename the component in question from the original Hierarchical Select to Hierarchical Options, due to the fact that the hierarchy can consist of any multiple option component, and is not limited to just a select. And to this face, this particular component was documented in the original post entitled &lt;a href="/web/2007/02/22/conservative-design-hierarchical-select-boxes/"&gt;Conservative Design: Hierarchical Select Boxes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.zachleat.com/Projects/valdi/hierarchicalOptions.html" title="Hierarchical Options"&gt;&lt;img src="/web/wp-content/uploads/2007/03/hierarchical.gif" alt="Hierarchical Options" /&gt;&lt;/a&gt;&lt;br/&gt;
Click the image above to go to the example.&lt;/p&gt;

&lt;p&gt;Notes on the example: The Tree structure is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Primary

&lt;ul&gt;
&lt;li&gt;Secondary

&lt;ul&gt;
&lt;li&gt;Tertiary

&lt;ul&gt;
&lt;li&gt;Quaternary

&lt;ul&gt;
&lt;li&gt;Quinary&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2nd Tertiary (is a static element that doesn’t hide)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;So without further adieu or out of place french, what do we have? 3 out of 4 requirements and 1 of 2 luxury items.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handles any number of select elements in a linear or tree (luxury item) like structure.&lt;/li&gt;
&lt;li&gt;Child select elements are optional based on parent selection. Can hide entire div element or display a message stating no options are available.&lt;/li&gt;
&lt;li&gt;Compliant with the Reset button.&lt;/li&gt;
&lt;li&gt;Right now only loads from standard HTML markup (not yet from JavaScript or JSON or an XMLHTTPRequest)&lt;/li&gt;
&lt;li&gt;Only supports Select elements for now, in the future should be abstracted to support Checkbox Lists or any multiple option component.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Outstanding Bugs&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opera button doesn’t reset properly with Reset Button&lt;/li&gt;
&lt;li&gt;Clicking off of the default and then back onto the default has the original selections downstream (but doesn’t propagate more than one level)&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/7n9UlPdmxxY" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>OMG SOA</title>
		<link href="http://www.zachleat.com/web/omg-soa/" />
		<updated>2007-03-12T00:00:00-05:00</updated>
		<id>http://www.zachleat.com/web/omg-soa</id>
		<content type="html">&lt;p&gt;In today’s Web 2.0 world of &lt;strong&gt;ultimate abstraction&lt;/strong&gt;, you don’t need to be bothered with the rudimentary low level programming functions of everyday languages. Client Side implementation of JavaScript functions across the browser landscape is unreliable at best, so why should you trust it for anything? So using forward thinking and futureproof compatibility design, naturally we will turn to the next great phase of web’s evolutionary growth, the Service Oriented Architecture (SOA). Using SOAP envelopes to package our function calls, I will now demo what is certainly to be the future of web development, and maybe, all programming endeavors. I call it: &lt;strong&gt;OMG SOA&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://soa.omg.org/"&gt;&lt;img src="/web/wp-content/uploads/2007/03/reflectomg-soabeta.png" alt="OMG SOA" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Are you programming a for loop? How do you know that the client will increment your integers through the loop correctly? That’s why you need to call our &lt;strong&gt;Incrementer Web Service&lt;/strong&gt; to increment your loop counter.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sample Service Calls&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/Projects/SOA/index.php/incrementer/0"&gt;Increment 0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/Projects/SOA/index.php/incrementer/3920"&gt;Increment 3920&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/Projects/SOA/index.php/incrementer/98"&gt;Increment 98&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Are you programming an array that needs to be magically combined into a string? Do you think you can reliably count on Internet Explorer to perform the function in the same way as your Firefox’s, or your Opera’s, or even your (God Forbid) Safari’s??? No, dare I say it, no.&lt;/p&gt;

&lt;p&gt;But don’t fear. We are here to comfort your pain, with a shot in the arm of standarditity. Welcome the &lt;strong&gt;String Concatenation Web Service&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sample Service Call&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/Projects/SOA/index.php/concat/string1/string2/string3/"&gt;Concatenate string1 with string2 with string3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;And finally, are you feeling lost in this sea of amorphous web technologies mixing and mashing together to form the gelatinous blob of money and media whores we know as Web 2.0? Don’t worry, OMG SOA is here for you again to solve all of your identity crisis problems. Ask our &lt;strong&gt;Are you Web 2.0 Web Service&lt;/strong&gt; with your URL and the magic 8 ball service will answer your question.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sample Service Call&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.zachleat.com/Projects/SOA/index.php/am-i-web-2.0/www.zachleat.com/"&gt;Is www.zachleat.com Web 2.0?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: apparently there is already a company called the Object Management Group with a &lt;a href="http://soa.omg.org/"&gt;website about SOA&lt;/a&gt;. Whoops?&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/5bWf6Gu3RGg" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Conservative Design Example: Multiple Option List</title>
		<link href="http://www.zachleat.com/web/conservative-design-example-multiple-option-list/" />
		<updated>2007-03-10T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/conservative-design-example-multiple-option-list</id>
		<content type="html">&lt;p&gt;All of the posts in the Conservative Design series so far have been brainstorming of design patterns. But how about some real life examples, some actual code? Let’s dive in.&lt;/p&gt;

&lt;p&gt;The first example I decided to tackle was the &lt;a href="http://www.zachleat.com/web/2007/02/26/conservative-design-option-list/"&gt;Option List&lt;/a&gt;, specifically the variant that allows multiple options to be selected. Let me start out by saying that I didn’t abstract out the type of source element that you could put into this example, I only programmed the element for a  element. For the impatient, let’s just start with the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="/web/wp-content/uploads/2007/03/optionlist_multiple_real1.gif"&gt;&lt;img src="/web/wp-content/uploads/2007/03/optionlist_multiple_real1.gif" alt="Multiple Option List Real Example" /&gt;&lt;/a&gt;&lt;br/&gt;
Click the image to see the actual example.&lt;/p&gt;

&lt;p&gt;This element was constructed using the YUI Library and Jack Slocum’s DomQuery selector class, as well as using the new form validation CSS and JavaScript code I’m currently developing entitled ‘&lt;strong&gt;Valdi&lt;/strong&gt;‘.&lt;/p&gt;

&lt;p&gt;It includes 3 of the 4 of the minimum features required as set in the original specification.&lt;/p&gt;

&lt;p&gt;Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Validation&lt;/strong&gt;: there is no submit button, but if there were, it would validate if the form has been entry has a value.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quick Links&lt;/strong&gt;: Select All, Select None, and Sort the Options&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Customizable Options&lt;/strong&gt;: Allow the user to add their own options for selection.&lt;/li&gt;
&lt;li&gt;Does &lt;strong&gt;not &lt;/strong&gt;abstract option types (checkbox, etc)&lt;/li&gt;
&lt;li&gt;Keyboard Support: CTRL A inside of the select box selects all options, Delete or Backspace removes the selected options, Enter key inside Add input field automatically adds option to the select.&lt;/li&gt;
&lt;li&gt;Can be &lt;em&gt;easily&lt;/em&gt; transformed into a Single Option List by removing the multiple=”multiple” option in the html.&lt;/li&gt;
&lt;li&gt;Sort will toggle between Ascending and Descending and maintain the selected options&lt;/li&gt;
&lt;li&gt;When the number of options outweighs the select size, the number of options is displayed next to the Add button. Try adding 5 or more options to the select list.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Screenshots for the Lazy People:&lt;/p&gt;

&lt;p&gt;Multiple Options are Added&lt;br/&gt;
&lt;img src="/web/wp-content/uploads/2007/03/optionlist_multiple_real1.gif" alt="Multiple Option List Real Example" /&gt;&lt;/p&gt;

&lt;p&gt;Validation when an Option is not selected:&lt;br/&gt;
&lt;img src="/web/wp-content/uploads/2007/03/optionlist_multiple_real21.gif" alt="Multiple Option List Real Example" /&gt;&lt;/p&gt;

&lt;p&gt;Success, they selected something and submitted:&lt;br/&gt;
&lt;img src="/web/wp-content/uploads/2007/03/optionlist_multiple_real31.gif" alt="Multiple Option List Real Example" /&gt;&lt;/p&gt;

&lt;p&gt;Watch for another separate article about Valdi later on.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/_vmnuInlsro" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Conservative Design: Command Line Interface</title>
		<link href="http://www.zachleat.com/web/conservative-design-command-line-interface/" />
		<updated>2007-03-07T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/conservative-design-command-line-interface</id>
		<content type="html">&lt;p&gt;This is another post in the series entitled &lt;a href="http://www.zachleat.com/web/2007/02/22/conservative-design-patterns-for-form-elements/"&gt;Conservative Design Patterns for Form Elements&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The argument has existed since the dawn of the Graphical User Interface (GUI). Which is better, keyboard-exclusive Command Line or mouse-intensive GUI’s? As more enterprise architectures are moving from terminals to web interfaces for their products, and as time is moving forward with the everyman user desiring an interface that looks pretty and easy to use, we’re seeing a drastic reduction in the utilization of the keyboard.&lt;/p&gt;

&lt;p&gt;But with the exception of form input, we’ve almost completely moved away from the keyboard as a means to execute functions and navigation. I’m proposing that we bring back the power of the keyboard. Obviously we can’t get rid of the GUI altogether, but instead complement it with a powerful command line.&lt;/p&gt;

&lt;p&gt;This component could exist as a standalone command line interface component or as a supplement to any search bar your page may contain. The basic premise of the Command Line Interface component is to provide a standardized method of navigating your website using nothing but the keyboard. It could fulfill more complex operations, but the scope of this article will just cover command line rudimentary navigation.&lt;/p&gt;

&lt;p&gt;Screen Printing: Fake Command Line Example&lt;br/&gt;
&lt;img src="/web/wp-content/uploads/2007/03/commandline.gif" alt="Command Line" /&gt;&lt;/p&gt;

&lt;p&gt;Screen Printing: Fake Command Line Example of AutoComplete Capabilities&lt;br/&gt;
&lt;img src="/web/wp-content/uploads/2007/03/commandline_f.gif" alt="Command Line AutoComplete" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minimum Feature Set&lt;/strong&gt;: (&lt;a href="http://jfulton.org/?page=Software&amp;amp;file=gui.php"&gt;source&lt;/a&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Autocomplete: must be able to finish the current command being typed by presenting a list of available options to the user. Must be compatible with keyboard navigation:

&lt;ul&gt;
&lt;li&gt;UP and DOWN arrows to select from list&lt;/li&gt;
&lt;li&gt;TAB autocompletes to first option&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Markup Scanning for Applicable Links: scan the current dom for  tags with a href element that could be used in autocomplete.&lt;/li&gt;
&lt;li&gt;Quick commands: markup options (custom attributes?) to allow the programmer to define commands in the html. These are one to three character combinations that execute a link or event.&lt;/li&gt;
&lt;li&gt;Standardized Command Set: standardized hot key to force focus to the command line. Also, for navigation options that are standardized between every website, have a standard set of commands that will execute with the same behavior, regardless of navigation implementation (Home [H], Login [L], Register [R], Forgotten Password [FP], Contact Us Page [C], Privacy Policy [PRIV], Terms of Service [TOS])&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Luxury Feature Set&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Markup Scanning for Events: sometimes navigation is executed through event handling. Scan the events assigned to nodes for any available options that could be executed in navigation.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Limitations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limitations on any sort of mouse-required interface: drag and drop&lt;/li&gt;
&lt;li&gt;Interaction with flash?&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Idea Credits&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.softpanorama.org/OFM/gui_vs_command_line.shtml"&gt;GUI vs Command line interface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.humanized.com/weblog/2007/02/24/your_grandmothers_command_line_the_command_line_co/"&gt;Command Line for the Common Man: The Command Line Comeback&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/B43wVa9R0WU" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	
	
	<entry>
		<title>Beaten to the Spiked Punch</title>
		<link href="http://www.zachleat.com/web/beaten-to-the-spiked-punch/" />
		<updated>2007-03-03T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/beaten-to-the-spiked-punch</id>
		<content type="html">&lt;p&gt;No matter what you think, &lt;a href="http://hyku.com/blog/archives/000786.html"&gt;someone else is thinking the same thing&lt;/a&gt;. I guess this guy might just be living with my same brain waves but a year or so earlier. It has never been a better time to just stop thinking.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/NDme2zvhcqA" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Conservative Design: Option List</title>
		<link href="http://www.zachleat.com/web/conservative-design-option-list/" />
		<updated>2007-02-26T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/conservative-design-option-list</id>
		<content type="html">&lt;p&gt;This is another post in the series entitled &lt;a href="http://www.zachleat.com/web/2007/02/22/conservative-design-patterns-for-form-elements/"&gt;Conservative Design Patterns for Form Elements&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next we’ll look at a web component that is almost ubiquitous among user interfaces today, the Option List. The Option List can take any one of the following three forms.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Multiple Selections: User can select any number of the options presented to them. Types: &lt;strong&gt;Checkbox Group&lt;/strong&gt;, &lt;strong&gt;Multiple Select Element&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Single Selection: User can select none or one of the options available. Types: &lt;strong&gt;Radio Group&lt;/strong&gt;, &lt;strong&gt;Select Element&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;User Input List: User types in the options that they want to use. All inputs are marked as selected. Types: &lt;strong&gt;Group of Textboxes&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;We’ll describe each of these variants separately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multiple Selections&lt;/strong&gt;:&lt;br/&gt;
&lt;img src="/web/wp-content/uploads/2007/02/optionlist_multiple1.gif" alt="Option List Multiple Selections" /&gt;&lt;br/&gt;
&lt;strong&gt;Minimum Feature Set&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validation: The user can select at least one, an integer range of options, or any number of the options presented.&lt;/li&gt;
&lt;li&gt;Quick Links: optional links to select all options, clear the options, and toggle the options to the opposite value of what they currently hold.&lt;/li&gt;
&lt;li&gt;Customizable Values: optionally allow the user to add their own options (one, an integer range, or many) to the list.&lt;/li&gt;
&lt;li&gt;Other Variants: Any Select Element, as described in the original post.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Single Selection&lt;/strong&gt;:&lt;br/&gt;
&lt;img src="/web/wp-content/uploads/2007/02/optionlist_single1.gif" alt="Option List Single Selection" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minimum Feature Set&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validation: The user can select at most one of the options presented.&lt;/li&gt;
&lt;li&gt;Quick Link: optional link to clear the options&lt;/li&gt;
&lt;li&gt;Customizable Value: optionally allow the user to add their own option (only one is required, since only one can be selected).&lt;/li&gt;
&lt;li&gt;Other Variants: Any Select1 Element, as described in the original post.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;User Input List&lt;/strong&gt;:&lt;br/&gt;
&lt;img src="/web/wp-content/uploads/2007/02/optionlist_all4.gif" alt="Option List User Input" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minimum Feature Set&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validation: The user must have at least one of the text fields with a value (doesn’t matter which one). Or the user must have an integer range number of fields with values.&lt;/li&gt;
&lt;li&gt;Quick Link: optional link next to an element to remove that element from the list (not clear it, remove it)&lt;/li&gt;
&lt;li&gt;Customizable Values: optionally allow the user to add their own options (up to an integer limit).&lt;/li&gt;
&lt;li&gt;Other Variants: Any List of InputX Elements, as described in the original post (could be passwords or textareas).&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The images above for all three component types show a textbox for the addition of another option, but this should also allow customization to allow any type of (Select or InputX) element for the addition of another option.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/wDjfTnry23Y" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Conservative Design Patterns for Form Elements</title>
		<link href="http://www.zachleat.com/web/conservative-design-patterns-for-form-elements/" />
		<updated>2007-02-22T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/conservative-design-patterns-for-form-elements</id>
		<content type="html">&lt;p&gt;Have you ever been to a web site that looks as though it has been built exclusively using pre-made bulky widgets cookie cuttered right onto the page? Lovely grid components, sweet over-featured WYSIWYG editors, maybe a Google or Yahoo map thrown in on the page for good measure. Conformist web sites using the conditioning forced upon them by time, executive, or work-ethic based constraints. The widgets on these websites either seem too bulky, reinventing the wheel with avant-garde user interaction for a confusing user experience, or they are just too lightweight to justify using at all.&lt;/p&gt;

&lt;p&gt;What I’m proposing is a standard set of Design Patterns for form input, as an extension to already existing HTML form elements. By describing the best practices for certain use cases of input, we can form a set of building blocks that can be used to enhance existing forms, instead of replacing them with totally new ways of user interaction.&lt;/p&gt;

&lt;p&gt;So keeping away from &lt;a href="http://www.adaptivepath.com/publications/essays/archives/000385.php"&gt;the spirit of inventing names for things that are already being done&lt;/a&gt;, I won’t be trivializing this idea with a catch phrase. Instead I hope you will realize the value of &lt;strong&gt;BUILDING BLOCKS&lt;/strong&gt; over &lt;strong&gt;cookie cutters&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These components be used to handle the tween cases of GUI development, where the interaction doesn’t warrant a full blown widget, but requires more than a standard HTML form element. I would be excited to see work done at this level of GUI development inside of the JavaScript libraries that are out there instead of work on the overblown “Widget Set” that seems to be the buzz in the community.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spectrum of GUI Elements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Raw HTML Inputs (Text, Password, Select…) -&gt; Smidgets -&gt; Full Blown Widgets (Editable Grid, Rich Text Editor)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Legend&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Toggle Option On or Off (Toggle)&lt;/li&gt;
&lt;li&gt;Select 0-1 Options From a List (Select1)&lt;/li&gt;
&lt;li&gt;Select 0 Options From a List (Select )&lt;/li&gt;
&lt;li&gt;Input 0 Characters into an Element (InputX)&lt;/li&gt;
&lt;li&gt;Input is obfuscated to prevent from being read (Obfuscated)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;To describe what we want, let’s first see what we have.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Existing HTML Elements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buttons (clicking performs a data altering action or form submission action)

&lt;ul&gt;
&lt;li&gt;Submit&lt;/li&gt;
&lt;li&gt;Reset&lt;/li&gt;
&lt;li&gt;Push (without attached behavior)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Checkbox (Toggle)&lt;/li&gt;
&lt;li&gt;Checkbox Group (Select )&lt;/li&gt;
&lt;li&gt;Radio Group (Select1)&lt;/li&gt;
&lt;li&gt;Select Single (Select1)&lt;/li&gt;
&lt;li&gt;Select Multiple (Select )&lt;/li&gt;
&lt;li&gt;Text (InputX)&lt;/li&gt;
&lt;li&gt;Textarea (&lt;em&gt;antiquated due to CSS styled word wrapping multi line Text input&lt;/em&gt;) (InputX)&lt;/li&gt;
&lt;li&gt;Password (InputX, Obfuscated)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;And because this is going to be a series, I’ll continue with my first case of a Conservative Design Form Element in a new post.&lt;/p&gt;

&lt;p&gt;Let me just reiterate that I do hope you take the ideas for these GUI components and develop them in your favorite JavaScript library. The purpose of this is to come up with a set of feature-based standards so that people don’t have to keep developing their own components over and over again. Do you have an idea for a feature that you think should be included in the standard or luxury feature set of a component? Post it in the comments of that component blog post and I’ll certainly modify the post with your suggestions.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/ho9jz6BbfJU" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Conservative Design: Hierarchical Select</title>
		<link href="http://www.zachleat.com/web/conservative-design-hierarchical-select-boxes/" />
		<updated>2007-02-22T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/conservative-design-hierarchical-select-boxes</id>
		<content type="html">&lt;p&gt;This is a post in a series entitled &lt;a href="http://www.zachleat.com/web/2007/02/22/conservative-design-patterns-for-form-elements/"&gt;Conservative Design Patterns for Form Elements&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For now, I’ll start off with an easy web component that a lot of you have probably already had some experience with. But, strangely enough, it is not included in any of the JavaScript libraries that are out there, that I’ve seen. If you know of one, go ahead and post it in the comments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hierarchical Select Boxes&lt;/strong&gt; (sometimes called Dynamic Select Boxes if you’re doing a web search)&lt;/p&gt;

&lt;p&gt;Behavior: 2 or more select boxes working in parallel, where selection of an option in a parent dynamically adjusts the options of the child.&lt;/p&gt;

&lt;p&gt;Screenshot (Prior to any selection):&lt;br/&gt;
&lt;img src="/web/wp-content/uploads/2007/02/hierselects1.jpg" alt="Prior to any selection" /&gt;&lt;/p&gt;

&lt;p&gt;Screenshot (After an option is chosen in the first select box):&lt;br/&gt;
&lt;img src="/web/wp-content/uploads/2007/02/hierselects2.jpg" alt="After a selection is made" /&gt;&lt;/p&gt;

&lt;p&gt;Minimum Requirements for Acceptable Feature Set:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must be able to handle any (reasonable) number of select boxes in a linear structure: parent elements only have one child.&lt;/li&gt;
&lt;li&gt;Child select elements can be optional depending on parent selection. Maybe a continent doesn’t have any countries, so don’t display a child select element. It would be nice to have a visual indicator showing whether or not a parent option had children (triangle, folder(?), arrow or other customizable icon).&lt;/li&gt;
&lt;li&gt;Must have functionality that allows it to be reset with the form reset button, as &lt;a href="http://www.mattkruse.com/javascript/dynamicoptionlist/"&gt;Matt Kruse has done (Example 3)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Load options in child select’s dynamically from multiple data sources (describe in &lt;a href="http://www.bobbyvandersluis.com/articles/unobtrusivedynamicselect.php"&gt;raw HTML code&lt;/a&gt;, local JS file, remote JSON object or XML file using an XMLHTTPRequest)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Luxury Feature Set:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must be able to nest select elements in a tree structure: selecting an option in a parent element could modify 2 child select elements.&lt;/li&gt;
&lt;li&gt;Could be able to modify the options for any element that displays options (Select1 or Select as described in the &lt;a href="/web/2007/02/22/conservative-design-patterns-for-form-elements/"&gt;Conservative Design Post&lt;/a&gt;: Checkbox Group, Radio Group, Select Single or Multiple)&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/W8NOkS-4MEs" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Screen Printing, Fake Interfaces Part 1</title>
		<link href="http://www.zachleat.com/web/screen-printing-a-dreaming-exercise/" />
		<updated>2007-02-20T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/screen-printing-a-dreaming-exercise</id>
		<content type="html">&lt;p&gt;Why not error messages that tell you when your internet has been disconnected? How about one that tells you when you’ve been logged out (maybe in another window) and allow you to reauthenticate to the server right there? I don’t believe there are any architecture problems with these two ideas.&lt;/p&gt;

&lt;p&gt;&lt;a href="/web/wp-content/uploads/2007/02/image2.jpg" title="Error Messages"&gt;&lt;img src="/web/wp-content/uploads/2007/02/image2.jpg" title="Error Messages" alt="Error Messages" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/g2zunoUlQos" height="1" width="1"/&gt;</content>
	</entry>
	
	
	
	<entry>
		<title>Checklist for Web Applications</title>
		<link href="http://www.zachleat.com/web/checklist-for-web-applications/" />
		<updated>2007-02-20T00:00:00-06:00</updated>
		<id>http://www.zachleat.com/web/checklist-for-web-applications</id>
		<content type="html">&lt;p&gt;As the first post in this new category of web development, I’ve decided to keep it simple and post the different components and architecture considerations a developer must consider when making a new application, especially in today’s world of in-page dynamic interaction and the complications that has put on the problems that were considered solved in yesterday’s page level world. Mostly this is a place to collect my thoughts on this subject.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Automatic Print Styling&lt;/strong&gt;: Is the page going to be able to be printed properly without a “Printer friendly” link? CSS style sheets can be used to modify the output of the page using the @media print declaration. Are the widget components you’re using in your JavaScript library able to support easy printing?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Browser History Management&lt;/strong&gt;: Will your application support the back button, especially with the increased usage of AJAX interactions on a full page application. Don’t use XMLHTTPRequest’s to fetch the entire content of a page. Just redirect them to a new page when you are only saving the header and the footer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Graded Browser Support&lt;/strong&gt;: support of the web browsers with a large percentage of market share using the ideas put forth by Nate Koechley in his Graded Browser Support descriptions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bookmark and Permanent Linking&lt;/strong&gt;: is the behavior of your JavaScript application changing how data is being displayed? You’d better modify the URL to allow the user to bookmark link straight to the same view.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;File Compression&lt;/strong&gt;: Minimize your CSS and JavaScript for delivery. GZip your CSS and JavaScript for browsers that support it (most all modern browsers do).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Efficient Caching Mechanisms&lt;/strong&gt;: server side caching of data is necessary for high volume traffic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Internationalization&lt;/strong&gt; (i18n): will your application be viewed in other countries by non-English speakers? Are your dates in an international format? How about 24 hour time formats? Time zones? Do they observe Daylight Saving Time?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Error Logging&lt;/strong&gt;: Both server side and client side (using AJAX to log JavaScript errors can be very helpful)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Recommended Luxury Items&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Support mobile devices&lt;/strong&gt;: How will your application look on a Blackberry? How does it render in Opera Mini?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Offline Mode&lt;/strong&gt;: Add and modify data offline, with the ability to automatically synchronize changes when an internet connection becomes available.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exportable data&lt;/strong&gt;: PDF, Excel, RSS, even offline static HTML. JavaScript can sometimes give unknown results when using the browser to save the page locally. Make sure this is supported. Don’t force your users to save screenshots.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Enterprise Client Side Widgets&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Data Grid&lt;/strong&gt;: businesses just love data grids. Nothing like a nice standard set of cookie cutter constraints to force upon your data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Charts and Graphs&lt;/strong&gt;: metrics are important. Existing client side JavaScript charting packages can be limited when it comes to printing, or even saving the chart as an image file. These are important.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;There are many facets that a developer must consider when designing a new application. I hope this list will at least make you think about some things that you may not have considered before. Thanks for reading.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/zachleat/~4/uKgwk6J2NFY" height="1" width="1"/&gt;</content>
	</entry>
	
	
</feed>
