Forgotten Expanse http://forgottenexpanse.com Web Blog Of Curtis Herbert Forgotten Expanse http://forgottenexpanse.com/images/icon.jpg http://forgottenexpanse.com 60 60 Web Site of Curtis Herbert en Copyright {gmt_date format="%Y"} {gmt_date format="%Y-%m-%dT%H:%i:%s%Q"} The Great Wall http://www.forgottenexpanse.com/blog/permalink/the_great_wall http://www.forgottenexpanse.com/blog/permalink/the_great_wall#When:22:12:59Z The iPad has the possibility to radically change how people use and think of computers over the years to come and I’m not just talking about touch-screen technology. Sure, touch-screen technology in this large of a form-factor is going to allow for some really new interfaces, but I think there is a greater shift working behind the scenes.

One of the changes we’re seeing, first with the iPhone and now with the iPad, is the removal of the file system (at least to the end-user). With any traditional PC when you boot up the first thing you’re presented with is your file system. All your apps are (sometimes) neatly stored in one folder, your documents, photos, downloads in others. You use Finder or Explorer to navigate to the document or application you want to launch and go from there. Of course there are things in place to simplify getting to what we want, like the start menu or dock, but you still need to be aware of the file system.

But as it’s been said elsewhere, to most people the concept of a file system just makes no sense. Sure to people like me, and probably you, using a file system is a very natural thing. But we aren’t the norm. I can’t count the number of times I’ve gone over to my parents to do a little tech support and been shocked by just how messy their desktop, download, or document folder was; three copies of installers for apps in the downloads folder, a mess of documents on their desktop that really should be under ~/Documents instead. The mess of course wasn’t their fault, they just don’t get the concept of keeping a file system organized. That kind of stuff just doesn’t matter to them—they want to log on, install app X, edit document Y, do their work and be done with it.

This changes on the iPhone OS. Every app runs within a sandbox: it has it’s own set of documents, settings, etc, but it can’t access the documents in another app. There is a wall between every app. Part of this was implemented for security reasons, now apps can’t hurt each other or delete other stuff they shouldn’t have access too. But it also simplifies some tasks. When you want to install an app you just do—no installer, no .DMG file. When you want to delete an app and all it’s stuff just tap-and-hold then click the little X. So much easier to manage.

It shifts the iPhone/iPad to be more app-centric rather than document centric. You don’t go into your documents and find that Numbers file you were working on. You launch numbers and you see a list of your Numbers documents. No more “oh where did I save that file to…” problems.

I for one welcome the death of the file system on mainstream computers. Especially ones my parents use.

This has a setback though, one I can only assume the brains at Apple are aware of, and hopefully working on (maybe with the iPhone OS 4.0 release?). This wall between the apps makes it harder to move documents between them. Each app has to be able to email or export its own files. Email seems to be the popular method to move things around at the moment. It worked great on the iPhone because no one really used the iPhone as their main computer—exporting was always to get it back to their desktop. But the iPad can (or will over time) replace said desktop for many people and now you have to be able to move documents between apps.

Apple started to address this with their media browser. All the apps they have save images into the Photos app. And any app can use the media browser to get to that store of photos. So right now it’s really easy to move an image from the internet into Pages on the iPad. Try to move anything else around and you’ll soon hit a dead-end. What happens if I get a bunch of documents into an app that I later want to switch away from (media-format combadability aside)? If it doesn’t have an export feature I’m screwed. Even if it does I can email them to myself, but it isn’t like Mail supports an “open with” option to tell it to open in the new app.

It’s a tricky problem that they’ll have to solve at some point I think. But in the mean time I think the direction they’re taking things is a net win for the majority of computer users.

]]>
Apple, 2010-04-05T22:12:59+00:00
Memory Leaks In jQuery Dialogs http://www.forgottenexpanse.com/blog/permalink/memory_leaks_in_jquery_dialogs http://www.forgottenexpanse.com/blog/permalink/memory_leaks_in_jquery_dialogs#When:15:37:08Z The Problem I've spent the last week optimizing a lot of our JavaScript code at work. We rely heavily on jQuery there (a great framework!) and it's partner in crime jQuery UI for some of our UI widgets. Part of my optimizing including tracking down some of the memory leaks we've been seeing on the site with extended use, especially in IE (surprise!).

After tracking down quite a few closures and fixing those up, I was still left with 10 meg leaks here and there. After a bit I tracked it down to every time we used a dialog from jQuery UI's library.

Our helper function was pretty simple -- allow the code to specify the title and the text, and optionally provide a callback function that'll be called with what they clicked to close the dialog. The dialog would pop up on the screen and gray out the background forcing the user to interact with the alert box. I was concerned because we rely on modals quite a bit, especially in the edit pages. A 10meg leak per dialog shown would quickly add up to 100,200,300+megs leaked over the course of a normal session.

I removed a lot of the surrounding code, making sure I wasn't leaking memory in my own code. I was left with a pretty simple use of the dialog use:

