The Trials And Tribulations Of 10KB

JavaScript is a fun language. It lets you build almost anything you can imagine. For some reason, I thought it would be fun to build a simulator for the card game War. I started hacking away on the idea in my spare time. It was also a good excuse to learn object-oriented JavaScript to make my card game simulator flexible and modular. After a few weekends I had something that worked (screenshot below). Unfortunately after that life got busy and my war simulator just sat there collecting virtual dust for more than a year.

Fast forward to July 29th when the 10K Apart contest is launched challenging developers to build compelling apps that are 10 kilobytes or less. This would be a fun way to refine my stale war game simulator as well as test my JavaScript coding-foo to squeeze it all in to 10 kilobytes.

Pure HTML Cards

One of my first challenges was re-doing the cards. Initially I constructed a single-image sprite containing all of the cards. JavaScript would manipulate the class of a div which would determine how to position the image for the proper card to be displayed. This method led me to discover something Internet Explorer actually gets right with CSS and the other browsers fall short. This image of all of the cards weighed in at 36KB alone. Ouch!

My solution was to use unicode characters for the different suites and letters and numbers for the card values. Child elements of the card held the symbols and I positioned them absolutely within the card element. The final touch was to rotate one of the child elements 180 degrees using the transform CSS property so it would display upside down just like a real card. My image-less approach was just a fraction of the size of using images for cards. But something was still missing.

Playing cards have decorative designs in the middle. It would be too complicated to completely replicate these designs so I came up with the idea to use a Twitter avatar as a background. Thanks to the awesome service provided by http://tweetimag.es/ their RESTful api let me grab any public Twitter users avatar by constructing a simple URL. Browsers provide an easy way to  add new CSS rules to a stylesheet via JavaScript so I could dynamically change the background image of a card based on which Twitter names the user provided. This is where the idea for making my War game simulator revolve around Twitter users was born.

Viral Sharing

A bigger advantage to hooking into Twitter is it makes each game more personal for the player. Pitting two people in a card game battle makes the experience more meaningful then a bunch of plain, virtual playing cards flipping back and forth for a couple hundred of turns. This also has the potential for a viral aspect to my app since I already have atleast two Twitter names that would be interested in the results. In order to share a game I needed to create a way to read in the number of players, their twitter name, and their deck at the start of the game. Using a simple string of characters that represented this data attached to the end of the URL allowed me to do this. All of the values in the deck could be stored as a number or letter since I had unique first letters.

Card Encoded Equivalent
0, 1, 2 … 10 0, 1, 2 … 10
Jack j
Queen q
King k
Ace a
Hearts h
Diamonds d
Spades s
Clubs c

Therefore, the Ace of Spades could be represented as ‘as’, the 10 of Diamonds would be ’10d’ and so on. A full game looks like this: p1-kingkool68:adqhkc2d5d10s3h3d5hjs8dqc9c8h2s9d6c7c9skd10d8c7s7d2c4s|p2-naudebynature:jc6d10cjdkh5c4h6sqdks2has6h4d7h4cac10h9hah3s8s5s3cjhqs

A Heap of Data

One of my favorite parts of developing this app was creating a way for keeping track of all the different data that results from a single game. For each war I store the turn it occurred on as well as keep track of which player won the war. After each turn I store a copy of the players deck for further analysis after the game concludes. I originally wanted to include a line graph showing the number of cards a player had in their deck as the game progressed. Building that feature was pretty simple thanks to the Google Charts API but in the end it had to be cut in order to get below the 10KB limit.

Squeezing Down the Bits

I was a little ambitious with the functionality that when I was ready to start compressing my code down I was shocked to see my idea bloated to 33KB. That’s more than 3 times the maximum size. A serious slimming down was in order. Pre-populat lists of Twitter users that would make for interesting battles: cut. Charting capabilities mentioned earlier: gone. A brief blurb explaining the game and who I was: removed. Title tags: discarded. Every little bit I could trim down would help. After all this I was down to about 17KB and along way to go to get under 10KB.

Dean Edwards took JavaScript compression to another level with his /packer/ tool. He came up with away to reduce the size of JavaScript by removing white space, stripping comments, and replacing variables with shorter, less-coherent replacements. CleanCSS.com does pretty much the same thing but for CSS. Such optimizations include replacing font-weight:bold; with font-weight:700; color:#ff0000; with color:red; and so forth. These packing tricks helped get me to 13KB but I was running out of ways to optimize further.

