Selecting the Next Table Row

If you find yourself with a table of alternating rows, first a visible summary row followed by a hidden detail row, then selecting the next table row is a piece of cake. You may need to do it for any number of reasons, too. For starters, you may want to only turn on the "expand" icon in the summary row if there is actually data in the detail row. We will assume that the detail row contains div.something if there is actually data there. [js]$("table tr:visible").each(function() { ($(this).next().is(":has(div.something)") && $(this).find("img.expand").show()); });[/js] That will select the visible rows in the table and iterate over them. It will check each one to see if it has the div we are looking for and if it does, it will show the expand image. We are taking advantage of the fact that there are all function calls and using short circuit evaluation of the conditional to not run the argument after the && if it fails. One of my favorite Stupid Javascript Tricks. You may also want to actually show and hide the table when the expand icon is clicked. Also pretty easy to do. [js]$("table tr img.expand").click(function() { $(this).closest("tr").next().toggle(); });[/js] That will toggle the table row following the one containing the clicked expand icon. Pretty straightforward stuff, thanks to jQuery.

Auto Select the First Form Element

This is an easy one that I have been asked about a number of times before. I always recommend that you wrap your content area in a containing div to separate it from other portions of the page. Namespacing your DOM will keep your javascript and css from bleeding over into other panels unexpectedly. Hence the div#content. So, to automatically select the first element in the form on your page, all you need is this: [js]$("div#content form :input:visible:first").focus();[/js]If you want the first empty element, then you just need to change it to:[js]$("div#content form :input:visible:first[value='']").focus();[/js]You may be wondering why I did :input:visible instead of just :text, and that is because I want to get any input elements that are on the screen, not just text inputs. Using :input will return input, textarea, select, and button elements. Adding :visible will not only filter out visibly hidden forms, but also type='hidden' input elements as well.

Constructing a Selector Friendly DOM

Your markup is extremely important not only for the display of your application, but also for the complexity and stability of your javascript. There are three important tenets to building a selector friendly DOM.

1. Keep it Lean!

I cannot stress the importance of the markup of your pages enough. Some people think of the markup as being just the browser's input feed, but it is actually much more than that. It is the data model for a face of your application and has three separate but related users: the browser, the javascript, and the css.

Building your markup with all three of these in mind will make your selectors a lot cleaner and easier to work with. Adding DOM elements that aren't necessary will negatively impact all three of these aspects, so just don't do it. Whatever the reason for adding them to begin with, remove them if you don't need them anymore. Having extraneous stuff in there will also hurt our next bullet.

2. Be Consistent!

Your DOM needs to be consistent. This starts with understanding what all the tags actually are and what they are intended for. For example, a "p" tag is for paragraphs. Are you making a paragraph when you use it? If not, then you may want to consider using something else that is better suited. A "div" is for defining a logical block of elements on the screen. A "table" is for displaying tabular data. If you are using it for your page layout, shame on you!

Having a consistent way of creating your DOM will make it a lot easier to write generic selectors. You can't select all the rows in your form cleanly if some of them are wrapped in paragraphs and some are wrapped in divs.

3. Namespace!

Namespace the major portions of your page. It will allow you to write javascript and css that is specific to a portion of the page and will prevent unintended bleed over into other portions of the screen. The simplest example is a typical page layout with a header, left panel, and content pane. Each of these are unique elements on the screen and should have an id. Every selector that is intended for only that piece should then begin with "div#content" or whatever.

Ids and classes aren't just for css, either. If it makes sense, add a class to the elements that you want to select with your javascript even if it is never mentioned in the css. Those attributes are designed for use with selectors and since we use selectors heavily in both css and javascript, it is perfectly acceptable to add them for one or the other or both.

Also, if an element is meant to be totally unique on the screen, like your content pane, use an id instead of a class to distinguish it. By their nature, ids are unique on the screen and classes are for mass assignment, so using them appropriately gives you one more piece of metadata when interacting with your DOM.

MacBook Pro Hard Drive Replacement