function AlertDialog(dialogTitle, dialogText, callbackFunction) {
    // dynamically generate and add a div so we can create the pop-up
    $('body').append("
" + dialogText + "
"); // define/configure the modal pop-up $("#alertDialog").dialog({ draggable: false, resizable: false, modal: true, buttons: { 'OK': function() { if (callbackFunction != undefined) { callbackFunction('OK'); } //remove the default beforeclose event and trigger the close $("#alertDialog").unbind('dialogbeforeclose').dialog('close'); } } }).bind('dialogbeforeclose', function(event, ui) { // Close (X) button was clicked; NOT the OK button if (callbackFunction != undefined) { callbackFunction('cancel'); } }).bind('dialogclose', function() { $('#alertDialog').dialog("destroy").remove(); }).dialog("open"); }

Despite all my efforts I couldn't get the leak to stop. Simply opening the alert would cause it, so I figured it wasn't my callback function. Frustrated I changed the modal option to false. Bam, no more memory leak in IE! How could this be? So I tried playing around with the appearance of the modal in their CSS file. I tried setting the background property to a GIF instead of a PNG, since IE is terrible with PNGs, with no luck. I tried removing the opacity filter in the CSS with no luck too. Turns out it's just how jQuery UI generates the gray background behind the dialog that causes the leak.

The Solution

The solution was to never use the modal: true setting in our use of the dialog boxes. I instead wrote two helper methods that would be used to gray out the UI and block interaction with anything but the alert.

HTML:
CSS:
#BlockUI 
{
    position: fixed;
    display: none;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 600;
    background: url(/Resources/grayout.gif);
}
JavaScript:
var blockCount = 0;

function BlockUI() {
    blockCount++;
    $('#BlockUI').show();
}

function UnBlockUI() {
    blockCount--;
    if (blockCount <= 0) {
        blockCount = 0;
        $('#BlockUI').hide();
    }
}

With this I had a common method for triggering a grayed-out background effect. The GIF I used was a checker-board pattern one, alternating between a light gray color and a transparent pixel. One could use a solid PNG with it's alpha set to something around 50%, but I wanted IE6 compatibility. The difference between the two is minimal.

With that in place I just needed to update the dialog to trigger the block and unblock calls. JQuery UI's dialog lets you specify a function for the "open" option which will be called when the dialog opens.

function AlertDialog(dialogTitle, dialogText, callbackFunction) {
    // dynamically generate and add a div so we can create the pop-up
    $('body').append("
" + dialogText + "
"); // define/configure the modal pop-up $("#alertDialog").dialog({ draggable: false, resizable: false, modal: false, open: function() { BlockUI(); }, buttons: { 'OK': function() { if (callbackFunction != undefined) { callbackFunction('OK'); } //remove the default beforeclose event and trigger the close $("#alertDialog").unbind('dialogbeforeclose').dialog('close'); } } }).bind('dialogbeforeclose', function(event, ui) { // Close (X) button was clicked; NOT the OK button if (callbackFunction != undefined) { callbackFunction('cancel'); } }).bind('dialogclose', function() { $('#alertDialog').dialog("destroy").remove(); UnBlockUI(); }).dialog("open"); }

And with that the memory leak was fixed. It's not ideal to have to rely on custom-code to get around the leak, but until jQuery UI is fixed to avoid this it's the best work around to make sure IE doesn't bloat like crazy when you use modals.

]]>
Development, 2010-01-22T15:37:08+00:00
Assassin’s Creed 2 http://www.forgottenexpanse.com/blog/permalink/assassins_creed_2 http://www.forgottenexpanse.com/blog/permalink/assassins_creed_2#When:20:47:23Z
cover

The first Assassin's Creed was a major disappointment, I think few will argue that fact. The original largely boiled down to a game engine with lots of promise but nothing to draw you into the game beyond that. The repetition was mind-numbing, the plot was a joke. I never actually finished the game, I got about 2/3 of the way through it.

After the bad taste the first left in my mouth you can imagine by reservation when Assassin's Creed 2 came out. But this time I was not disappointed; instead I was finding myself unable to put the controller down. Assassin's Creed 2 is the perfect sequel: it took everything that was weak about the first and improved it.

What a difference a plot can make. The first one had a plot but it wasn't a personal plot. You were just a tool of a larger war between two factions being told to go kill boss X and Y. In between bosses they didn't even try to hide that you were doing the same thing over and over again. You always had ~9 smaller missions before the boss, which were always of the same type. In Assassin's Creed 2 it is actually personal and diverse. You start out not knowing a thing about Assassins or Templars (heck you spend most of the game not caring about that), you're just a guy whose family is attacked and you go after the killers in revenge (sweet stabby revenge). You're going around killing people because you want to, not because you're told to. And everything in between killing bosses doesn't feel like repetitive kill X, pickpocket Y, loot treasure Z. Sure it boils down to that in the end, but it doesn't feel like that at all. The game flows so well.

The asides from the plot are vastly improved too. If you find yourself wanting a distraction from the revenge-plot there is plenty to do this time around beyond just climbing around. You can help out in the cities with various assassination and beat-the-cheating-husband up style missions that reward you with money. Partway through you get your own villa which you can chose to sink money into. Doing so gets you the warm fuzzy feeling (also helps the place stop looking so run-down) but also makes upgrades cheaper as you spend money to upgrade your blacksmith. Plus as you upgrade your villa more and more it will start generating money for you every 20 minutes.

This money comes in handy as there is a full weapon and armor system in the game, finally. There are quite a few classes of weapons you can choose to carry around, from daggers to swords to maces, all of which cause you to fight a little differently. Along with weapons and armor there are plenty of little upgrades too, like additional medicine pouches and knife-slots that really help out later in the game. There are six Prince-of-Persia style jump-puzzles (Assassin's Tombs) you can do if you want the best armor in the game.

For the obsessive-collectors they kept plenty to do in the game that requires running around everywhere trying to find things. Most importantly you have hidden glyphs you can seek out (with small hints as to where in the cities they are) that help unlock something within the game. There are hundreds of treasure chests around the city, and a side-quest where you need to find 100 feathers in memory of someone in your family. You can try to buy all the paintings available as part of the side-quest to restore your villa to its former glory.

They added in a notoriety system for the second game. It tracks your notoriety per-city and really helps you gage how cautious you need to be around guards. And now there is finally a way to lower your notoriety if you care: running around ripping down wanted posters, bribing town criers, or killing city officials. And when you are running from guards they're a lot more intelligent with their chase, they'll actually look for you in hiding spots sometimes. This makes it feel much more realistic instead of just having them give up once you jump in some hay.

One can tell that they really learned from the shortcomings of the first game and made sure they didn't exist in the second. A complaint I had was the rebounding-off-walls controls. There were a few times it would have me jump off in a different direction then I was going for, but this really only showed itself during the more difficult jump-puzzles (the most inopportune time for it to happen). The combat wasn't vastly changed in the sequel, it was still a bit of well-timed button-mashing, but it didn't really detract from the fun of the game.

Without a doubt Assassin's Creed 2 was a wonderful game and well-worth the time I sank into it. It's what the first game should have been. I'm glad to see Ubisoft pull a 180 with this game and really produce something with such high quality. And fortunately it ends with a pretty cool twist leaving it open for a third (which they've already said will happen).

]]>
Games, 2010-01-01T20:47:23+00:00
Moving From Apache to Lighttpd http://www.forgottenexpanse.com/blog/permalink/moving-from-apache-to-lighttpd http://www.forgottenexpanse.com/blog/permalink/moving-from-apache-to-lighttpd#When:18:29:28Z Recently I moved away from Apache and to Lighttpd for my web servers to better handle load, especially in a low-memory environment like a VPS.  Resources were somewhat scattered when I was trying to get it set up the way I wanted it so I wanted to document the process.