My next plan was to modify my HTML. IDs like ‘prepare-for-war’ became a single letter, <strong> elements were replaced with deprecated <b> tags, and the closing </body> and </html> tags were axed since they had no affect on my page. Sidenote: Google chops off the closing </body> and </html> tags which for a site that serves up that volume of pages results in a savings of a couple million dollars in bandwidth bills every year.</end sidenote>

At this point I was so close to coming under 10KB but yet so far. It was time for one more drastic technique. I noticed how well the JavaScript /packer/ tool worked so I decided to combine my HTML and CSS into a single line and use JavaScript to write it out to the page as it was loading. This way I could combine it with my main JavaScript code for the most efficient compression possible. After 3 hours of toiling in vain, I reached the point where my app was under the magic limit. Ten kilobytes is equal to 10,240 bytes. My code weighed in at 10,236 bytes; a mere 4 bytes to spare!

Lessons Learned

Even after spending hours tediously compressing and optimizing my code, I still had a lot of fun. My biggest challenge wasn’t squeezing everything down, or getting it all to work just right. Rather my biggest challenge was myself and when to determine it was finished. After each piece of functionality I coded I wound up thinking of two more things to make it even better. Once it was submitted to the contest gallery, my app got some luke-warm attention but I’m used to that now. Personal projects I toil over never get the amount of attention I always think they will. I’m anxious to see who wins the 10K Apart contest and whether my War app gets any mention at all from the judges.

But in the end that doesn’t matter. What matters is I got my idea out of my head and into a working state where people could actually try it out, no matter how trivial of an idea it is. And that is what makes the web such a great platform for an individual like myself.

Making JavaScript And The Blip.tv Player Work

It sure would be nice if the blip.tv player had an easy way to change which video is playing in a playlist using their JavaScript API. But they don’t, so I had to roll my own to make the two play together nicely. Here is the end result (Note there are some line breaks I put in here for visual formatting, it might not work):

var player;
var currentPlaylistItem;
var currentState;
function getUpdate(type, arg1, arg2) {
	switch(type) {
        case "state":
			currentState = arg1;
		break;
		case "item":
			currentPlaylistItem = arg1;
			var episode = player.getCurrentItem();
			document.title = episode.title;
        break;
    }
}
var flashvars = {
	'file': 'http://blip.tv/play/ha0CjMVEh_8o',
    'enablejs': 'true',
    'javascriptid': 'blip_player',
    'autostart': 'false'
};
var params = {
	'allowscriptaccess': 'always',
	'allowfullscreen': 'true',
	'expressinstall': '/millennials/flash/expressInstall.swf'
};
var attributes = {
	'id': 'blip_player',
	'name': 'blip_player'
};
swfobject.embedSWF('http://blip.tv/play/ha0CjMVEh_8o',
'blip_player', '770', '470', '8.0', false, flashvars,
params, attributes, swfCallBack);
function swfCallBack() {
	player = document.getElementById('blip_player');
	$('#agenda h3 a, #agenda a.blip_tv').click(function(){
		var playlistItemNum =
                    $(this).attr('href').split('#')[1];
		changePlaylist(Number(playlistItemNum));
		$.scrollTo('.video .player', 800);
		return false;
	});
}
function changePlaylist(num) {
		var direction = 'prev';
		var diff = currentPlaylistItem - num;
		if (diff < 0) {
			direction = 'next';
			diff = Math.abs(diff);
		}
		for(i=0; i < diff; i++) {
			player.sendEvent(direction);
		}
		if (currentState == 0) {
			player.sendEvent('play');
		}
}

There are three requirements to getting started as outlined in the blip.tv wiki:

  1. The player must be embeded with the enablejs=true Flash variable set
  2. The player must be embeded with allowScriptAccess=always object/embed parameter set
  3. A JavaScript function must exist named getUpdate()

The first part of my script sets up three global variables that we’ll use.

  • player will reference the object/embed element by an ID. It is how we send commands to the show player.
  • currentPlaylistItem is the number of the video selected (or position) in the playlist.
  • currentState is either 2 (playing), 1 (loading), or 0 (stopped) depending on the current state of the player.

The getUpdate() function listens to the blip.tv player for changes like when the player is stopped or a video is changed in the playlist. The type argument is a string which we can send through a switch statement to determine what we need to do.

