I am parking misc. iPad development notes on this page:

3/28/12 Encountered a problem where specifying the .xib file in the Main Interface drop down in XCODE 4 for a Web App with simple interface crashed, throwing a NSUnknownKeyException. This post was helpful in understanding the problem.

These links were really helpful when setting up node.js on a standard Amazon EC2 linux instance.

The problem I set out to address with setWidth involves arranging div boxes containing various lengths of text (and some embedded photos) into columns, all of which have the same length.

Create a div box that contains two or more child div boxes of varying sizes:

</pre>
<div class="myBoxOfText">
<div>Random length of text...maybe some floating div boxes or images...</div>
<div>Random length of text...maybe some floating div boxes or images...</div>
 ...</div>
<pre>

Then use jQuery to apply the plug-in:

$(document).ready(function() {
     $('.myBoxOfText').setWidth();
});

You can download setWidth here.

You can test setWidth here.

Here is the source code:

// setWidth jQuery plug-in
//
// setWidth takes a div box that contain 2 or more div boxes, converts them to floating columns
// and adjusts the widths to make the lengths equal. The containing div box should have a
// width specified, but no height.
//
// George Campbell
// February 4, 2012
//

//
// This function takes all the div boxes in the target div box, converts them into left
// justified columns and then adjust their widths so they have the same length.
//
// The algorithm:
//   * calculate the average height of the uneven columns
//   * increase the width of over long columns by 1px
//   * reduce the width of under length columns by 1px
//   * repeat for 100 iterations
//   * Fine adjust the column heights by adjusting the paragraph margins.
//

function log() {
	window.console && console.log &&
        console.log('[setWidth] ' + Array.prototype.join.call(arguments,' '));
}

$.fn.setWidth = function(options) {
	var containerWidth = $(this).width();                 // width of the container
	var numberOfColumns = $(this).children('div').length; // number of div boxes in the container
	//
	// Set the initial widths of all n columns to the same amount, allowing for the the
	// first n-1 columns to have a 20px margin on the right side for column separation.
	//
	var initialcolwidth = (containerWidth - (numberOfColumns-1)*20) / numberOfColumns;
	var columnHeight = new Array(numberOfColumns);        // for ea. column's height
	var columnWidth = new Array(numberOfColumns);         // for ea. column's calculated new width
	for (var i = 0; i < numberOfColumns; i++) {           // initialize the columnWidth array
		columnWidth[i] = initialcolwidth;
	}
	var maxColumnLength,      // The longest column
	minColumnLength,          // The shortest column
	averageColumnLength,      // The average length
	count=0;                  // loop counter

// Iterate through each div box in the container.
// Convert plain div children to floating columns.
// The first n-1 columns get a 20px right margin.

	do {
		$.each(this.children('div'),function(index,value) {
			$(value).css({'float':'left','width':columnWidth[index]});
			if (index != numberOfColumns - 1) {
				$(value).css({'padding-right':'9px',
					          'margin-right':'10px',
					          'border-right':'1px solid #aaaaaa'});
			}

// Get the calculated height of each column
// Initialize the max and min column heights

			columnHeight[index] = $(value).height();
			if (index == 0) {
				maxColumnLength = columnHeight[index];
				minColumnLength = columnHeight[index];
			} else {

// calculate the longest column
				if (maxColumnLength < columnHeight[index]) {
                                       maxColumnLength = columnHeight[index];
                                }
// calculate the shortest column
 				if (minColumnLength > columnHeight[index]) {
					minColumnLength = columnHeight[index];
				}
			}
		});

// Calculate the average column width and amount of total change per iteration.

		averageColumnLength = (maxColumnLength + minColumnLength) / 2;
		var totalAmountOfWidthChange = 0;
		for (var i = 0; i < numberOfColumns; i++) {
			if (columnHeight[i] > averageColumnLength) {
				columnWidth[i] += 1; // Increase width for long columns
				totalAmountOfWidthChange += 1;
			} else {
				columnWidth[i] -= 1; // Decrease width for short columns
				totalAmountOfWidthChange -= 1;
			}
		}

// To keep the total width of all
// columns constant, it is necessary
// to make adjustments for the net
// amount of change in each iteration

		for (var i = 0; i < numberOfColumns; i++) {
			columnWidth[i] -= totalAmountOfWidthChange / numberOfColumns;
		}

		count++;
	}
	while (count < 100);

// End the loop after 100 iterations. Ending the loop via error minimization is tricky
// because div boxes tend to make discrete jumps in length of more than 1px when the width is
// adjusted by 1px, leading to "noise" in the error function. I discovered through experimentation
// that 100 iterations brought convergance for most practical cases.

// Now, fine tune each column's height by micro adjusting the paragraph margins.
// This loop cycles through the paragraphs in each div box, adding 1px per
// iteration until all columns are the same length as the longest column.

	log('maxheight',' -> ',maxColumnLength);
	$.each(this.children('div'),function(index,value) {
	   var colHeight = $(value).height();
	   while (colHeight < maxColumnLength) {
	      var numberOfPars = $(value).children('p').length;
	      $.each($(value).children('p'),function(indexPar,valuePar) {
	         if (indexPar < (numberOfPars-1)) {
	            var marginBottom = $(valuePar).css('margin-bottom').replace('px','');
		    marginBottom = (parseInt(marginBottom.replace('px',''))+1)+'px';
		    $(valuePar).css('margin-bottom',marginBottom);
	         }
	      });
	      colHeight = $(value).height();
	   }
	});
};