Getting Started

This tutorial assumes you’re running Debian or Ubuntu.  Most commands in this tutorial are going to require root privileges, so sudo or su to your heart’s content.  Lets get started.

First lets get all the packages we’ll need for the install:

apt-get install lighttpd php5-cgi build-essential php5-dev bzip2

Note: at time of writing spawn-fcgi was part of the Lighttpd package, but in SVN was moved out to its own project. You might need to download the spawn-fcgi package (at this point I don’t know what its name will be, but do an apt-cache search spawn-fcgi and you should find it easily).

If you didn’t have Apache on your system previously, you’ll need to create a group and user for the various services to run as.  I stuck with the default Apache one “www-data”.

Setting Up Spawn-fcgi

The standard configuration I saw referenced when setting up Lighttpd was to have it spawn off PHP processes as needed. Lighttpd would control how many processes were spawned, how many children each process supported, etc. With a minor amount of tweaking one is able to get a go-between set up between the PHP processing and the server. I prefer this set-up because then if something needs to change with your PHP configuration you don’t need to take down the whole web server. Plus, if you want to be paranoid, you can further sandbox PHP and have it run as a user independent from Lighttpd.

The first thing that has to be done is to create a script that will spawn off a Spwn-fcgi process with the appropriate arguments that we can reference later:

vi /usr/bin/php-fastcgi
#!/bin/sh
/usr/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -C 5 -u www-data -f /usr/bin/php5-cgi

Save and close the file then you need to make it executable:

chmod +x /usr/bin/php-fastcgi

When this script is executed it will set spawn-fcgi to listen on the local IP and listen on port 9000.  It will spawn off 5 PHP processes and have them run as the www-data user.  You can tweak the port/user/number of children as needed.  The one you might want to play around with is the number of processes; I found 5 to handle plenty of load (90k views in a day) within a 512meg VPS.

Now we need something to kick off this script when the server starts, and a way to restart it when we make changes.  We’ll make an init script:

vi /etc/init.d/fastcgi
#!/bin/bash
PHP_SCRIPT=/usr/bin/php-fastcgi
RETVAL=0

case "$1" in
    start)
          $PHP_SCRIPT
          RETVAL=$?
  ;;
    stop)
          killall -9 php5-cgi
          RETVAL=$?
  ;;
    restart)
          killall -9 php5-cgi
          $PHP_SCRIPT
          RETVAL=$?
  ;;
    *)
       echo "Usage: fastcgi {start|stop|restart}"
       exit 1
  ;;