If the state of player has changed then we update our currentState variable with the value of arg1 (which will be a number between 0 and 2). If the event is an item change, we will update the currentPlaylistItem variable to reflect that. As an added bonus we get the title of the current playing video and change the title of the webpage to reflect this. This has zero SEO value and is really only a convenience to our audience.  Now that we know what is going on, lets get to the fun stuff.

Three variables (which are really Objects) are created for swfobject so we can easily embed the video player dynamically into the page. The ‘blip_player’ paramter is the ID of the player that we’ll be referencing shortly. The swfCallBack() function is called once the blip.tv player has loaded. There we set our player variable to reference the element of the blip.tv player. I used a line of jQuery to set the onClick() events of a group of links that will change the playlist when they are clicked.

In the HTML the links contain direct links to each blip.tv video and an anchor with a number after it. This number is the playlist position of the specific video. jQuery makes it a snap to extract just that number from the URL which we store in the playlistItemNum variable. The playlistItemNum variable is passed along to a function called changePlaylist() which does all of the heavy lifting.

Since the blip.tv show player doesn’t have a direct way of going to a specific video in a playlist, we have to hit the next or previous button on the player programmatically. The direction is set to ‘prev’ initially.  diff is calculated by subtracting the number passed to the function from the position of the currently playing video, currentPlaylistItem.

If diff is a negative number than we need to switch the direction variable to ‘next’ and get rid of the negative number by calling the absolute value method ( Math.abs() ). Now we simply send the player a command to go to the next or previous video as many times as we need to get to the desired video via a loop. Finally, if the player is stopped, we send the video player a command to start playing the video.

As an added nicety, we gently scroll the viewer up the page to the top of the video player so they’re not left wondering why nothing happened. The jQuery scrollTo plugin makes this a breeze to do.

There is one caveat for the changePlaylist() function to work: the playlist needs to be visible on the blip.tv show player. This is simply an option you set on the player configuration screen on blip.tv. Without it showing, we can’t get which video is playing and the whole thing falls apart.

That wraps up how to roll your own playlist changing function as well as shed some light on how you might control other things about the blip.tv show player using JavaScript. You can see this in action on the Pew Research Center Millennial Conference video page. If you have any questions leave them in the comments or get in contact.

Paying For JavaScripts? Just View Source

ThemeForest.net is an online marketplace for developers to sell themes, templates, and other web development related goodies. A lot of the files are for the backend making it next to impossible for someone to copy them without breaking into your server. But ThemeForest offers JavaScripts for sale and even offers a live preview.

By the very nature of the web, a front end technology like JavaScript requires the source code to be downloaded to your computer before it can run. This means anyone with a little know-how can easily bypass the need to buy the script and piece it together themselves.

For example, take this JavaScript calendar widget which has 0 sales as of this writing. All you have to do is go to the live preview and remove the frame by clicking the link in the top left corner. From there it’s just a matter of viewing the source (Choose View->Source in Internet Explorer, View->Page Source in Firefox) and copying the necessary JavaScript and CSS files. Here’s everything you need for this calendar widget:

Now before you get all upitty about the ethics behind this, you should know that this script is freely available from the author’s own site, which was based on an open source project from around 2006 according to comments in the CSS files.

Granted ThemeForest isn’t targeted at professional developers like me so someone might be more than happy to plunk down $8 to download everything in one nice, neat package. But if I were selling scripts on ThemeForest, with the expectation of a profit, I would be pissed that ThemeForest didn’t take more precaution to protect my source code. At the least they could obfuscate the live preview code using a tool like /packer/.

At any rate this demonstrates why it’s so hard to sell JavaScripts by themselves due to the very nature of how they work in an open web.

How I Learned JavaScript On Accident

I picked up JavaScript by accident before jQuery, Prototype or any of the other smitten tools that make web developers lives easier. The web was just coming back to life in early 2005 from the dot-com bomb. I was enrolled in the Digital Media Production program at the Art Institute of Philadelphia; a degree encompassing video, web, and multimedia all rolled up into one. Back then almost everything about building websites fell under the term ‘scripting.’ ‘Scripting 1’ was really an introduction to HTML with a little bit of CSS thrown in. I managed to test out of this class with an example site I put together for a friend a week earlier. Logically, Scripting 2 would seem to be more advanced HTML and CSS techniques, but my thinking was wrong. My school deemed ‘Scripting 2’ as a JavaScript class.

Dreamweaver's horrible rollover JavaScript code

