function category_hover( form_id, content_id, login_url, set_ignore_unload )
{
	// The form the category hover is associated with.
	this.form_id = form_id;
	this.form = document.getElementById(form_id);
	
	// If ignore_unload should be set to true when the category hover submits.
	this.set_ignore_unload = (true == set_ignore_unload)?true:false;

	// If a login url is passed in then the user must login first before the form is submitted.
	this.login_url = null;
	if( (undefined != login_url) && (login_url.length > 0) )
	{
		this.login_url = login_url;
	}

	// The content id and the object.
	this.id = content_id;
	this.content = document.getElementById(content_id);

	// Storage of the hover object.
	this.hover = null;

	// Stores if the category error has been outputted already.
	this.outputted_category_error = false;

	this.outputted_location_error = false;
	
	// If set to true it validates the number of checkboxes ticked.
	this.verify_selected_categories = true;

	// Opens the hover.
	this.open = function( submit_action, login_url )
	{
		try
		{
			this.form.submit_action.value = submit_action;
		}
		catch(e){}

		// Load the locations.
		hover_location_load_locations();

		// Create a new hover.
		this.hover = new hoverpopup();

		// Open the hover.
		this.hover.create(this.content);
		
		// Check the selected categories.
		this.hover_count_selected_categories();

		//hoverpopup_fade_in(this.content.id, 0, 100, 20);
	}

	this.submit = function( skip_this_step )
	{
		// If the user has hit skip this step then set the value in the form.
		if( true == skip_this_step )
		{
			document.getElementById('skip_this_step').value = 1;
		}
		else
		{
			// Validate the form.
			if( false == this.validate_form() )
			{
				return false;
			}

			document.getElementById('skip_this_step').value= 0;
		}

		// Close the hover
		this.close();
		
		if( true == this.set_ignore_unload )
		{
			form_ignore_unload = true;
		}

		// If the user is not logged in, display the login popup first.
		if( this.login_url != null )
		{
			// Once logged in, submit the form.
			var submit_form_id = this.form.id;
			showPopWin(this.login_url, 308, 350, function(returnVal){ document.getElementById(submit_form_id).submit(); }, 'hovername');
		}
		else
		{
			// Submit the form.
			this.form.submit();
		}

		return false;
	}

	// Closes the hover.
	this.close = function()
	{
		// Place the hover back into the form.
		this.form.appendChild(this.content);

		// Hide the content div.
		this.content.style.display = 'none';

		// Close the blocking hover.
		this.hover.close();
	}


	// Validates the posted form.
	this.validate_form = function()
	{
		var $edit_mode_value = document.getElementById('content_edit_mode').value;

		//
		// Check the location details.
		// If the location_local checkbox exists and is checked.
		// Otherwise there is no need to validate the location data.
		//

		// Load the location local checkbox.
		var $location_local = document.getElementById('location_local_checkbox');

		// If it is present and checked, make sure they have selected a location.
		if( ($location_local != null) && (true == $location_local.checked) )
		{
			return this.locations_valid();
		}

		// If the form is in edit mode, do not check the categories.
		if( $edit_mode_value == '0' )
		{
			// Check the categories, make sure one is selected.
			return this.categories_valid();
		}
	}

	// Displays the form error message.
	this.display_category_error = function( $message )
	{
		this.hide_location_error();

		if( false == this.outputted_category_error )
		{
			var category_select = document.getElementById('hover_category_select');
			category_select.style.height = (category_select.clientHeight - 35) + 'px';
		}
		
		document.getElementById('category_select_error').innerHTML = $message;
		document.getElementById('category_select_error').style.display = 'block';
		this.outputted_category_error = true;
	}

	this.hide_category_error = function()
	{
		document.getElementById('category_select_error').style.margin = '0';
		
		if( true == this.outputted_category_error )
		{
			var category_select = document.getElementById('hover_category_select');
			category_select.style.height = (category_select.clientHeight + 15) + 'px';
		}

		document.getElementById('category_select_error').style.display = 'none';
		this.outputted_category_error = false;

	}

	/**
	 * Checks if the forms category data has been filled out correctly.
	 *
	 * Returns TRUE if the form is valid, FALSE otherwise.
	 */
	this.categories_valid = function()
	{
		// Fetch all the inputs in the content div.
		var inputs = this.content.getElementsByTagName('input');

		// Check to make sure at least one of the form's checkbox's beginning with 'category_sub_' is selected.
		var index = 0;
		for( index; index<inputs.length; index++ )
		{
			if( (true == inputs[index].checked) && (inputs[index].name.substr(0, 13) == 'category_sub_') )
			{
				return true;
			}
		}

		// The data entered isn't valid.
		this.display_category_error('<div style="height: 25px">Please select categories below</div>');
		return false;
	}


	this.locations_valid = function()
	{
		//
		// If the location_local checkbox doesn't exist,
		// Or the location local checkbox isn't checked.
		// Then there is no need to validate the location data.
		//

		var $location_local = document.getElementById('location_local_checkbox');
		if( $location_local == null || false == $location_local.checked )
		{
			return true;
		}

		// Check the state first.
		var $location_state = document.getElementById('location_state');
		if( $location_state[$location_state.selectedIndex].value == 0 )
		{
			this.display_location_error('Please select a city and state.');
			return false;
		}

		// Check the location id.
		var $location_name = document.getElementById('location_name');
		if( $location_name[$location_name.selectedIndex].value == 0 )
		{
			this.display_location_error('Please select a city.');
			return false
		}

		return true;
	}

	this.display_location_error = function( $message )
	{
		// If the location error div doesn't exist, do not do anything with the error boxes
		var $location_error = document.getElementById('location_local_error');
		if( $location_error == null )
		{
			return true;
		}

		this.hide_category_error();

		if( false == this.outputted_location_error )
		{
			var category_select = document.getElementById('hover_category_select');
			category_select.style.height = (category_select.clientHeight - 25) + 'px';
		}

		$location_error.style.display = 'block';
		$location_error.innerHTML = $message;
		this.outputted_location_error = true;
	}

	this.hide_location_error = function()
	{
		// If the location error div doesn't exist, do not do anything with the error boxes
		var $location_error = document.getElementById('location_local_error');
		if( $location_error == null )
		{
			return true;
		}

		if( true == this.outputted_location_error )
		{
			var category_select = document.getElementById('hover_category_select');
			category_select.style.height = (category_select.clientHeight + 5) + 'px';
		}

		$location_error.style.display = 'none';
		this.outputted_location_error = false;
	}
	

	this.hover_count_selected_categories = function()
	{
		if( true == this.verify_selected_categories )
		{
			var hover_category = document.getElementById('hover_category');
			
			var hover_checkboxes = getElementsByClassName(hover_category, 'input', 'categoryHoverCategorySelect');
			
			var selected_checkboxes = new Array();
			
			for( var i = 0; i < hover_checkboxes.length; i++ )
			{
				input = hover_checkboxes[i];
				
				// Enable all checkboxes to allow users to change their preferences.
				input.disabled = false;
				
				if ( input.checked == true )
				{
					selected_checkboxes[selected_checkboxes.length] = input;
				}
			}
			
			if ( selected_checkboxes.length == 5 )
			{
				for( var i = 0; i < hover_checkboxes.length; i++ )
				{
					input = hover_checkboxes[i];
					
					if ( input.checked != true )
					{
						input.disabled = true;
					}
				}
				
				var hover_category = document.getElementById('hover_category');
				hover_category.style.height = (hover_category.clientHeight - 5) + 'px';
				
				this.display_category_error('You\'ve selected the maximum number of categories for your post. Click <a href="#" onClick="hover_category.submit(false); return false;">Submit</a> to continue.');
				document.getElementById('category_select_error').style.margin = '0 0 7px 0';
			}
			else
			{
				if( true == this.outputted_category_error )
				{
					var hover_category = document.getElementById('hover_category');
					hover_category.style.height = (hover_category.clientHeight - 35) + 'px';
				}
				
				this.hide_category_error();		
			}
		}
	}
}


