the inspiration

First and foremost, I'd like to give credit to Johnny Lee's "_____" will "_____" you. This project was inspired by his, and is essentially a direct copy.

I wasn't inspired by the idea behind the site as much as I was by the program. As I try to learn PHP/MySql better, I look for little projects wherever I can find them. When I first saw Lee's site, I figured it was simple enough that I could recreate it, but still teach me some useful programming. I was initially going to rip-off his front-end code and create my own backend that would read and write entries from a database. Then when I actually looked at his front-end code, I realized that his program was pretty flawed. The site was created in 2005 so the poor coding is certianly excusable, but I figured it's time for a more elegant solution. Plus, let's be honest, the ads at the bottom are tacky.

Every time someone lands on his page, Lee's program loads 400 random entries from the database and outputs them into a static javascript array. The nice little fade rotation just randomly pulls one of those to display. If you stay on the page for long enough, all that you'll ever see are the same 400 entries rotating over-and-over. It certainly gets the job done, but isn't very efficient. Also, why overload both front-end and backend processses to retrieve more entries than most people will ever see?

"What if you could load entries one at a time, immediately before they get displayed?" I thought.

the solution

The simple answer: AJAX.

The longer answer:

the php

I knew I was going to try to use AJAX to call the entries onto the page, but first I had to be able to receive entries from users. I created a simple php form with two fields, the "I am" part, and the "the" part. I pass the inputted values back into the same script, do some minor validation (mostly security and length-checking), and enter the values into a single database table. The homepage then reloads with the entry you just submitted proudly displayed at the top. Very simple stuff.

Retrieving a random entry from the database was probably the most time consuming part of the project. Though I'm not too familiar with efficiency when it comes to MySql queries, I was hoping to use what I assumed were simple, lightweight scripts. Rather than loading the entire db table and randomly pulling out one of the results, I would choose a random row id, and retrieve just that single entry. The only problem is that even at this stage in development, I had entered and deleted a number of test entries, so my rows didn't all have consecutive ids. They started out something like 3, 4, 8, 10, etc. So the function needed to take into account that the id might not exist, and if not, try again.

What I came up with was the following.

function randomRow($result='') {
	if($result=='' || mysql_num_rows($result)!=1) {
		$randId = rand(0,getMaxId());
		$query = "SELECT *
			FROM mytable
			WHERE id = {$randId}
			LIMIT 0,1";
		$result = mysql_query($query);
		$result = randomRow($result);
	return $result;

randRow is a recursive function that first checks if the query result exists, and if not, chooses a new id by random and starts over. Once the query result actually returns with a valid row, the function quickly returns that result and unravels from it recursion stack (or whatever you'd call that). getMaxId (referenced when selecting a random id) is a function that simply grabs the largest id out of the db. It helps ensure that the random id is at least a number within the range of values in the database.

What you end up with is a single random row.

the jquery

The jquery plugin I used for the text fade is called InnerFade. Simple, I just plugged it in and changed some of the default parameters, and it started working.

On a slightly unrelated side note, I spent a lot of time on this step researching an option that would allow the text to have a dynamic height. Unfortunately, I wasn't able to come up with one. All jquery slider & fader & slideshow plugins I found require you to set a defined height. The fade is accomplished by overlapping two elements and changing their opacities. In order to accomplish the overlap, each element needs to be absolutely positioned within their parent container. The parent container won't stretch vertically to accomodate its absolutely positioned child elements. If you have any suggestions on how to fix this, please

the ajax

This is the first time I've ever used ajax, so I followed tizag's ajax tutorial to set up the basic function. When the function is called, it simply activates a server-side script that uses the above randomRow php function to echo out a single entry. But the challenge was to figure out where to call the ajax function.

Though it took me a long time to figure out, the solution was simple. I added the function call inside the innerfade function where the fade transition is triggered. Basically, the jquery innerfade works by cycling through all of the <li> tags in an unordered list, and displaying them one at a time. I hard-coded two list items into the area where the entries display, and initially hardcoded a single entry into each (using randomRow of course). When you first load the page, those are the first two entries you see. As soon as the innerfade function is triggered for the first time and the second list item begins to appear, the ajax function is called after a short delay. While the first list item is hidden, a new random entry is grabbed from the db, and using the javascript function innerHTML, that entry is inserted into the first list item before it begins to reapper. When innerfade is triggered a second time, it loops back and shows the first list item again, which is now the new random entry. No more than two entries ever exist in the front-end at once. The fader continues to cycle between the two <li>'s which continue to get updated with each cycle. Brilliant.