My only experience with JavaScript before ‘Scripting 2’ was the auto-generated cruft from Dreamweaver MX used in rollovers and jumpmenus. I had no idea what it did or how it worked; I only knew not to muck with it or things would break. I also spent most of my Dreamweaver time in design view, not code view. The required reading for the class was Beginning JavaScript by Paul Wilton. It was still a leading book at the time even though it was 5 years old. That’s how stagnant web development was compared to the blistering pace of progress made today. Some of the more advanced topics included dynamic HTML (DHTML) on Internet Explorer 4.0 and Netscape Navigator 4.x. Yea it was that old, but a lot of the basics still hold true even today.

Beginning JavaScript Cover by Paul Wilton

I read that book cover to cover to get a handle of JavaScript and help me complete my projects consisting of things like temperature converters and form validation. After 11 weeks it finally began to make sense. I began thinking about solving problems with it which led me to my personal project Deviant Bordermaker. The simple tool calculated image sizes for specific ratios given an image. It was developed long before Adobe Air as an offline app that people would download and run locally. Ecstatic couldn’t even begin to describe the feeling of bringing an idea to life and overcoming the barriers of learning a new technology. I knew from that day on that JavaScript would be a part of my career.

Fast forward nearly 2 years later when I land my first job at USNews & World Report. My very first task was to develop a quiz-building tool. Since I knew zilch about server-side programming languages, like PHP, I built the app using JavaScript. The final output was the HTML necessary for the quiz to run that a producer could simply copy and paste into the right place. Thinking back on it, the JavaScript was probably overly complex but I certainly learned a lot and continued to push the boundaries of my JavaScript chops.

From there I slowly learned the Prototype JavaScript framework, which was the defacto library at the time. At first I didn’t feel like it was making anything easier as I was struggling to grasp the object oriented model of doing things in Prototype. This hard work paid off as learning jQuery was a breeze; it’s pretty much the same thing but with different names for things.

JavaScript has come a long way since 2005. The language continues to be pushed into new areas thanks to AJAX, web applications, and a rekindled browser war. Learning JavaScript will go a long way in learning other things like PHP and should definitely be a foundation skill for most any frontend developer. How did you come across JavaScript?

Death To The Div

Every web developer is looking forward to the new HTML spec, HTML 5. The new spec will birth 20 new elements to add more underlying semantic meaning to content. The new elements came out of popular IDs and Class attributes for common situations in web design: <nav> is just like <div id=”nav”>. But these new elements are just a stop gap.

Death to the Div Tag

I wish the web community could move beyond pigeon-holing ourselves with specific elements. Why can’t we make our own elements to better describe our content? If I had my way <div>s would be ancient history and any element not already defined in the HTML spec would be treated by browsers like a <div>.

There are many benefits to opening up the element nomenclature like this.

1) It will be much easier to describe content. No longer will we need to shoehorn our content into quasi-relevant elements. Did you know the <address> tag is to define the contact information for the author or owner of a document and not to hold a plain street address?

2) No more div-itis. Web developers will no longer have to wade through a dozen </div> tags. <div> tags are the least-semantic structural elements in a web designers toolbox; it literally means ‘division’ of a page and is used to mark off different sections within a document. Things can get pretty messy when using too many <div>s however as it is hard to tell where they end. Take a look at this code example:

<div id="container">
   <div id="article">
      ...
     <div id="chart">
      ...
     </div>
   </div>
</div>

Look how much better this markup looks from both a readability and maintainability perspective:

<container>
   <article>
      ...
     <chart>
      ...
     </chart>
   </article>
</container>

A benefit to free-form elements is the semantic closing tags making it clear where each element begins and ends.

3) Microformats might actually work. The movement to create semantic markup using loosely agreed upon Classes slowly died off due to the extra bloat it introduced to the underlying code. With the ability to create your own tags, Microformats could flourish and we can begin to set-up our own best practices for describing content.

4) Faster JavaScript. Not many browsers support the JavaScript method getElementsByClassName but every browser supports getElementsByTagName. Because of this many libraries have had to write their own implementations which are many times slower than native methods. Faster DOM traversal = faster JavaScript!

What will it take to make this a reality? Boogers

We’re already going to have issues with older browsers supporting brand new elements with HTML 5. We might as well go all the way and make sure every browser can support whatever element we can come up with. After all we only have one shot to get HTML right for this generation according to John Allsopp.