function hoverpopup()
{
	this.blocking_element = null;
	this.original_overflow = null;

	this.create = function( content_object )
	{
		// Get all the document dimensions.
		var dimensions = document_dimensions();

		// Create a new blocking div so the user cannot select anything behind the hover.
	    this.blocking_element = document.createElement('div');
	    this.blocking_element.setAttribute('id', 'hoverpopup_blocking_element');
	    this.blocking_element.style.width = dimensions.docwidth + 'px';
	    this.blocking_element.style.height = dimensions.docheight + 'px';
	    this.blocking_element.style.opacity = 0.1;
	    this.blocking_element.style.filter = 'alpha(opacity=10)';
	    
	    document.body.appendChild(this.blocking_element);

	    // Fade it in.
		//hoverpopup_fade_in(this.blocking_element.id, 0, 10, 2);

	    // Display the object to work out its dimensions
 		content_object.style.display = 'block';

	    // Position it in the middle of the screen.
		content_object.style.top = (((dimensions.winheight - content_object.clientHeight) / 2) + dimensions.top) + 'px';
		content_object.style.left = (((dimensions.winwidth - content_object.clientWidth) / 2) + dimensions.left) +'px';

		// Place the content object on top of the blocking element
    	document.body.appendChild(content_object);
	}

	this.close = function()
	{
		// Remove the blocking element/
		document.body.removeChild(this.blocking_element);
	}
}