The 120GB hard drive on my 15" MacBook Pro 2.16 Core 2 Duo has been teetering on the edge of full for a while now and I finally decided to go ahead and swap it out with a bigger and faster drive. One of the questions I had going into this was whether the SATA 3.0Gbps drives would work on the 1.5Gbps controller that is built into the motherboard. As it turns out, they work just fine. Here are the steps I took to replace the drive:
  1. I bought a 320GB Western Digital Scorpio Black from Newegg along with an external enclosure.
  2. Put the new drive in the enclosure and connected it to the Laptop.
  3. Formatted and used Carbon Copy Cloner to copy my existing hard drive onto the new one. It took a couple of hours to complete.
  4. Followed the instructions on ifixit.com for replacing the hard drive. It looks intimidating, but was actually really easy. Just don't lose those tiny screws!
That was it. I booted the computer back up when everything was back together and it works like a champ. Everything is as it was before I replaced the drive and the computer is running much faster than it was before.

The Danger of Unobtrusive Javascript

Unobtrusive javascript is a great practice to follow. Having pages that can fall back to real links and requests if javascript is unavailable is a great safeguard. The thing is, though, that we sometimes don't really expect things to be invoked that way. It is just a fallback, right? We may forget to test screens down the road that are never supposed to be used like that. You know, like that form that is always rendered through ajax into a modal window.

You are being a good web developer and using jQuery or Prototype or whatever and have all your event handlers attached in the DOM onload. What that also means is that someone on a slow internet connection might take a few seconds to load your page. During that time, if they click any of your anchor tags with hrefs that are supposed to invoke ajax calls, it will actually browse to the page since the onload hasn't been executed yet.

So, they click that link and bam! There they are at some page that was supposed to render in a modal window and now looks ridiculous as an actual page since you haven't seen it that way in a dozen iterations. Whoops!

What Kind of Developer are You?

I always hear people described as being a back-end guy or a front-end guy. Really, I think those terms are a little ambiguous and can be a little misleading. Or worse, you can get pigeon-holed into one or the other and then people don't trust you with half of the system.

At my current gig, I am generally regarded as a "front-end guy". That is largely because when I started working on the web application there, the whole thing was in shambles. I mean, it worked and generated a ton of revenue, so in that sense it was a success. However, the UI looked ridiculous, the code left a lot to be desired, and the page load performance was abysmal. I was constantly on my soap box about it and so the title stuck.

The problem with the application wasn't that the developers were not good. In fact, that company had a great collection of fantastic developers. The problem was actually two fold. From the development side, there was never anyone on staff who was a real expert on how to assemble a web stack. On the business side, no one really knew how to design a web front end and there was no graphic designer anywhere in the company.

If you are working on a web application stack, everyone needs to be a front-end and a back-end guy. The fact of the matter is that it is a front-end application and even though it has a front-end and back-end portion, most likely everyone is working on every part of the application. I know I have always worked on the whole stack, from top to bottom. These days, my knowledge base is weighted towards the presentation layer, but I have my fair share of experience creating database schema, building ORM mappings, writing nightly scripts, setting up and deploying servers, etc. I feel totally comfortable doing that stuff and enjoy it just as much as I do making wild UX implementations.

It is natural that some people are better at certain aspects than others. Some people are jacks of all trades and decent at each layer. Anyone who can only work on one layer though, is probably having a tough time finding a job or, if they're lucky, is coasting at a BDC.

I think one of the key factors of success is knowing and embracing your identity. Despite what anyone thinks I am, I am a front-end application developer who works the whole stack, but has special expertise in the presentation layer. It works really well when I am paired with someone who is the exact opposite and is a front-end-application developer who works the whole stack, but has special expertise in something that I am not an expert in.

Right now I am working on a real back-end system. No application container, no presentation layer, just a lean and mean environment for doing an incredible amount of heavy duty processing. It really is coming together as a great system thanks to the team and especially the tech lead, who is an elite developer/architect. I feel like I am making a meaningful contribution, despite my unofficial title as the front-end guy. The best part about it though, is that I get to work with some really fantastic people who have skill sets that compliment mine and can teach me lots of new tricks.

So, what kind of developer are you?

Dynamic Positioning with jQuery

