Wednesday, June 4, 2008

A Simple YUI-Powered Accordion Widget

Accordion menus are all the rage at the moment (as are Carousels and Sliders). I wanted a snazzy way to show my resume during my recent job search so I went looking for an accordion-style menu. I had these requirements in mind:

1) be lightweight
2) use unobtrusive Javascript techniques (ie not have scattered Javascript all over the markup)
3) use simple CSS to make it look nice
4) needed to support both single and multiple sections opened at a time.

My search came up short. Most were overly complicated, or they required libraries other than what I already have running on my sites. Too much bloat. I guess I'd have to write my own. Since I already use the *radical* YUI libraries on my sites, making it YUI-powered was the way to go for me. I set my goal to <100 lines of good OO unobtrusive Javascript. The current version sits at 80 LOC with lots of comments. Here's what it looks like:
**note that the size of the menu is dynamic, however to embed it in a blogger post I had to use the ol <iframe> trick.

JILS_accordion will make an unordered list <ul> of your choice into a spiffy animated accordion menu. These are the steps to get it going on your site:

Massage the Markup:


While any <ul> will work, you need to make sure it has an id.
Next you need to create two divs inside of each <li>. One div for the title with class accordionTitleDiv, and one for the content with class accordionContentDiv The markup should look like this:
*Note it is not necessary for the individual <li> elements to have id's

Include the JS & CSS Files, initialize the JILS_accordion object:



The first argument for the constructor function is an object that can be left empty '{}' or you can specify things like {multiSelect:true, sectionExpandedSize:10}, etc. The code is heavily commented so most front end guys will be able to figure it out.

Open accordion example in a new page

Updated to v 1.1b following a heads up from Satyam that the widget was broken in IE. Turned out to be a different bug. A 'dangling' comma after the last item in my callback object definition was the culprit, but I still wrapped the init methods using YAHOO.util.Event.onDOMReady() -- just in case. Thanks Satyam!

Update #2 v1.2b A few performance tweaks: Switched to using the YUI aggregate file utilities.js, which includes everything we need in one line AND loads faster with a single HTTP request. Updated the initializing code to show how onDOMReady() can be used as an alternative to onload(). YUI's onDOMReady() makes sure the DOM is ready to go, but doesn't wait for images to be loaded for a snappier page load. The last tweak was to the default animation speed... now with 1/2 the Saturated Fat!

Thursday, May 29, 2008

One step Universal Binary builds Compatible with 10.3 PPC with Xcode (for reals)

Dang. That was a long title. An alternate title could have been: how to misread Apple's Cross Development documentation.

Anyway, when I upgraded my main development system to Leopard 10.5, my Xcode 2.4 projects worked beatifully with Xcode 3.0. I didn't change anything, and builds were still working fine in 10.4 and 10.5. Alas, 10.3.9 users weren't having much luck with my builds. Hrmm...

I double checked the project and target build settings. The target SDK no longer read 10.3, instead 10.4u was selected. Disclaimer: I have no idea if this was something that happened by default, or if I had changed this at some point when I was still running 10.4.

Oh well, so I chose the 10.3.9 SDK for cross-development and tried building. No dice. A bazillion errors. Most notably:

stdbool.h:8: error: #error "This header only supports __MWERKS__."

Some more keyword fiddling with the Googles, and this thread saved the day. A helpful Apple engineer shed some light on the subtleties of Universal Binaries, 10.3, and PPC machines. In the same thread, a poster noted that Lipo was not necessary, just some special "Per-Architecture" Xcode build settings. Turns out adding per-architecture settings is now even easier with Xcode 3.

To build your app as a UB that is compatible back to 10.3.9 on PPC machines set Base SDK Path (Under Target...Build...Build Locations) to 10.3.9 for PPC and 10.4u for Intel.

Your Target's build settings should end up looking something like this:

Note: if you already set the Base SDK Project-wide to be 10.4u, then you can just add a Per-Architecture setting for PowerPC at the Target level.

Now you'll be able to compile just fine on Intel because you'll be using 10.4u, but PPC machines on 10.3.9 will still be able to run your app. Remember to be careful to use 10.3.9 APIs.

Thursday, May 22, 2008

Xcode 3.0 Snapshots: Notes on Repository Location

Man, I love this new feature. Being able to diff files to any of my previous Snapshots is superb. Being able to roll back changes on a single file or over the entire project is even better. I find I give myself more freedom to try new things because I know I have a good clean (compiling) Snapshot to fall back to. Scotty's Xcode Quick Tip is a great place to learn more about them.
--
I wanted to make sure that I was backing up the Xcode snapshot sparse image, so I went looking for it. Currently, Apple's docs say the file should be here:
~/Library/Application\ Support/Apple/Developer Tools/Snapshot Repository


