	jQuery.fn.slidingBillboard = function(autoDelay) {
		return this.each(function() {
			
			var speed = 900;
			var postClickDelay = -1;
			
			var root = $(this);
			var rootId = root.attr('id');
			$(root).addClass("slidingBillboard");
			$(root).data('timeout_id', 0);
			$(root).data('inuse', false);
			$(root).data(
				"config", {
					// endless_scroll: true,  /* Something to add later if I want to disable endless scrolling. */
					collection: $(root).find('li')
				}
			);
			
			
			// Get the total number of swappable items.
			var numItems = $(root).find('li').length;
			
			// Add auto Ids and classes
			$(root).find('li').each(function(itemIndex) {
				var i = itemIndex + 1;
				
				// If an item does not have an ID add an auto generted ID to it.
				var itemId = $(this).attr('id');
				if (itemId == '' || itemId == undefined) {
					$(this).attr('id', String(rootId+'SwapImg'+i));
				}
				
				// Add the Ids used for quickjump ctrls.
				$(this).addClass('jb'+i);
				$(this).data('jbId', i);
			});
			
			// Hide all but one element (randomly selected).
			// var rand = Math.ceil(Math.random() * numItems);
			// Force the first element to be displayed first.
			var rand = 1;
			
			$(root).find('li:not(:nth-child('+rand+'))').hide();
			$(root).find('li:nth-child('+rand+')').addClass('open');
			
			// Mark the starting images quick jump button.
			jbShowClass = '.'+rootId+'-jb'+rand;
			$(jbShowClass).addClass('open');
			
			
			var prevClass = '.'+rootId+'-prev';
			var nextClass = '.'+rootId+'-next';
			
			var autoNext;
			if (autoDelay) {
				autoNext = function(uid) {
					$(nextClass).trigger('click');
					return true;
				};
			} else {
				autoNext = function() {};
			}
			// $.doTimeout(rootId, autoDelay, autoNext);
			$(root).data('timeout_id', setTimeout(autoNext, autoDelay));
			
			
			// Previous Button
			// ==================================================================
			$(prevClass).each(function() {
				var prevButton = $(this);
				var entrySelector = $(root);
				
				prevButton.bind('click', function(objEvent) {
					if (!$(entrySelector).data('inuse')) {
						// $.doTimeout(rootId);
						clearTimeout($(root).data('timeout_id'));
						
						// Make the navigation buttons unusable while processing the action.
						$(entrySelector).data('inuse', true);
						
						// Get the config data out of the button.
						var objConfig = $(entrySelector).data("config");
						
						// Get the currently open list item.
						var jCurrent = objConfig.collection.filter(".open");
						
						// Get the pervious item.
						var jPrev = jCurrent.prev();
						
						// Check to see if we got the previous item successfully
						if (jPrev.attr('id') == undefined) {
							
							// We're here because the button was clicked a
							// second time before the animation completed.
							// Return false so we don't loop back to the end.
							if (jCurrent.attr('id') != $(entrySelector).find("li:first").attr('id')) {
								return(false);
							}
							
							// We reached the first item in the list.
							// Loop back to the end.
							jPrev = $(entrySelector).find("li:last");
						}
						
						// Hide the showing image.
						jCurrent.removeClass('open');
						jCurrent.hide("slide", { direction: "right" }, speed);
						
						// Mark the clicked item as open.
						for(var j = 1; j <= numItems; j++) {
							var jbHideClass = '.'+rootId+'-jb'+j;
							$(jbHideClass).removeClass('open');
						}
						jbShowClass = '.'+rootId+'-jb'+jPrev.data('jbId');
						$(jbShowClass).addClass('open');
						
						// Show the previous image.
						jPrev.addClass('open');
						jPrev.show("slide", { direction: "left" }, speed, function () {
							// Set the navigation buttons as useable again.
							$(entrySelector).data('inuse', false);
							
							// $.doTimeout(rootId, autoDelay, autoNext);
							$(root).data('timeout_id', setTimeout(autoNext, autoDelay));
						});
					}
					
					// Prevent default event (form submit).
					objEvent.preventDefault();
					return(false);
				});
			});
		
		
			// Next Button
			// ==================================================================
			$(nextClass).each(function() {
				var prevButton = $(this);
				var entrySelector = $(root);
				
				prevButton.bind('click', function(objEvent) {
					if (!$(entrySelector).data('inuse')) {
						// $.doTimeout(rootId);
						clearTimeout($(root).data('timeout_id'));
						
						// Make the navigation buttons unusable while processing the action.
						$(entrySelector).data('inuse', true);
						
						// Get the config data out of the button.
						var objConfig = $(entrySelector).data("config");
						
						// Get the currently open list item.
						var jCurrent = objConfig.collection.filter(".open");
						
						// Get the pervious item.
						var jNext = jCurrent.next();
												
						// Check to see if we got the previous item successfully
						if (jNext.attr('id') == undefined) {
							
							// We're here because the button was clicked a
							// second time before the animation completed.
							// Return false so we don't loop back to the end.
							if (jCurrent.attr('id') != $(entrySelector).find("li:last").attr('id')) {
								return(false);
							}
							
							// We reached the first item in the list.
							// Loop back to the end.
							jNext = $(entrySelector).find("li:first");
						}
						
						// Hide the showing image.
						jCurrent.removeClass('open');
						jCurrent.hide("slide", { direction: "left" }, speed);
						
						// Mark the clicked item as open.
						for(var j = 1; j <= numItems; j++) {
							var jbHideClass = '.'+rootId+'-jb'+j;
							$(jbHideClass).removeClass('open');
						}
						jbShowClass = '.'+rootId+'-jb'+jNext.data('jbId');
						$(jbShowClass).addClass('open');
						
						// Show the previous image.
						jNext.addClass('open');
						jNext.show("slide", { direction: "right" }, speed, function () {
							// Set the navigation buttons as useable again.
							$(entrySelector).data('inuse', false);
							
							// $.doTimeout(rootId, autoDelay, autoNext);
							$(root).data('timeout_id', setTimeout(autoNext, autoDelay));
						});
					}
					
					// Prevent default event (form submit).
					objEvent.preventDefault();
					return(false);
				});
			});
			
			
			// Quick Jump Controls
			// ==================================================================
			for(var i = 1; i <= numItems; i++) {
				var jbClass = '.'+rootId+'-jb'+i;
				$(jbClass).each(function() {
					var jbId = jbClass.replace('.'+rootId+'-', '');
					var jumpButton = $(this);
					var entrySelector = $(root);
					
					jumpButton.bind('click', function(objEvent) {
						if (!$(entrySelector).data('inuse')) {
							// $.doTimeout(rootId);
							clearTimeout($(root).data('timeout_id'));
							
							// Make the navigation buttons unusable while processing the action.
							$(entrySelector).data('inuse', true);
							
							// Get the config data out of the button.
							var objConfig = $(entrySelector).data("config");
							
							// Get the currently open list item.
							var jCurrent = objConfig.collection.filter(".open");
							if (!jCurrent.hasClass(jbId)) {
							
								// Mark the clicked item as open.
								for(var j = 1; j <= numItems; j++) {
									var jbHideClass = '.'+rootId+'-jb'+j;
									$(jbHideClass).removeClass('open');
								}
								$(this).addClass('open');
							
								// Hide the showing image.
								jCurrent.removeClass('open');
								jCurrent.hide("slide", { direction: "left" }, speed);
							
								// Show the previous image.
								var selClass = '.'+jbId;
								var jSelected = objConfig.collection.filter(selClass);
								jSelected.addClass('open');
								jSelected.show("slide", { direction: "right" }, speed, function () {
									// Set the navigation buttons as useable again.
									$(entrySelector).data('inuse', false);
									
									if (postClickDelay != -1) {
										// $.doTimeout(rootId, postClickDelay, autoNext);
										$(root).data('timeout_id', setTimeout(autoNext, postClickDelay));
									}
								});
							}
							else {
								$(entrySelector).data('inuse', false);
							}
						}
						
						// Prevent default event (form submit).
						objEvent.preventDefault();
						return(false);
					});	
				});
			}
		});
	};