esac    
exit $RETVAL

Save and close the file and then run:

chmod +x /etc/init.d/fastcgi
update-rc.d fastcgi defaults 

This script will allow you to call /etc/init.d/fastcgi stop|start|restart like you would Apache/Lighttpd/Mysql/any other daemon.  The last command ran, update-rc.d, will add this script to the normal startup scripts so when you restart the machine PHP is brought back online without having to do anything manually.

Go ahead and kick off the daemon now, we’ll need it for Lighttpd in the next section:

/etc/init.d/fastcgi start

Hooking Spawn-fcgi up with Lighttpd

With all the PHP work out of the way we can hook up Lighttpd now. Go ahead and open up it’s configuration file.

vi /etc/lighttpd/lighttpd.conf

First we need to have it load the fast cgi module.  Find the module section towards the top of the file (you’ll see a bunch of “mod_xxxxxx"s) and make sure mod_fastcgi is in that list and not commented out.

Next we need to tell Lighttpd how to access the PHP processor, in our case spawn-fcgi.  If you remember from earlier we set it up to listen on the local IP and port 9000, that’s all the info we need to give Lighttpd. So add the following to the bottom of the configuration:

fastcgi.server = ( ".php" =>
  ( "localhost" =>
    ( "host"        =>     "127.0.0.1",
      "port"        =>     9000
    )
  )
)

While you’re in here make sure you update the web root to point to where your site is currently living — probably /var/www.

Save and close and you’re done.  Restart the Lighttpd daemon to pick up the changes:

/etc/init.d/lighttpd restart

Now you have a web server with PHP running.  To test this create the following file in your web root and load it through a browser:

eAccelerator

Now that everything is running through Lighttpd lets get caching up and running using eAccelerator (similar to APC).  eAccelerator provides post-compile caching of your PHP code which will greatly increase performance of your site. It’s one of the first things I lay down when I’m setting up a PHP install. As of writing the latest version is 0.9.5.3, make sure to check the homepage for any updates and use the latest version.  It is a manual install, but goes very smoothly:

cd /tmp
wget http://bart.eaccelerator.net/source/0.9.5.3/eaccelerator-0.9.5.3.tar.bz2
tar xvfj eaccelerator-0.9.5.3.tar.bz2
cd eaccelerator-0.9.5.3
phpize
./configure
make
make install

With eAccelerator installed we just need to configure it.  Open up its configuration file…

vi /etc/php5/conf.d/eaccelerator.ini

And add the following to it:

extension="eaccelerator.so"
eaccelerator.shm_size="16"
eaccelerator.cache_dir="/var/cache/eaccelerator"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
eaccelerator.compress="1"
eaccelerator.compress_level="9"

Save and close the file. Anything you add inside the conf.d folder in the PHP config will automatically be loaded when PHP goes to run.  Now you need to create the cache folder for eAccelerator (as specified the path in the configuration file you just created).

mkdir /var/cache/eaccelerator
chmod 777 /var/cache/eaccelerator

And that’s it, eAccelerator is ready to go.  Restart the PHP process:

/etc/init.d/fastcgi restart

With that in place you’ll see a dramatic difference in the number of requests per second your server can handle.

You can confirm that is it working by going back to the PHP info page you created above.  Do a search for the string “eAccelerator” on the page and you’ll see a section on it.

Done!

And with that you have a working Lighttpd server in place of Apache, with PHP accelerator and everything. I’ll be taking this further with virtual hosts, server-side compression, how to replace .htaccess files, and content expiration in a future post.

]]>
Development, 2009-07-15T18:29:28+00:00
Slimming The Server http://www.forgottenexpanse.com/blog/permalink/slimming-the-server http://www.forgottenexpanse.com/blog/permalink/slimming-the-server#When:01:16:21Z Server load can be a hard thing to deal with especially when, in my case, your peak loads occur during only six days of the year.  The server will hum along for the rest of the year without issue, no indication of the impending and inevitable doom just around the corner.  Then your server gets Slashdotted, or in my case the Nike Outdoor Nationals happen.

Last year I migrated the NSSF server to a VPS with 512megs of RAM.  VPSs are a great option for someone wanting some of the benefits of a dedicated box (root access, set it up as you see fit, etc) but doesn’t want to pay ~$250+ a month for the dedicated hardware.

But with the great freedom of a VPS or dedicated box comes new issues you used to not have to worry about on a shared/managed host.

During the last two meets we’ve been running into a problem — the high load of people refresh-monkeying for results and photos of their kids for two days was making the server choke (80k+ pageviews a day; nothing amazing but certainly not a light load for a single-server operation).  At the first meet in March I spent the weekend learning about Apache optimization for high load and updating the server’s configuration to meet the swarm of parents and track enthusiasts descending upon our server.  Of course the optimizations were bounded by the need to run within 512 megs of RAM, along a MySQL instance.  We survived the storm, but the site’s response times weren’t ideal under that load.