// Notes:
//
// Additional work is required. Error checking - what if there are elements besides divs
// in the container? Need a way to handle that situation gracefully.
//
// In cases where convergance is poor, it is likely the boxes are small and the
// font is large. May want to detect that situation and walk the font size up or down.
//
// Width adjustment of divs in the columns would greatly extend the
// functionality of this plug-in.
//
//

I finally wrote down the detailed steps for installing Rails a Windows 7 Professional 32 bit OS. The difficult part was getting Rails to cooperate with MySQL 5.5.

Installing Ruby Rails on Windows 7

I hope this is helpful!

Designing Software More Efficiently from the Start

Software complexity and user experience are being managed today with some new development technologies. Behavior Driven Development is a concept that you begin software development with testing, instead of testing it last. Ruby Cucumber is useful structure to implement Test Driven Design up front, and User Experience principals are part of the up front definition. I found these links particularly useful in laying out the methods.

BDD – Behavior Driven Development

Ruby Rails / Cucumber

User Interface / User Experience

I have a pile of handwritten notes accumulated while setting up Amazon EC2 Instance (virtual server) with Red Hat Enterprise Linux 6.2 and I spent this weekend organizing them into some useful procedures. Although you can set up pre-configured servers, I think it is always best to understand how to set up a server manually, especially if you want to customize it, or if you need to understand where certain settings were made.

Here are some useful links for further information.

How to install Drupal 7.10

Continuing our series on Content Management Systems, we are looking at how to install Drupal on our Amazon EC2 Red Hat Linux Enterprise 6.2 server. WordPress is really for blogging while Drupal is for managing large amounts of content. It is pretty simple to install.

Installing Drupal 7.10

$ cd /var/www/html
$ wget http://ftp.drupal.org/files/projects/drupal-7.10.tar.gz
$ tar --strip-components=1 -zxvf *.tar.gz

Now create an empty MySQL Database

$ mysql -u root -p
Enter password: [type your password]
myqsl> create database drupal;
mysql> grant all privileges on drupal.* to 'guest'@'localhost' identified by 'guest' with grant option;
mysql> use mysql;
mysql> update user set password = PASSWORD('guest') where user='guest';
mysql> quit;

Type in the IP-Address of your Amazon EWS Server in your browser.

Follow the onscreen instructions, Pressing “Save and Continue” when prompted.

You will get a message “The directory sites/default/files does not exist. An automated attempt to create this directory failed, possibly due to a permissions problem.” For security reasons, we don’t want to open our permissions wide, so we it is time to go back to the command line and enter some commands:

$ mkdir sites/default/files
$ chmod 777 sites/default/settings.php
$ cp ./sites/default/default.settings.php ./sites/default/settings.php
$ chmod 777 sites/default/files

Go back to the browser and continue the installation. When prompted for the database information:

database: drupal
user: guest
password: guest

You will have to go to Admin -> Config -> Clean URLs and turn Clean URL’s on, but that won’t work without the changes to the httpd.conf. Change the folder permission for sites/default/files back to 755 and the file permission for ./sites/default/settings.php to 644. Continue to configure the site per the instructions on the web browswer.

Clean URL’s

To enable clean URL’s, change the settings in the /etc/httpd/conf/httpd.conf to:


    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    Allow from all

CUFON

Get CUFON fonts here.

Content Management Systems – Get a Site up Fast!

The efficiency of spinning up a Web Site with WordPress, Drupal or Joomla has pushed traditional hand coded websites to the sidelines. But it still helps to have the hand coding experience to wade into these content management systems so you can quickly theme and customize them to the application’s need. Here’s my quick reference to spinning up these sites on an Amazon EC2 virtual server:

Set up an Amazon EC2 Server and then load the LAMP stack.

How to Install WordPress

$ cd /var/www/html
$ wget http://wordpress.org/latest.tar.gz
$ tar --strip-components=1 -zxvf latest.tar.gz

Now create an empty MySQL Database

$ mysql -u root -p
Enter password: [type your password]
myqsl> create database wordpress;
mysql> grant all privileges on wordpress.* to 'guest'@'localhost' identified by 'guest' with grant option;
mysql> use mysql;
mysql> update user set password = PASSWORD('guest') where user='guest';
mysql> quit;

Type in the IP-Address of your Amazon EWS Server in your browser.

Set up WordPress with the following parameters:

Database Name: wordpress
User Name: guest
Password: guest
Database Host: localhost
Table Prefix:

You will receive a message “Sorry, but I can’t write the wp-config.php file.” Now you could open the permissions wide on your /var/www/html directory, but that would be poor security practice. So we are going to manually copy the contents of the wp-config file from the browser and paste them into the file on the command line:

Copy the contents of the configuration of the box to your clipboard. Return to the command line:

$ cat > /var/www/html/wp-config.php
[paste the contents of the file you copied]
CTRL-c

Go to the browser and click “Run the Install” button. Finish filling out the forms – you are ready to go.