Well, the location in the current documentation is wrong, the disk image really is here:
~/Library/Application\ Support/Developer/Shared


I've also found that the defaults command for changing the location of this magical disk image doesn't work for me on Xcode 3.0. Anybody have any tips?
defaults write com.apple.Xcode XCSnapshotRepositoryPath /Volumes/Backup/Xcode\ Snapshots/

Wednesday, May 14, 2008

Tip for Failed Time Machine Restore


So I recently went through a two day ordeal caused by both a dying hard drive and my cheapness. A parade of software failures like this one should be written down for posterity anyway. Read on for some tips on what to do and what to avoid if your Time Machine restore fails as spectacularly as mine did...

When my MacBook started beachballing during heavy disk IO, I looked in the logs and found several tell-tale kernel[0]: disk0s2: 0xe0030005 (UNDEFINED) messages. I suspected an imminent HDD death so I deleted a few newly created files that I knew were damaged, and ran Time Machine one last time. Things went OK. After running TechTool Pro and verifying that I did indeed have bad blocks (5 to be exact!), I figured that I might still put off buying a new hdd by choosing the "Zero All Data" option and reformatting the drive. Sure enough, several hours later, I had zeroed the drive and received a clean bill of health from TechTool's surface scan.

Next I tried booting the Leopard DVD and running a Time Machine restore. It wasn't that easy since my TM volume lives on an unsupported share on my 10.4 Client file-serving G4. Time Machine couldn't find the drive and never offered me to connect to any servers. Manually mounting the drive didn't help either. The Join button remained greyed out. I had no choice but to pull the drive from my server and hook it up to the MacBook since Target disk mode also failed spectacularly. Apparently a boot raid in a Gig-Ethernet G4 will cause Target disk mode to "fall through". I was still calm at this point, since I was using a totally unsupported method to have a networked Time Machine.

OK, so I copied the sparse bundle to a single drive and copied along the two "." files that seem to go with TM's system just in case. I rebooted with the Leopard DVD and it happily found my Time Machine! I hit restore and let it to its thing for a couple of hours. When it finished up, I hit restart and held my breath. The MacBook restarted, and then restarted again, and then restarted again. No amount of pram zapping, option key-holding trickery would break the loop.

I was pretty beaten down by Technology at this point so I took a break to drink a beer. I decided that I'd try to do a clean install of Leopard and give the Migration Assistant a shot since it now offers Time Machine support.

I yet again formatted my drive, partitioned for Boot Camp and clean installed Leopard. After the install I created a temp account and matched the system up to the same 10.5.2 OS via Software Update.

I fired up Migration Assistant and told it I wanted to use Time Machine. It, however, claimed to not find any Time Machines. YARGH! OK, so I figure I'd mount the sparse Image and see what happens. As soon as I finished mounting the image, Migration Assistant updated its list and offers to pull from this mounted Time Machine dmg! I selected the user accounts and told it to copy over everything. About 1.5 hours later it reported success. I skeptically logged into my old user account and everything seems perfect! Success? Could it really be? Well, it was, for a few minutes.

I decided to push my luck and try to also restore my Boot Camp partition from a backup made with the great WinClone. Unfortunately I was a total dumbass and made the partition 1 GB too small. When I enlisted Boot Camp Assistant to return my drive to a single Mac OS volume, I received a success message... but then when I tried to re-partition for Boot Camp, I received a series of strange error messages. I did a stupid thing and rebooted. TOTAL FAILURE. Turns out Boot Camp Assistant wiped out my partition table.

Another over-night format and restore session finally yielded a working MacBook. Here's the no-whining summary:


    If your bare-metal restore fails or refuses to show up when booted from the Leopard DVD follow these steps:


  • Partition your drive *exactly how you want it*
  • Clean Install Leopard
  • Create a temp account with a non-colliding name to use for updating your OS to match what is on Time Machine
  • Mount the Time Machine sparseImage .dmg in the Finder (if your backup volume is a local HFS+ disk, this step doesn't apply)
  • Launch Migration Assistant.




You might just end up with a working Mac like I did. Oh, try to avoid all the massive pitfalls I ran into, especially with Boot Camp Assistant. No offense Boot Camp team, but I've deemed this app beta, because of this mishap and another in the past --both resulting in totally destroyed partition tables and hours of time from my life!