It wasn’t until the second meet, held last weekend, that I got to realizing that maybe the solution wasn’t in tweaking Apache, but rather ditching Apache.  Now don’t get me wrong, Apache is great and has been my server of choice for six years, but it is a beast.  Apache is meant to do everything and because of that isn’t ideal for low-memory-footprint environments that come under heavy load.  Yes, more RAM would help, but I’m not the kind of guy that just throws more hardware at a problem when I can do something to fix it.  Open-heart surgery, not a band-aid that comes attached to an additional monthly fee, was in order.

I’d heard of Lighttpd before; the servers at Meebo run on it.  It’s a very lightweight server that has a small footprint and runs wonderfully under very high loads.  So during the first morning of the two-day meet, when Apache was crying in a corner just wanting people to leave it alone, I went about installing Lighttpd.

Within 30 minutes I had Lighttpd ready to go, hooked up using FastCGI for PHP, with the main site running within it on a test port.  Usually one doesn’t switch things like this during peak traffic, but desperate times… I flipped the metaphorical switch and shut down Apache and brought Lighttpd up in its place on the public port.

Wow.

Even with only minimal tweaking to the configuration the difference in page response time was comparable to night and day.  It felt like the server was under normal load even though we were at our peak traffic for the year!  Plus the server went from 80 megs of RAM open with Apache running to 140 megs (which later went up to 200 megs with more tweaking) open with Lighttpd running.  Small footprint indeed.  A few more minutes of work and I had all the other domains and subdomains back up as well.

Lesson learned: don’t be afraid to switch from the norm.  Sure, Apache is pretty much the standard when it comes to a LAMP server, but that doesn’t mean it’s what you have to stick with.  In this case Lighttpd had what I needed most: performance, and it didn’t require me sacrificing any functionality I’d come to rely on with Apache.

]]>
Development, 2009-06-23T01:16:21+00:00
Trek http://www.forgottenexpanse.com/blog/permalink/trek http://www.forgottenexpanse.com/blog/permalink/trek#When:01:18:33Z Star Trek 2009

In short: go see it.  I went in with high expectations and wasn’t disappointed.

[Minor Spoilers]

Sure, there were a few plot holes (but, lets be honest here, that’s nothing new for Trek), and way too many lens flares, but it felt like Star Trek and that is really what mattered.  And it was fun, something I think the franchise lost some time ago.  It washed the bad taste of the last two movies and the last two shows out of my mouth.

The biggest complaint I’ve see so far has been with the use of an alternate universe to reboot everything.  I really have to disagree with those who think it “pisses all over the original continuity” — I argue they went out of their way to acknowledge the original work.  The movie didn’t just ignore the original work and do what it wanted (we already have one Mirror Universe, why not just make another?), it came up with a plot that allowed it to split off gracefully.

It was very fun, the actors portrayed the characters wonderfully (Scotty and Bones were awesome), and visually beautiful.  And best of all it’s Nemoy-approved.

Looking forward to the inevitable sequel, which better have some bad-ass Klingons.

]]>
Film, 2009-05-12T01:18:33+00:00
Semantically Delicious Address Form http://www.forgottenexpanse.com/blog/permalink/semantically-delicious-address-form http://www.forgottenexpanse.com/blog/permalink/semantically-delicious-address-form#When:11:46:09Z Last time I went over my new pattern for forms.  It’s continued to serve me well so far, so I wanted to dig a little deeper into some more complex form layouts.

One input per line is pretty common for a form online.  However it’s not always the best-looking; sometimes it really improves the usability of your form to have inputs grouped together visually.  A great example of this is an address form.  Having one line per input (city, state, zip, etc) takes up a lot of vertical room and leaves for a lot of wasted horizontal space.

Cleanly marked up address form

The layout for an address form I’ve decided on is above.  It’s good to leave plenty of room for address line 1 and 2 — they’ll usually contain lots more information than any other field.  City, on the other hand, is usually pretty short, as are the state, postal code, and country options.  As such I’ve gone with grouping city and state on one line, and then postal code and country on the last.

The first two lines are simple, pretty much just follow the same formatting from the previous post (note I’m assuming the final CSS from last post is active):

<fieldset>
<legend>Contact Information</legend>
<ol>
	<li><label for="address1">Address<span class="error"> *</span></label>
	      <div class="inputWrapper">
	      <input type="text" id="address1" name="address1" value="" size="50" />
	      <label for="address1">Address Line 1</label><br />

	      <input type="text" id="address2" name="address2" value="" size="50" />
	      <label for="address2">Address Line 2</label></div></li>
</ol>
</fieldset>

Pretty simple start.  We’re just having two inputs and labels within the inputWrapper div.  One item I’m not 100% on: I have two labels pointing to the first address prompt.  Both the main label, “Address:”, and the label under the input, “Address Line 1”, point to it.  Not sure if there is allowed to be multiple labels per input, but in this case it’s the markup I’m happiest with.

Anywho with the simple stuff out of the way let’s think about the remaining items.  At this point my paranoia sets in — I want to avoid floats if possible when dealing with multiple inputs on the same line to make sure floating doesn’t get in the way later.  So no wrapping each group (input/label) in a div and floating the divs.  Fear not, there is an equally as simple way to do this.