// Fade the layer in to the max opacity.
function hoverpopup_fade_in(object_id, opacity, max_opacity, step)
{
	var blocking_element = document.getElementById(object_id);

	// Set the opacity.
	blocking_element.style.opacity = opacity / 100;
	blocking_element.style.filter = 'alpha(opacity=' + opacity + ')';
	if( opacity <= max_opacity )
	{
		setTimeout("hoverpopup_fade_in('" + object_id + "', " + (opacity+step) + ", " + max_opacity + ", " + step + ");", 25);
	}
}





//
// Functions related to the location selection.
//


/**
 * Sets the location state and name pulldowns to active when the 'local' checkbox is selected.
 *
 * If the checkbox is changed to unticked then the pulldowns are made inactive.
 */
function hover_activate_location_pulldowns()
{
	var $local_checkbox = document.getElementById('location_local_checkbox');

	if( true == $local_checkbox.checked )
	{
		document.getElementById('location_state').disabled = false;
		document.getElementById('location_name').disabled = false;
	}
	else
	{
		document.getElementById('location_state').disabled = true;
		document.getElementById('location_name').disabled = true;
	}
}


function hover_location_initialise_form()
{
	hover_activate_location_pulldowns();
}

var hover_location_ajax = new ajax('text');
function hover_location_load_locations()
{
	var $location_pulldown = document.getElementById('location_state');
	if( $location_pulldown == null )
	{
		return;
	}

	if( $location_pulldown[$location_pulldown.selectedIndex].value != 0 )
	{
		// Clean all the values from the city pulldown.
		var $location_name_pulldown = document.getElementById('location_name');

		// Clear all elements first.
		while( $location_name_pulldown.length > 0 )
		{
			$location_name_pulldown.remove($location_name_pulldown.length - 1);
		}

		// Add a new element to say its loading.
		var $option_new = document.createElement('option');
		$option_new.text = 'Loading...';
		$option_new.value = 0;

		try
		{
			$location_name_pulldown.add($option_new, null); // standards compliant; doesn't work in IE
		}
		catch(ex)
		{
			$location_name_pulldown.add($option_new); // IE only
		}

		// Call the ajax request to load the new location's.
		hover_location_ajax.InitializeRequest('/ajax/location/list/', hover_location_load_success, hover_location_load_fail);

		var $state = $location_pulldown[$location_pulldown.selectedIndex].value;
		hover_location_ajax.Commit("state=" + $state);
	}
}

function hover_location_load_success(new_select_html)
{

	var $locations = new_select_html.split("\n");

	var $location_pulldown = document.getElementById('location_name');

	// Clear all elements first.
	while( $location_pulldown.length > 0 )
	{
		$location_pulldown.remove($location_pulldown.length - 1);
	}

	// Add the '--' text as the first item in the list.
	$locations.unshift('0|--');
	
	var $cookied_location_id = document.getElementById('cookie_location_id').value;
	
	var $location_count = 0;

	// Add in the new elements.
	for( $location in $locations )
	{
		if( $locations[$location].length > 0 )
		{
			var $option_new = document.createElement('option');

			var $location_details = $locations[$location].split('|');
			$option_new.text = $location_details[1];
			$option_new.value = $location_details[0];

			try
			{
				$location_pulldown.add($option_new, null); // standards compliant; doesn't work in IE
			}
			catch(ex)
			{
				$location_pulldown.add($option_new); // IE only
			}
			
			// Set the location id from the users cookied value.
			if( $cookied_location_id == $location_details[0] )
			{
				$location_pulldown[$location_count].selected = true;
			}
		}
			
		$location_count++;
	}
}

function hover_location_load_fail(xmldoc, message)
{
}