Many browsers already support free-form elements both with CSS and JavaScript. To really flesh this out I created the Booger Test and below are my findings.

  • Firefox 3+ supports the <booger> tag as if it were a native element but has to be explicitly set to display:block.
  • Firefox 2 has no problem with CSS unless there children elements in which case the <booger> tag collapses. Weird!
  • All versions of Internet Explorer don’t know what to do with the <booger> tag but they do function normally when using a JavaScript shiv
  • Safari and Chrome have no problems.
  • Every browser I tested passed the JavaScript portions (getElementsByTagName(“booger”)) of the booger test with flying colors!

So as you can see, we are really close to being able to use our own elements. HTML 5 is already going in this direction but it would be a real shame if everyone got hung up on what frivolous new element names we should all agree to use instead of coming up with new functionality to move the capabilities of the web forward.

Top 5 Firebug Extensions

Firebug started as an indispensable Firefox extension which takes web development to a new level. But after 2 years since it’s initial 1.0 release, Firebug has grown into a platform with a host of extensions built right on top of it. Here are my top 5 Firebug extensions that every web developer should have installed.

#5 SenSEO – SenSEO is a handy checklist of key SEO criteria. This Firebug extension rates your page on a scale of 100 against Google’s webmaster guidelines. SenSEO is most important right before a big launch to catch any simple tweaks that you may have overlooked during development.

SenSEO Firebug Extension Screenshot

#4 CodeBurner – CodeBurner is an HTML and CSS reference right at your fingertips while you debug. It adds a Code Example tab which gives a brief description of the HTML tag or CSS property you have highlighted as well as a code sample so you can see the recommended usage. If that’s not enough, CodeBurner provides a link to the Sitepoint reference page which has everything you could ever want to know. Man, I wish I had this extension when I was learning HTML and CSS (let alone Firebug).

CodeBurner Firebug Extension Screenshot

#3 FireFind – FireFind does only one thing but it does it well: finding elements. Using a CSS selector or XPath statement, FireFind will highlight all of the matching elements on the page. This makes it a breeze to test CSS selectors with your site right in front of you. To boot, it also features a count of all the elements found. Even though this is possible through Firebug’s console tab when any popular JavaScript library is included, FireFind makes the process straight-forward and painless.

FireFinder Firebug Extension Screenshot

#2 FireCookie – If you have ever had to debug JavaScript cookies then you’ll wonder how you got by without this extension. FireCookie lets you inspect and edit cookies on the fly including permissions, values, and the expiration time. You can even sort all of your cookies as well as filter them out by domain. And when testing a script for your audience that has cookies disabled, FireCookie provides a simple option to disable cookies globally or just for the current domain. Now working with cookies doesn’t have to be such a stale experience.

FireCookie Firebug Extension Screenshot

#1 YSlow – Serious web developers are obsessed with performance and YSlow provides a smorgasbord of tools for measuring the speed of a site. YSlow is built around 34 best practices for speeding up a website which is the result of extensive research by the Yahoo Performance team. The extension provides a letter grade of each practice with advice on how to squeeze out every little bit of extra performance.

YSlow Test Grade View

Another handy view is the Components tool which gives you an insight into all of the componets of the page. There are a bevy of stats that can be analyzed to pinpoint bloated waste.

YSlow Components View

Finally, the statistics tool gives insight into the weight of your page for users with an empty cache and a primed cache.

YSlow Statistics View

If you have never given much thought to the performance of your site, YSlow makes it easy to dive right in.

What are some of your favorite Firefox extensions geared towards web development?

KristinaNaude.com: From Comp To Code In 12 Hours

Kristina had been toying with the idea of her own website for a couple weeks now. However, this past weekend, she got around to comping one together. She has been fascinated with the eclectic desk style that seems popular these days. While she was busy in Photoshop, I was setting up the domain and basic file structure. Since it’s a small site, the preparation didn’t take long. In fact the most time consuming task involved cutting images up from the comp and organizing them. Coding was a snap. The site is a basic 3 column layout and most everything is an image.


KristinaNaude.com Screenshot

Creating the carousel to page through her resume was a custom job that took me about 20 minutes using jQuery. I had hoped to just go out to the jQuery community and find a nifty carousel plugin that I could just drop in and be on my way. Unfortunately this wasn’t the case. While there were plenty of options out there, everything was over engineered and too rigid. Most require the content to be an unordered list but I was using a set of divs. This shouldn’t make a lick of difference as any jQuery selector could be used.