We’ll have two lines of items (per group): the inputs and then the labels.  We can follow the same basic format as have previously, we’ll just have to make everything inline and limit the width.  With them inlined we can use fixed widths to ensure that the labels line up under the inputs as we want (note CSS is inline to keep this simple, you should bring it out into classes where possible):

<fieldset>
<legend>Contact Information</legend>
<ol>
	<li><label for="address1">Address<span class="error"> *</span></label>
	      <div class="inputWrapper">
	      <!-- Address -->
	      <input type="text" id="address1" name="address1" value="" size="50" />
	      <label for="address1">Address Line 1</label><br />

	      <input type="text" id="address2" name="address2" value="" size="50" />
	      <label for="address2">Address Line 2</label><br />

	      <!-- City/State -->
	      <input type="text" id="city" name="city" value="" size="11" style="width: 200px; display:inline; margin-right: 30px;" />
	      <select name="state" id="state" style="width: 175px; display:inline;">
	          <option value="" selected="selected"></option>
	          <option value="AL">Alabama</option>
	          ...
	          <option value="WY">Wyoming</option>
	      </select><br />
	      <label for="city" style="width: 227px; display:inline;">City</label>
	      <label for="state" style="width: 175px; display:inline;">State / Province / Region</label><br />

	      <!-- Postal Code/Country -->
	      <input type="text" id="postalcode" name="postalcode" value="" size="11" style="width: 200px; display:inline; margin-right: 30px;" />
	      <select name="country" id="country" style="width: 175px; display:inline; ">
	          <option value=""></option>
	          <option value="CA">Canada</option>
	          ...
	          <option value="US" selected="selected">United States</option>
	      </select><br />
	      <label for="postalcode" style="width: 227px; display:inline;">Postal / Zip Code</label>
	      <label for="country" style="width: 175px; display:inline;">Country</label></div></li>	
</ol>
</fieldset>

And that’s it.  Not too bad once you take a second to read over it.  From here you can easily extend the pattern for any other multi-input group like first name/last name, etc.

]]>
Development, 2009-04-16T11:46:09+00:00
Semantically Delicious Forms http://www.forgottenexpanse.com/blog/permalink/semantically-delicious-forms http://www.forgottenexpanse.com/blog/permalink/semantically-delicious-forms#When:03:58:13Z I’m continually revisiting my XHTML markup to remove all the excess crud and try to get it semantically correct while keeping the markup flexible and stylish.  I think I’m finally happy with the pattern I follow for form markup.  Back in the old day you’d just wrap a table around the whole thing and be done with it.  However using that method the markup doesn’t actually represent the data; a form isn’t a table of data.  The table tag was just an easy way to get the page to look right.  Now we have better ways.

Basic Form Layout

First lets start with the basic XHTML that will represent our form.  Thinking about the basic structure you’ve got a list of fields with labels where order of these inputs is important.  These are often grouped together into logical sets of inputs — one group on the page covering the account information, the next group covering the contact information, etc.

Pretty straight forward, right?  So, following those concepts, the XHTML would look like this for a form with just two inputs:

<form action="/signup" method="post">
<fieldset>
<legend>Basic Information</legend>
<ol>
<li><label for="name">Name</label><input type="text" id="name" name="name" size="30" /></li>
<li><label for="dob">Date of Birth</label><input type="text" id="dob" name="dob" size="10" /></li>
<li><label for="gender">Gender</label><select id="gender" name="gender">
    <option value=""></option>
    <option value="female">Female</option>
    <option value="male">Male</option>
    </select></li>
</ol>
</fieldset>
</form>

Most of that markup should be familiar except maybe the fieldset and legend tags since they are often left out when people create forms.  The fieldset tag groups a set of inputs together to show it is logically related and the legend is essentially a caption for that fieldset.  In the past developers would perhaps use header elements in between groups of data to separate them.  Doing it this way not only visually separates and groups the inputs but it also does so in the markup itself.

I’ll repeat the fieldset/legend/ol group as often as needed on a page for different sets of inputs that belong together and I want visually divided on a page (contact info vs basic info, etc).  Add an li for every input I need within a grouping.

Why ols and lis?  I’ve seen other sites out there that prefer to use the dd and dt tags to define the list of inputs.  I believe that the list tag more closely represents the data: there is no “definition” relationship between an input and it’s label.  The relationship is defined by the “for” attribute on the label; you shouldn’t need to define the relationship beyond that.

Next we need to apply some basic styling to the form.  Personally I prefer the labels aligned left with the inputs to the right.  In addition I prefer the inputs lined up neatly going down the page.  To accomplish this I started with the following:

fieldset { 
    margin: 0 0 20px 0; } 