I have been working on a few sprints lately that require some javascript to do dynamic positioning of a DOM element on whatever was just clicked on the screen. Here is a sample of some of that code. It assumes that there is an element, a.some_link, that when you click it the dynamically positioned element, #DP, places itself just to the right and centered vertically. It will also detect if positioning to the right will cause it to be off the screen and flip it to the left side instead. The only CSS requirement is that #DP be "position: absolute;". [js]$("a.some_link").click(function() { //Get the coordinates of the clicked element. var cellPosition = $(this).position(); //Add the left displacement to the width of the trigger, //placing the DP just to the right of it. var horizontalPosition = cellPosition.left + $(this).outerWidth(); //Here is the fancy part. If the position plus the width of your DP //if greater than the window width, change the position to the left //side of the trigger. if (horizontalPosition + $("#DP").outerWidth() > $(window).width()) { horizontalPosition = cellPosition.left - $("#DP").outerWidth(); } //Center your DP vertically on the trigger. var verticalPosition = cellPosition.top - ($("#DP").outerHeight() / 2) + ($(this).outerHeight() / 2); //Update the position of your DP. $("#DP").css({top: verticalPosition, left: horizontalPosition}); });[/js] Also note that if you were to call "animate" instead of "css" in that last call, then it would animate the movement instead of just snapping it to the new position.

Apple Airport Extreme Update - Lesson Learned

Tonight I updated the firmware on my Airport Extreme to version 7.4.1. When the device went to restart, I shut off the Airport Utility software and went about my business. I quickly found that my Airport was rendered completely useless by this update. After power cycling the router a few times and rebooting my Mac, I still had no luck. I could connect wirelessly but not access the internet. I could connect via the Airport Utility, but couldn't bring up the management screens because of an error "-5" saying something about not being able to read the configuration.

As it turns out, shutting off the Airport Utility during the middle of a firmware update will ruin the configuration on the router. If you update the configuration and cause it to restart, you can shut it down just fine. Doing an update to the firmware is a different case though. I ended up having to hold down the small unlabeled reset button on the back of the device for 5 seconds with it plugged in to reset the configuration on the device and now it is up and running again. Of course, I had to redo all my settings. Not too big a deal though.

After that, I updated my Airport Express to test my theory about shutting off the software. This time, I let it run all the way through before I shut it down and the firmware applied just fine and the device worked again right away.

You'll learn something new every day if you aren't careful.

How to use a sqlite3 database in your iPhone app

Using a sqlite database in an iPhone app is actually really easy. The only real requirement to get started is that you need to create a sqlite database to include, which is very easy to do.

Step 1 - Create the Database

Make sure you have it installed. If you don't have it, it is available through MacPorts. Once you have it, just type on the command line:

sqlite3 test.sqlite3

This will create a new database called "test.sqlite3" and set you up in the sqlite prompt. You will need to create your tables here. For this example, just type:

CREATE TABLE iphone_test ( id INTEGER PRIMARY KEY, value VARCHAR(255) );

Now you need to put some data in it:

INSERT INTO iphone_test (value) VALUES ("This is value 1"); INSERT INTO iphone_test (value) VALUES ("This is value 2");

Not too bad so far. Now just type .quit and you are all set. Copy your database into the Resources folder of your Xcode project and you are ready to move on.

Step 2 -Prepare Your Project

You need to link the sqlite3 framework library to your project. All you need to do is right-click on the Frameworks folder and select Add > Existing Frameworks... then select:

/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/usr/lib/libsqlite3.0.dylib

Step 3 - Add Some Code to Your AppDelegate.h

Open up your AppDelegate.h and add an import for sqlite3.h so you can use sqlite. Then this declaration inside your @interface so you have a nice handle to the database:

sqlite3 *database;

Then add these prototypes for the methods we are adding to the AppDelegate.m:

- (void)verifyDatabase:(NSString *)databaseName databasePath:(NSString *)databasePath;

- (NSString *) randomRecordContent;

Step 4 - Add Some Code to Your AppDelegate.m

Open up your appDelegate.m and add this method in somewhere. This will make sure that the database file exists in the user's file store and if it doesn't, it will copy it over from your application code.