Carousel scripts are pretty basic. You need a set of items to rotate through, a container to hold the items, and a frame to mask off the ugly parts. Some basic styling is used to line the items up in a row. The container is given a postion of absolute so it can be freely moved left and right and a large width to hold all of the items inside. The frame needs the overflow property set to hidden to mask out the items that we don’t want the user to see. To pull off the animation we use jQuery’s handy animate() method for the left and right positioning of the container element. This lets us set a key point and jQuery will handle the interpolation from the current value to the key point. Attach this function to a next and previous button and you’re ready to go with your own custom carousel that works the way you want it to.

How A Carousel Works

It was a lot of fun to create a brand new site from scratch without any legacy content or rigid CMS. Simple websites are fun! And if you haven’t checked out the fruits of both of our labors, then please immediately proceed to KristinaNaude.com.

Super Mario Kart JavaScript Version

In case the JavaScript version of the original Super Mario game got a bit boring, Nihilogic has redone Super Mario Kart in much the same way. Weighing in at a mere 11Kb this proof concept lets you choose your driver (Mario, Luigi, or the Princess) and one of two courses. There is no collecting coins, knocking out opponents with turtle shells, or even counting laps. You can use the arrow keys of your keyboard to steer around a simple loop course over and over again until the end of time. The computer controlled drivers help keep up the pace though you can pass right through them as there is no collision detection.

Music is included to add to the nostalgia of the old SNES days. There’s not much else to this except to prove what can be done with modern JavaScript when applied to interactive games.

Play a JavaScript version of Super Mario Kart

Hot Or Not For XHTML Code

Valentin Agachi’s XHTML Challenge takes the rating meme under the hood letting users compare websites based on their (X)HTML markup. When a challenge is set up between two sites, a PHP script from XHTMLChallege.com slurps up the source code and begins a detailed analysis. Facets for competition include which doctype was declared, validation, content length in bytes, a ratio of content/markup/ and whitespace, use of conditional comments, and the number of table tags used.

XHTML Challenge Screenshot

As I have written about before, there is more than just HTML that goes into making a sexy source. I think XHTML Challenge could expand their analysis to include the number and positioning of CSS and JavaScript files, use of microformats (which results in more semantic, though bulkier, markup), and total file size of all components. This would paint a better overall picture of all the necessary components that go into a modern design.

Frontend web developers, like myself, take a lot of pride in how we structure our code. HTML coding is all about semantic, well-organized markup that is as small as possible while providing a solid structure for the content. It is good to see that there are others out there like myself that can appreciate the thought and planning that goes in to the under pinnings of a modern website.

XHTML Challenge should not be confused with Command Shift 3 which rates the aesthetics of a site not its code. Maybe the two sites should get together producing the ultimate website rating tool!

via (Web Designer Wall)

Kingkool68.com Aggregates All Of My Web Activity

I finally finished kingkool68.com this weekend. The purpose of the site is to aggregate all of my activity on the web into one single stream, commonly referred to as a lifestream. To mash all of my RSS feeds of activity together I used SimpleLife, a WordPress adaption of the SimplePie PHP script. For the front end I used jQuery, a JavaScript library, as well as standard HTML and CSS.

Screenshot of kingkool68.com

Most lifestreams I saw didn’t include a way to for end users to filter out certain items, so I built one into my lifestream application. Using the power of CSS selectors built in to jQuery, I wrote a function to grab the list items with a certain class and then toggle a fade effect. If the item was hidden the script would fade them in, otherwise it would fade them out. You can see the 13 lines of code I wrote to do this for yourself.

Once I finished writing the filter code I noticed it didn’t work in Safari browsers even though it performed flawlessly in Firefox. After debugging and digging around on the net for possible solutions I stumbled upon the Safari Developer FAQ. Did you know you can unlock a debugging menu in Safari? The FAQ provides details on how to reveal it and then by holding Apple+Shift+J shows a JavaScript console alerting you to any errors. I used this to figure out that you can’t use ‘class’ as a variable name even though Firefox doesn’t seem to mind. I haven’t tested the site on any version of Microsoft’s Internet Explorer which is notorious for choking on standard code.

So if you ever wanted to see everything I do on the web, checkout kingkool68.com. And if you want to add me as a friend on any of these popular sites, click the small icons associated with each item to take you directly to my profile for that site. The next step would be to package my modifications up into a WordPress plugin so anyone could run a lifestream just like mine. In the meantime if you have any problems implementing a lifestream on your own, leave a question in the comments of this post and I’ll do the best I can to help out. Happy lifestreaming!