fieldset legend { 
    font-weight: bold; 
    font-size: 16px; 
    padding: 0 0 10px 0; 
    color: #214062; } 

fieldset label { 
    width: 170px; 
    float: left; 
    margin-right:10px; 
    vertical-align: top; } 

fieldset ol { 
    list-style:none; 
    margin: 0;
    padding: 0;} 

fieldset ol li { 
    float:left; 
    width:100%; 
    padding-bottom:7px; 
    padding-left: 0; 
    margin-left: 0; } 

fieldset ol li input, 
fieldset ol li select, 
fieldset ol li textarea { 
    margin-bottom: 5px; } 

Just a few basic things going on here.  The fieldset and legend styling sets up how I personally like things to look — a 20px margin between fieldsets and in this case I have a dark blue legend at the top of each fieldset.  The ol and li styling ensures that the default nature, indented with numbers, is ignored for the list leaving me to style is as I please.  Then the label floating left with a margin ensures that all the inputs make a nice neat line going down the page to the right of the labels (170 pixels in, in this case).  If you prefer to have the labels above the input instead of to the left you could just remove the float.  Lastly the margin on the bottom of inputs ensures some spacing after the field.

One last part to tweak before the basic form is done.  The above code will work perfectly if you have some kind of CSS reset in place.  By default the fieldset element has a border and adds a padding around its conents.  If you don’t have a CSS reset in place (why don’t you?) you’d modify the fieldset element in the CSS like so:

fieldset { 
    margin: 0 0 20px 0; 
    border: 0;
    padding: 0;} 

That markup leaves you with:

What the basic structure looks like

Descriptions and Required Fields

So that’s the basic set-up, but forms are rarely that simple.  One of the first items I wanted to add was a description for a field; just a little bit of text below the field to help the user out.  Adding the text by itself after the input field results in an undesired look: the text will end up under the label instead of under the input.  To combat this we need to add a wrapper element around the input and description and then make sure the entire element is moved to the right the appropriate amount.  The changed XHTML and new CSS when adding a description to the Date of Birth field is:

<li><label for="dob">Date of Birth</label>
    <div class="inputWrapper"><input type="text" id="dob" name="dob" size="10" />
    <span class="note">YYYY-MM-DD</span></div></li>
form fieldset div.inputWrapper { 
    margin-left: 180px; } 

.note { 
    font-size: 0.9em; color: #666; }

The “note” class is just a convention I use it to specify text that should be a bit more subdued than normal text.  In the same vein I use an “error” class to denote error messages and required field markings.  We’ll use that to add the standard asterisks for noting the fields are required:

<li><label for="dob">Date of Birth <span class="error">*</span></label>
    <div class="inputWrapper"><input type="text" id="dob" name="dob" size="10" />
    <span class="note">YYYY-MM-DD</span></div></li>
.error{ 
    color: #d00; }

The IE Factor

IE treats legends a little differently than all the other browsers.  Most browsers, using the CSS and XHTML just written, will just put the legend above the group of inputs.  IE will do that but not without adding it’s own flair.  It will intent the legend a few pixels.  I prefer to have the legends and fieldsets to look as they do in all the other browsers:

To remedy this you need an IE fix in the header of your page:

<!--[if IE]>
<style type="text/css" media="screen">
legend {margin-left: -7px}
</style>
<![endif]-->

This will cause any IE browser to align the legend with the rest of the labels as opposed to indenting it a bit.

The Final Look With Markup

Cleanly marked up form

The form is now marked up and should be stylish in all browsers (even that pesky IE).  The complete code for this markup is as follows:

...
<!--[if IE]>
<style type="text/css" media="screen">
legend {margin-left: -7px}
</style>
<![endif]-->
...
<form action="/signup" method="post">
<fieldset>
<legend>Basic Information</legend>
<ol>
<li><label for="name">Name <span class="error">*</span>
    </label><input type="text" id="name" name="name" size="30" /></li>
<li><label for="dob">Date of Birth <span class="error">*</span></label>
    <div class="inputWrapper"><input type="text" id="dob" name="dob" size="10" />
    <span class="note">YYYY-MM-DD</span></div></li>
<li><label for="gender">Gender <span class="error">*</span></label>
    <select id="gender" name="gender">
    <option value=""></option>
    <option value="female">Female</option>
    <option value="male">Male</option>
    </select></li>
</ol>
</fieldset>
</form>

And the CSS:

fieldset { 
    margin: 0 0 20px 0; } 

fieldset legend { 
    font-weight: bold; 
    font-size: 16px; 
    padding: 0 0 10px 0; 
    color: #214062; } 

fieldset label { 
    width: 170px; 
    float: left; 
    margin-right:10px; 
    vertical-align: top; } 

fieldset ol { 
    list-style:none; 
    margin: 0;
    padding: 0;} 

fieldset ol li { 
    float:left; 
    width:100%; 
    padding-bottom:7px; 
    padding-left: 0; 
    margin-left: 0; } 

fieldset ol li input, 
fieldset ol li select, 
fieldset ol li textarea { 
    margin-bottom: 5px; } 

form fieldset div.inputWrapper { 
    margin-left: 180px; } 

.note { 
    font-size: 0.9em; color: #666; }

.error{ 
    color: #d00; }
]]>
Development, 2009-02-20T03:58:13+00:00
SyntaxHighlighter 2.0 http://www.forgottenexpanse.com/blog/permalink/syntaxhighlighter-20 http://www.forgottenexpanse.com/blog/permalink/syntaxhighlighter-20#When:02:50:45Z While working on some new posts I noticed that the ever so popular SyntaxHighlighter just released version 2.0.  The new version eliminates my main grip that it required invalid XHTML to work.  Previous versions worked by specifying the name of an element to highlight.  The problem was the tag it used, PRE, wasn’t allowed to have a name attribute.  Now it uses a much more elegant solution through css classes.

Installed it on here tonight and it works very nicely.  Fair warning this will probably cause some more code-heavy posts later.

]]>
Aside, 2009-02-10T02:50:45+00:00
A Media Center PC: Nico http://www.forgottenexpanse.com/blog/permalink/a-media-center-pc-nico http://www.forgottenexpanse.com/blog/permalink/a-media-center-pc-nico#When:21:12:00Z My AppleTV has served me well over the past two years.  I hacked it to enable support for other formats (AVI, etc) and to browse files stored on my file server (as opposed to just ones I bought in iTunes); ATVFiles is useful to that end.  But its support for MKV and OGM files (frequently used for anime and now Bluray files) was massively lacking and it just doesn’t have the processing power to decode 720p or 1080p video (unless it was purchased from iTunes), a major limitation with the advent of Bluray titles.

A month or so ago XBox Media Center was made to work on an AppleTV and I started playing around with that.  I was always turned off by its default skin but the new one, Media Stream, is very slick and even rivals the AppleTV’s wonderful interface.  Above and beyond ATVFiles XBMC supports the concept of a media library; complete with meta-data about all shows and movies in your library.  Add all that to the wonderful timing of a fresh version coming out in November and I felt the desire, no the need, to upgrade.

The hardware for the project was easy to pick out aside from the motherboard since I want to go for an integrated graphics chip if I could find one with the power I needed.  I also knew I wanted the computer to have a small footprint so I went with a MicroATX setup this time around: a nice Intel Core 2 Duo at the heart of it, a Intel motherboard with HDMI port and a sweet integrated graphics chipset with on-board decoding of popular Bluray codecs, reasonably attractive case, 1 Gig of RAM, Seagate HDD (SSDs just aren’t cheap enough yet), and a Media Center Edition remote.  Already reasonably cheap, having a birthday around the time I wanted to build it helped bring the cost down even more.  Parts in hand assembly was easy although tight being a MicroATX case and all.  Although not perfectly silent like my last media PC (a price I knew I’d pay for using a MicroATX case — those tiny fans bite you in the ass) one can only hear it when everything else in the room is off so I’m happy with the results.

Originally I was going to put Windows XP on it but I ran into an odd bug where XBMC would play back standard files somewhere around one frame every five seconds.  Using VLC I had no issues.  The XBMC forums confirmed this is a bug but they don’t know what exactly is causing it (in November when I tried XBMC on the gaming box XP I had no issues).  Remembering how much of a pain Linux can be to get audio-out over optical working, especially with newer chipsets, I figured I’d see if Vista would work out.  I knew going into this Vista was going to be a world of hurt but my options were limited.

Loading Vista and getting XBMC working went without much trouble, but I had to spend a lot of time A) working through Vista making me want to reformat the PC and battle Linux to get audio working and B) screwing with the remote to get it to work right.  Two pieces of software helped with this: IR Server Suite and Event Ghost.  IR Server Suite works to translate the IR codes sent by the remote to system events and Event Ghost listens in the background for when an event happens (button pressed, system comes back from sleep, etc) and runs commands.