- (void)verifyDatabase:(NSString *)databaseName databasePath:(NSString *)databasePath { NSFileManager *fileManager = [NSFileManager defaultManager]; if (![filemanager fileExistsAtPath:databasePath]) { NSString *databasePathFromApp = [[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName]; [fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil]; } [fileManager release]; }

Then add this code inside your applicationDidFinishLaunching method to get the location of the database in the users phone:

NSString *databaseName = @"test.sqlite3"; NSString *documentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex: 0]; NSString *documentsPath = [documentsDir stringByAppendingPathComponent:databaseName];

Now call the verifyDatabase method to copy the database from your app code to the users file store in case it isn't already there.

[self verifyDatabase: databaseName databasePath:databasePath];

Open the database so you can use it throughout your application:

sqlite3_open([databasePath UTF8String], &database);

Don't forget to close the connection in your dealloc method:

sqlite3_close(database);

Finally, add in a method that will read something from the database. In this case, we are adding the implementation of randomRecordContent that we specified in the header.

-(NSString *) randomRecordContent { NSString *theValue; const char *sqlStatement = "select value from iphone_test order by random() limit 1"; sqlite3_stmt *compiledStatement; if (sqlite3__prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) { while (sqlite3_step(compiledStatement) == SQLITE_ROW) { theValue = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)]; } } sqlite3_finalize(compiledStatement); return theValue; }

Now you are all set. As long as you have a handle to your AppDelegate, you can call this method and grab something from the database. For example, if you are in your view controller you can get a handle and call the method like this:

YourAppDelegate yourAppDelegate = (YourAppDelegate *)[[UIApplication sharedApplication] delegate]; NSString theValue = [yourAppDelegate randomRecordContent];

So there you have it. Hopefully that code is pretty readable. Please post comments or e-mail me if you have any questions.

What Does It Mean To Be a Rock Star?

What does it really mean to be a good developer? Human Resources will go ballistic when they read this, but being good does not have to do with years of experience or technologies listed on your resume.

Sorry to break that news, but it is the truth. Now, I am not saying that those two things are irrelevant or meaningless, but they are only a very small part of a much bigger picture. I have been on both sides of the interviewing table and have seen dozens of senior developer applicants with 10+ years of experience not be able to write simple for loops. It is absurd.

So what makes a developer good? I think it is a combination of a number of things. It is hard to pinpoint in an interview, which is why so many people take the easy route of the two items mentioned above.

It starts with a passion for problem solving. Most, if not all, good developers started very young and were initially self taught. They have a real passion for figuring out difficult problems. Even though this exhibited at a young age, it is something that is ingrained in their personalities and will continue through their professional careers. These are the people that work on side projects after hours. They are probably trying to push the envelope at their day jobs and introduce new technologies into the code base. Programming isn't just something they do to pay the bills, it is a way of life. They think about it constantly. It probably drives their wives crazy (I know it does mine).

So what does this mean? It means that the years of professional experience listed on the resume is only a small portion of their programming career. Someone in this category who is two years out of school has really been programming for over a decade.

So how about that long list of technologies that the applicant knows? Very impressive. They were able to list all the industry buzz words...even ones no one cares about any more like PowerBuilder!

The other major element of a good developer is being able to learn new technologies easily. With the way the technical landscape changes, it is a necessary part of the job. People that eat, sleep, and breathe programming will not have any trouble picking up whatever web framework or ORM technology your operation uses. They won't be scared to dive in and start playing. In fact, chances are they will be a productive member of the team within a couple of days, even having never used that specific technology before.

I am not saying that they will immediately be an expert, but being able to answer some high level questions in an interview doesn't mean that the "senior developer" with that bullet item on his resume will be able to actually produce anything.

So the resume is barely worth the weight of the digital copy. The vast majority of resumes I have seen are showcases of years of experience and the applicants ability to regurgitate all the technologies they have heard of. So please, when you are shopping for good developers, see if you can look past the paperwork and see the developer inside. That goes for the seniors as well as the n00bs.

Oh, and don't use years of experience as a cover for age discrimination. It is absolutely reprehensible.