With regards to A Vista seems to not deal with mapped network drives the way I’d expect it to.  Whenever I boot up or resume from sleep it would complain it couldn’t reconnect the drive, but as soon as I double-clicked the drive letter it’d open up and be fine.  I had to do this specifically through Explorer.  Odd.  So I had to set Event Ghost to launch (and the promptly close) an Explorer window for that drive whenever the system boots or comes back from sleep.

With regards to B IR Server Suite went a long way to getting everything working perfectly.  Just set up the mappings in XBMC’s keymapping.xml file and it all worked.  Except for when you resume from sleep.  Every couple resumes the remote would stop working (except for the arrows, those worked).  Turned out Input Service was crashing (even though I went in and set that service to restart if it crashed) and I had to manually stop and start the service to get it to pick up the remote again.  Of course this had to be done before XBMC was launched or else XBMC itself wouldn’t see the remote.  So I have Event Ghost set to kill XBMC when the system goes to sleep, and then I have Even Ghost set to run a bat script that restarts the Input Service and then launch XBMC.

To make things sync up nicely (since XBMC can’t monitor a folder for new files and automatically add them to the library) I set XBMC to automatically scan for new content on launch (and because of those Event Ghost settings that is every time I wake the pc on to use it).  I’ve also mapped a key on my remote to manually trigger an update incase I need to.  I debated having a script running on the file server that would notify the media pc whenever a file was added, but that’d only be ideal if I was going to leave the media pc on all the time, as opposed to making it sleep whenever I’m not using it.

Turned out to be a bit more of a project than I expected on the software configuration side, mainly because I had to move to Vista, but we watched the Bluray version of Serenity in last night.  It was beautiful and made the project worth it.

]]>
2008-12-22T21:12:00+00:00