/**
 * 
 *  Riseart common javascript library
 *
 * @package public
 * @subpackage js
 *
 * @copyright Copyright (c) Rise Art Ltd 2010
 * @author massa
 *
 *
 */

/**
 * Verify dependencies
 */
if (typeof jQuery == 'undefined') {
	alert("Riseart utils: jQuery is not loaded and is a required dependency.");
}


/**
 * Define RA JSON response object
 */
function RaJSON() {};
RaJSON.RESPONSE_OBJECT_RESULT  = 'result';
RaJSON.RESPONSE_OBJECT_DATA = 'data';

/**
 * Create and return callback function for JSON request and reponse
 * 
 * @param $success The callback function on success response
 * @param $error The callback function on error response
 * @returns function
 */
RaJSON.getCallback = function($success, $error) {
	
	var $callback = function($response) {
		if(typeof $response === 'undefined') {
			// No response received assume error
			$error();
			return;
		}
		if($response[RaJSON.RESPONSE_OBJECT_RESULT] === true) {
			if(typeof $success !== 'undefined') { 
				$success($response[RaJSON.RESPONSE_OBJECT_DATA]);
			}
			return;
		} else {
			if(typeof $error !== 'undefined') {
				$error($response[RaJSON.RESPONSE_OBJECT_DATA]);
			}
			return;
		}
	};
	return $callback;
};

/**
 * Submits an AJAX request and processes the response
 * 
 * @param $data The data to be sent to the server
 * @param $url The server endpoint URL
 * @param $success The callback function on success response
 * @param $error The callback function on error response
 */
RaJSON.prototype.send = function($data, $url, $success, $error, $get) {
	
	if($data === null && $get === true) {
		$type = 'GET';
	} else {
		$type = 'POST';
	}
	$.ajax({
		type: $type,
		dataType: 'json',
		url: $url,
		data: $data,
		success: RaJSON.getCallback($success, $error)
	});
};

/**
 * Instantiate default RA JSON Object
 */
var $RaJ = new RaJSON;

//-----------------------------------------------------------------------------

/**
 * Define RA Form object
 */
function RaForm() {};
RaForm.ELEMENT_ERRORS_CLASS = 'errors';

/**
 *  Submits a whole form by its id. Will callback a success or failure function
 *  
 * @param $id The form id
 * @param $success The callback function on success response
 * @param $error The callback function on error response (optional)
 * @param $url The server endpoint URL (optional)
 * @param $submit The form submit element ID (optional)
 * @param $disable Whether the form should be disabled before submission (optional)
 * @param $file Whether the form contains a file element (Optional)
 */
RaForm.prototype.submit = function($id, $success, $error, $url, $submit, $disable, $file)
{
	var $name = null;
	var $value = null;
	if($submit != null && $submit != '' && typeof $submit !== 'undefined') {
		$name = $('#' + $id + ' #' + $submit).attr('name');
		$value = $('#' + $id + ' #' + $submit).attr('value');
	}
	if(typeof $url === 'undefined' || $url == '' || $url == null) {
		var $url = $('#' + $id).attr('action');
	}
	
	if($file === true) {
		// Get request data object
		var $data = {
			url: $url,
			dataType: 'json',
			success: RaJSON.getCallback($success, $error)
		};
		if($name != null) {
			$data.data = {$name: $value};
		}
		// There is a file element in the form, submit using target iFrame
		$('#' + $id).ajaxSubmit($data);
	} else {
		// Serialize form data
		var $data = $('#' + $id).serialize();
		if($name != null) {
			$data = $data + '&' + $name + '=' + $value;
		}
		// Disable form after serializing - if done before, no data is serialized
		if($disable === true) {
			this.disable($id, true);
		}
		// Send data to server
		$RaJ.send($data, $url, $success, $error);
		return;
	}
};

/**
 * Reset a form. Removes any validation errors and restores field values.
 * 
 * @param $id The ID of the form
 */
RaForm.prototype.reset = function($id){
	$('#'+$id).get(0).reset();
	$('#'+$id).find('.'+RaForm.ELEMENT_ERRORS_CLASS).remove();
};

/**
 * Disable or enable all form elements
 * 
 * @param $id The ID of the form
 * @param $disable Optional. Whether to disable or enable the form
 */
RaForm.prototype.disable = function($id, $disable){
	if(typeof $disable != 'boolean')
		$disable = true;
	if($disable === true) {
		$('#'+$id+' input:enabled').attr('disabled', true);
		$('#'+$id+' select:enabled').attr('disabled', true);
		$('#'+$id+' textarea:enabled').attr('disabled', true);
	} else {
		$('#'+$id+' input:disabled').attr('disabled', false);
		$('#'+$id+' select:disabled').attr('disabled', false);
		$('#'+$id+' textarea:disabled').attr('disabled', false);
	}
};

/**
 * Validate an entire form
 * 
 * @param $id The form id
 * @param $url The server endpoint URL. If not provided the form action url will be used
 * @param $event The event that triggered the validation. Optional.
 * @param $stop Whether the event propagation should be stopped. Optional.
 */
RaForm.prototype.validate = function($id, $url, $event, $stop){
	
	if(typeof $event !== 'undefined') {
		$.ajaxSetup({
			async: false
		});
	}
	if($stop !== true) {
		$stop = false;
	}
	
	this.submit(
		$id,
		function() {
			$('#' + $id).find('.' + RaForm.ELEMENT_ERRORS_CLASS).remove();
			return;
		},
		function($response) {
			$('#' + $id).find('.' + RaForm.ELEMENT_ERRORS_CLASS).remove();
			$RaF.displayErrors($response);
			if(typeof $event !== 'undefined') {
				$event.preventDefault();
				if($stop === true) {
					$event.stopImmediatePropagation();
				}
			}
			return;
		},
		$url
	);
	
	return;
};

/**
 *  Validates a single form element by its id.
 *  
 *  @param $id The form element ID
 *  @param $url The server endpoint URL (optional)
 *  @param $formId The ID of the form (optional)
 */
RaForm.prototype.validateElement = function($id, $url, $formId)
{
	if($formId == '' || typeof $formId === 'undefined' || $formId == null) {
		var $formId = $('#' + $id).closest('form').attr('id');
	}
	if($('#' + $id).attr('validate') != null && $('#' + $id).attr('validate') != '') {
		$id = $('#' + $id).attr('validate');
	}
	var $name = $('#' + $id).attr('name');
	
	this.submit(
		$formId,
		function() {
			$('#' + $id).parent().find('.' + RaForm.ELEMENT_ERRORS_CLASS).remove();
			return;
		},
		function($response) {
			$('#' + $formId + ' #' + $id).parent().find('.' + RaForm.ELEMENT_ERRORS_CLASS).remove();
			if($response != null) {
				if($id.indexOf('-') >= 0 && ($name.indexOf('[') >= 0 || $name.indexOf(']') >= 0)) {
					var $ids = $id.split('-');
					var $errors = $RaF.findErrors($response, $ids);
				} else if ($id.indexOf('-') >= 0) {
					var $errors = $response[$name];
				} else {
					var $errors = $response[$id];
				}
				$('#' + $formId + ' #' + $id).parent().append($RaF.formErrorHTML($errors, $id));
			}
			return;
		},
		$url
	);
	
	return;
};

/**
 * Adds errors HTML to a default Zend_Form output. 
 * 
 * @param $response JSON response object
 * @param $formId String (Optional)
 */
RaForm.prototype.displayErrors = function($response, $formId)
{	
	var $errors = this.flattenErrors($response);
	
	for(var $key in $errors) {
		// Find element selector
		var $selector = null;
		if($formId == '' || typeof $formId === 'undefined' || $formId == null) {
			if($('#' + $key).size() > 0) {
				$selector = '#' + $key;
			} else if($('[name="' + $key + '"]').size() > 0) {
				$selector = '[name="' + $key + '"]';
			}
		} else {
			if($('#' + $formId + ' #' + $key).size() > 0) {
				$selector = '#' + $formId + ' #' + $key;
			} else if ($('#' + $formId + ' [name="' + $key + '"]').size() > 0) {
				$selector = '#' + $formId + ' [name="' + $key + '"]';
			}
		}
		// Add error message to form element
		if($selector != null) {
			$elementId = $($selector).get(0).id;
			$($selector).parent().append(this.formErrorHTML($errors[$key], $elementId));
		}
	}
	return;
};

/**
 * Generates HTML unordered list based on a JSON response of Zend_Form::getMessages() for an element (by id)
 * 
 * @param $errors Object with list of elements errors
 * @param $id The element id
 * @returns The list of errors in HTML
 */
RaForm.prototype.formErrorHTML = function($errors, $id)
{
	var $html = "<ul id = \"" + $id + "-errors\" class = \"" + RaForm.ELEMENT_ERRORS_CLASS + "\">";
	var $count = 0;
	for(var $key in $errors) {
		$html += "<li>" + $RaU.htmlEncode($errors[$key]) + "</li>\n";
		$count++;
	}
	if($count != 0)
		return $html += "</ul>";
	else
		return;
};

/**
 * Search errors array for a specific key recursivelly
 * 
 * @param $errors The JSON reponse object with form errors
 * @param $ids A string with the element Id OR an array with the element Id parts (for Zend_Sub_Forms)
 */
RaForm.prototype.findErrors = function($errors, $ids) {
	
	if($.isArray($ids)) {
		var $key = $ids.shift();
	} else if (typeof $ids === 'string') {
		var $key = $ids;
	} else {
		return;
	}
	
	if(typeof $errors[$key] !== 'undefined') {
		if($.isArray($ids) && $ids.length > 0) {
			return this.findErrors($errors[$key], $ids);
		} else {
			return $errors[$key];
		}
	} else {
		return;
	}
};

/**
 * Process form errors recursivelly and flatten response object
 * to manage Zend_Sub_Form errors 
 * 
 * @param $errors The JSON reponse object with form errors
 */
RaForm.prototype.flattenErrors = function($errors, $id, $response) {
	
	if(typeof $response != 'object') {
		var $response = {};
	}
	for(var $key in $errors) {	  
		var $hasChilds = (typeof $errors[$key] == 'object') ? true : false;
		if($hasChilds === true) {
			if($id == '' || typeof $id === 'undefined') {
				var $childId = $key;
			} else {
				var $childId = [$id, $key].join('-');
			}
			$response = this.flattenErrors($errors[$key], $childId, $response);
		} else {
			if(typeof $response[$id] != 'object') {
				$response[$id] = {};
			}
			$response[$id][$key] = $errors[$key];
		}
	}
	return $response;
};

/**
 * Execute any returned scripts globally
 * 
 * @param $response
 */
RaForm.prototype.execScripts = function($response) {
	if(typeof $response['scripts'] !== 'undefined' && $response['scripts'] != null) {
		if(typeof $response['scripts'] === 'object' && $response['scripts'].length > 0) {
		    $.each($response['scripts'], function($index, $script) {
		        $.globalEval($script);
		    });
		} else if (typeof $response['scripts'] === 'string') {
			$.globalEval($response['scripts']);
		}
	}
};

/**
 * Toggle form password field value between visible and hidden
 * 
 * @param $id
 * @param $checkBoxId
 */
RaForm.prototype.togglePassword = function($id, $checkBoxId) {
	var $helperText = $('#'+$id+'-clone').attr('helper');
	var $hasHelper = ($helperText != '' && $helperText != null) ? true : false;
	var copy = function($source, $destination) {
		if($hasHelper && ($source.val() == '' || $source.val() == null) && $destination.val() == $helperText) {
			return;
		}else if($hasHelper && ($destination.val() == '' || $destination.val() == null) && $source.val() == $helperText) {
			return;
		} else {
			$destination.val($source.val());
		}
	};
	var toggle = function() {
		if($('#'+$checkBoxId).is(':checked')){
			copy($('#'+$id), $('#'+$id+'-clone'));
			$('#'+$id).hide();
			$('#'+$id+'-clone').show();
		} else {
			copy($('#'+$id+'-clone'), $('#'+$id));
			if($hasHelper && ($('#'+$id).val() == '' || $('#'+$id).val() == null)) {
				$('#'+$id).hide();
				$('#'+$id+'-clone').show();
			} else {
				$('#'+$id+'-clone').hide();
				$('#'+$id).show();
			}
		}
	};
	$('#'+$checkBoxId).live('click', function(){toggle();});
	$('#'+$id).live('keyup', function(){copy($('#'+$id), $('#'+$id+'-clone'));});
	$('#'+$id+'-clone').live('keyup', function(){copy($('#'+$id+'-clone'), $('#'+$id));});
	if($hasHelper) {
		$('#'+$id).live('blur', function(){
			if($('#'+$id).val() == null || $('#'+$id).val() == '') {
				$('#'+$id+'-clone').val($helperText);
				if(!$('#'+$checkBoxId).is(':checked')) {
					$('#'+$id).hide();
					$('#'+$id+'-clone').show();
				}
			}
		});
		$('#'+$id+'-clone').live('focus', function(){
			if($('#'+$id+'-clone').val() == $helperText) {
				$('#'+$id+'-clone').val(null);
			}
			if(!$('#'+$checkBoxId).is(':checked')) {
				$('#'+$id+'-clone').hide();
				$('#'+$id).show().focus();
			}
		});
		$('#'+$id+'-clone').live('blur', function(){
			if($('#'+$checkBoxId).is(':checked') && ($('#'+$id+'-clone').val() == null || $('#'+$id+'-clone').val() == '')) {
				$('#'+$id+'-clone').val($helperText);
			}
		});
	}
};

/**
 * Initialize events for AJAX edit forms
 * 
 * @param $formId
 * @param $placeholderId
 * @param $containerId
 * @param $messagesId
 * @param $groupId
 * @param $validate
 * @param $editId
 * @param $deleteId
 * @param $linksId
 * @param $linksMsgId
 */
RaForm.prototype.initEdit = function($formId, $placeholderId, $containerId, $messagesId, $groupId, $validate, $editId, $deleteId, $linksId, $linksMsgId) {
	// Show form when clicking on the placeholder or edit link
	if(typeof $editId === 'undefined' || $editId == null || $editId == '') {
		$('#' + $placeholderId).click(function($event) {
			if($($event.target).is('a')) {
				return;
			} else {
				$event.preventDefault();
			}
			$('#' + $placeholderId).css({display: 'none'});
			if($linksId != null)
				$('#' + $linksId).css({display: 'none'});
			$('#' + $containerId).css({display: 'block'});
		});
	} else {
		$('#' + $editId).click(function() {
			$('#' + $placeholderId).css({display: 'none'});
			$('#' + $linksId).css({display: 'none'});
			$('#' + $containerId).css({display: 'block'});
		});
	}
	// Reset and hide the form when clicking on cancel buttons
	$('#' + $formId + ' .button[name="cancel"]').click(function() {
		$('#' + $containerId).css({display: 'none'});
		$('#' + $placeholderId).css({display: 'block'});
		if($linksMsgId != null)
			$('#' + $linksMsgId).empty();
		if($linksId != null)
			$('#' + $linksId).css({display: 'block'});
		$('#' + $formId).get(0).reset();
		$('#' + $formId).find('.' + RaForm.ELEMENT_ERRORS_CLASS).remove();
		$('#' + $messagesId).empty();
	});
	// Validate form element
	if($validate !== false) {
		$('#' + $formId + ' :input:not(:submit):not(:button)').blur(function() {
			$id = $(this).get(0).id;
			$action = $('#' + $formId + ' input[name="validate"]').val();
			$RaF.validateElement($id, $action, $formId);
		});
	}
	// Form submission events
	$('#' + $formId + '  input[type="submit"]').click(function() {
		$('#' + $formId + ' input[type="submit"]').removeAttr('clicked');
		$(this).attr('clicked', 'yes');
	});
	$('#' + $formId).submit(function($event) {
		$event.preventDefault();
		// Get clicked button, disable and change label
		var $button = $('#' + $formId + ' input[type="submit"][clicked="yes"]');
		var $label = null;
		if(typeof $button == 'object'){
			$button.removeAttr('clicked');
			if($button.is('input')) {
				$label = $button.val();
				$button.val('Wait...');
			} else if ($button.is('button')) {
				$label = $button.text();
				$button.text('Wait...');
			}
			$button.attr('disabled', true);
		}
		// Submit form
		$RaF.submit(
			$formId, 
			function($response){
				$RaF.disable($formId, false);
				$('#' + $formId).get(0).reset();
				$('#' + $formId).find('.' + RaForm.ELEMENT_ERRORS_CLASS).remove();
				$('#' + $messagesId).empty();
				if(typeof $button == 'object'){
					if($button.is('input')) {
						$button.val($label);
					} else if ($button.is('button')) {
						$button.text($label);
					}
				}
				if($response['form'])
					$('#' + $groupId).replaceWith($response['form']);
				if($response['html']) {
					for(var $key in $response['html']) {
						$($key).replaceWith($response['html'][$key]);
					}
				}
				$RaF.execScripts($response);
				return;
			},
			function($response){
				$RaF.disable($formId, false);
				$RaF.handleError($response, $formId, $messagesId);
				if(typeof $button == 'object'){
					if($button.is('input')) {
						$button.val($label);
					} else if ($button.is('button')) {
						$button.text($label);
					}
				}
				return;
			},
			null, null, true
		);
	});
	// Delete record
	if(typeof $deleteId !== 'undefined' && $deleteId != null && $deleteId != '') {
		$('#' + $deleteId).click(function($event) {
			var $url = $(this).attr('href');
			if($url == null || $url == '') {return;}
			$event.preventDefault();
			$RaJ.send(
				null,
				$url,
				function($response){
					$('#' + $groupId).empty();
					if($response['html']) {
						for(var $key in $response['html']) {
							$($key).replaceWith($response['html'][$key]);
						}
					}
					return;
				},
				function($response){
					$RaF.handleError($response, null, $linksMsgId);
					return;
				}
			);
		});
	}
};

/**
 * Initialize events for AJAX multi forms
 * 
 * @param $linkId
 * @param $formId
 * @param $containerId
 * @param $messagesId
 * @param $divId
 */
RaForm.prototype.initMulti = function($linkId, $formId, $containerId, $messagesId, $divId) {
	// Show form when clicking on the add link
	$('#' + $linkId).click(function($event) {
		$event.preventDefault();
		$(this).css({display: 'none'});
		$('#' + $containerId).css({display: 'block'});
	});
	// Reset and hide the form when clicking on cancel button
	$('#' + $formId + ' .button[name="cancel"]').click(function() {
		$('#' + $containerId).css({display: 'none'});
		$('#' + $linkId).css({display: 'block'});
		$('#' + $formId).get(0).reset();
		$('#' + $formId).find('.' + RaForm.ELEMENT_ERRORS_CLASS).remove();
	});
	// Validate form element
	$('#' + $formId + ' :input:not(:submit):not(:button)').blur(function() {
		$id = $(this).get(0).id;
		$action = $('#' + $formId + ' input[name="validate"]').val();
		$RaF.validateElement($id, $action, $formId);
	});
	// Submit add form
	$('#' + $formId + '  input[type="submit"]').click(function() {
		$('#' + $formId + ' input[type="submit"]').removeAttr('clicked');
		$(this).attr('clicked', 'yes');
	});
	$('#' + $formId).submit(function($event) {
		$event.preventDefault();
		var $url = $('#' + $formId).attr('action');
		// Get clicked button and change label
		var $button = $('#' + $formId + ' input[type="submit"][clicked="yes"]');
		var $label = null;
		if(typeof $button == 'object'){
			$button.removeAttr('clicked');
			if($button.is('input')) {
				$label = $button.val();
				$button.val('Wait...');
			} else if ($button.is('button')) {
				$label = $button.text();
				$button.text('Wait...');
			}
		}
		$RaF.submit(
			$formId, 
			function($response){
				$RaF.disable($formId, false);
				$('#' + $formId).get(0).reset();
				$('#' + $formId).find('.' + RaForm.ELEMENT_ERRORS_CLASS).remove();
				$('#' + $messagesId).empty();
				if(typeof $button == 'object'){
					if($button.is('input')) {
						$button.val($label);
					} else if ($button.is('button')) {
						$button.text($label);
					}
				}
				if($response['form'])
					$('#' + $divId).replaceWith($response['form']);
				if($response['html']) {
					for(var $key in $response['html']) {
						$($key).replaceWith($response['html'][$key]);
					}
				}
				$RaF.execScripts($response);
				return;
			},
			function($response){
				$RaF.disable($formId, false);
				$RaF.handleError($response, $formId, $messagesId);
				if(typeof $button == 'object'){
					if($button.is('input')) {
						$button.val($label);
					} else if ($button.is('button')) {
						$button.text($label);
					}
				}
				return;
			},
			$url, null, true
		);
	});
};

/**
 * Initialize events for AJAX static forms
 * 
 * @param $formId The form ID
 * @param $messagesId
 * @param $validate Whether the form should validate each field independently
 * @param $submit Whether the form should submit via AJAX
 * @param $button Whether the submit button should be serialized for submission
 * @param $file Whether the form includes a file element
 */
RaForm.prototype.initStatic = function($formId, $messagesId, $validate, $submit, $button, $file) {
	// Validate form element
	if($validate !== false) {
		$('#' + $formId + ' :input:not(:submit):not(:button)').blur(function() {
			$id = $(this).get(0).id;
			var $action = $('#' + $formId + ' input[name="validate"]').val();
			$RaF.validateElement($id, $action, $formId);
		});
	}
	// Form submission events
	$('#' + $formId + '  input[type="submit"]').click(function() {
		$('#' + $formId + ' input[type="submit"]').removeAttr('clicked');
		$(this).attr('clicked', 'yes');
	});
	$('#' + $formId).submit(function($event) {
		// Get clicked button
		var $buttonEl = $('#' + $formId + ' input[type="submit"][clicked="yes"]');
		var $buttonId = null;
		var $label = null;
		if(typeof $buttonEl == 'object'){
			$buttonEl.removeAttr('clicked');
			if($button === true)
				$buttonId = $buttonEl.attr('id');
			else {
				// If button is not serialized, disable and change label
				if($buttonEl.is('input')) {
					$label = $buttonEl.val();
					$buttonEl.val('Wait...');
				} else if ($buttonEl.is('button')) {
					$label = $buttonEl.text();
					$buttonEl.text('Wait...');
				}
				$buttonEl.attr('disabled', true);
			}
		}
		// Submit the form
		if($submit !== false) {
			$event.preventDefault();
			$RaF.submit(
				$formId, 
				function($response){
					$RaF.disable($formId, false);
					$('#' + $formId).get(0).reset();
					$('#' + $formId).find('.' + RaForm.ELEMENT_ERRORS_CLASS).remove();
					if($messagesId != null)
						$('#' + $messagesId).empty();
					if($button !== true) {
						if(typeof $buttonEl == 'object'){
							if($buttonEl.is('input')) {
								$buttonEl.val($label);
							} else if ($buttonEl.is('button')) {
								$buttonEl.text($label);
							}
						}
					}
					if($response['html']) {
						for(var $key in $response['html']) {
							$($key).replaceWith($response['html'][$key]);
						}
					}
					if($messagesId != null && $response['messages'])
						$('#' + $messagesId).html($response['messages']);
					$RaF.execScripts($response);
					return;
				},
				function($response){
					$RaF.disable($formId, false);
					$RaF.handleError($response, $formId, $messagesId);
					if($button !== true) {
						if(typeof $buttonEl == 'object'){
							if($buttonEl.is('input')) {
								$buttonEl.val($label);
							} else if ($buttonEl.is('button')) {
								$buttonEl.text($label);
							}
						}
					}
					return;
				},
				null, $buttonId, true, $file
			);
		}
	});
};

/**
 * Handle form submission error response for Ajax forms
 * 
 * @param $response The JSON response object
 * @param $formId The form ID
 * @param $messagesId The ID of the messages conatiner
 */
RaForm.prototype.handleError = function($response, $formId, $messagesId) {
	if($formId != null)
		$('#' + $formId).find('.' + RaForm.ELEMENT_ERRORS_CLASS).remove();
	if($messagesId != null)
		$('#' + $messagesId).empty();
	if($response != null) {
		if($formId != null && $response['errors'] != null)
			$RaF.displayErrors($response['errors'], $formId);
		if($messagesId != null && $response['messages'] != null)
			$('#' + $messagesId).html($response['messages']);
	}
	return;
};

/**
 * Instantiate default RA Form Object
 */
var $RaF = new RaForm;

//-----------------------------------------------------------------------------

/**
 * Define RA Authentication object
 */
function RaAuth() {};
RaAuth.AUTH_ACTION_NAME = 'auth';
RaAuth.AUTH_CONTROLLER_NAME = 'user';
RaAuth.AUTH_POPUP_PARAM_NAME = 'popup';
RaAuth.RADIO_GROUP_NAME = 'user-has-ra';
RaAuth.SIGNIN_DIV_ID = 'signin-form-container';
RaAuth.SIGNIN_FORM_ID = 'signin-form';
RaAuth.SIGNOUT_DIV_ID = 'signup-form-container';
RaAuth.SIGNOUT_FORM_ID = 'signup-form';
RaAuth.MESSAGES_DIV_ID = 'auth-messages-container';

/**
 * Hide and show signin and signout forms
 * 
 * @param $value
 */
RaAuth.prototype.switchForm = function($value) {
	
	if($value == 'yes') {
		$('#' + RaAuth.SIGNIN_DIV_ID).show();
		$('#' + RaAuth.SIGNOUT_DIV_ID).hide();
	} else {
		$('#' + RaAuth.SIGNIN_DIV_ID).hide();
		$('#' + RaAuth.SIGNOUT_DIV_ID).show();
	}
	$('#'+RaAuth.MESSAGES_DIV_ID).html('');
	$RaF.reset(RaAuth.SIGNIN_FORM_ID);
	$RaF.reset(RaAuth.SIGNOUT_FORM_ID);
};
	
/**
 * Initialize auth events and handlers
 */
RaAuth.prototype.initAuth = function() {
	
	$('a').live('click', function($event) {
		var $isAuth = false;
		var $href = $(this).attr('href');
		if($href == '' || typeof $href === 'undefined') {
			return true;
		}
		$parts = parseUri($href);
		if($parts.path != null && $parts.path != '') {
			var $path = $parts.path.split('/');
		} else {
			return true;
		}
		if($path.indexOf(RaAuth.AUTH_ACTION_NAME) >= 0 
			&& $path.indexOf(RaAuth.AUTH_CONTROLLER_NAME) >= 0)
		{
			if($parts.queryKey.popup == 1) {
				$isAuth = true;
			} else if($parts.indexOf(RaAuth.AUTH_POPUP_PARAM_NAME) >= 0
				&& $parts[$parts.indexOf(RaAuth.AUTH_POPUP_PARAM_NAME)+1] == 1)
			{
				$isAuth = true;
			}
		}
		// Show popup dialogue
		if($isAuth === true) {
			$event.preventDefault();
			$RaU.dialogue($href);
		}
	});
};


/**
 * Instantiate default RA Auth Object
 */
var $RaA = new RaAuth;

//-----------------------------------------------------------------------------

/**
 * Define RA Utils object
 */
function RaUtils() {};
RaUtils.TWITTER_HANDLE = 'risearts';

/**
 * Initialize events for AJAX pagination
 * 
 * @param $paginationId
 * 
 * @deprecated New AJAX pagination uses RaContent object instead
 */
RaUtils.prototype.initPagination = function($paginationId) {
	// Submit pagination
	$('#' + $paginationId + ' a.paginate-ajax').click(function($event) {
		$event.preventDefault();
		$RaJ.send(
			null,
			$(this).attr('href'),
			function($response){
				if($response['html']) {
					for(var $key in $response['html']) {
						$($key).replaceWith($response['html'][$key]);
					}
				}
				return;
			},
			function(){return;}
		);
	});
};

/**
 * Clear an input field on focus and reset value on blur
 * 
 * @param fieldId
 */
RaUtils.prototype.clearInput = function(fieldId) {
	
	if (!document.getElementById || !document.getElementById(fieldId)) {
		return;
	}
	document.getElementById(fieldId).onfocus = function() {
		if (this.value == this.defaultValue) {
			this.value = '';
		}
	};
	document.getElementById(fieldId).onblur = function() {
		if (this.value == '') {
			this.value = this.defaultValue;
		}
	};
};

/**
 * Check and setup form field for automatic clear on focus
 * 
 * @param formId
 * @param fieldId
 */
RaUtils.prototype.checkFormField = function(formId, fieldId) {
	
	if (!document.getElementById || !document.getElementById(formId) || !document.getElementById(fieldId)) {
		return;
	}
	this.clearInput(fieldId);
	document.getElementById(formId).checkField = fieldId;
	document.getElementById(formId).onsubmit = function() {
		if (document.getElementById(this.checkField).value == document.getElementById(this.checkField).defaultValue) {
			return false;
		}
	};
};

/**
 * Confirm popup message
 * 
 * @param $message
 */
RaUtils.prototype.confirm = function($message) {
	
	return confirm($message);
};

/**
 * Open dialogue box
 * 
 * @param $url
 * @param $height
 * @param $scroll
 */
RaUtils.prototype.dialogue = function($url, $height, $scroll) {

	if ($height == 'auto') {
		var $height = $(window).height() - 100;
	}

	if($url != null) {
		$.fancybox({ 
			'href': $url,
			'height': (($height != null) ? $height : 666),
			'width': 600,
			'autoDimensions': true,
			'type': 'iframe',
			'scrolling': (($scroll != null) ? $scroll : 'no'),
			'autoScale': false,
			'overlayColor': '#909381'
		});
	}
};

/**
 * Initialize share
 * 
 * @param $url
 * @param $text Optional
 */
RaUtils.prototype.initShare = function($url, $text) {
	
	if($url != null) {
		$('#share .facebook a').bind('click', function ($event) {
			$event.preventDefault();
			$RaU.shareWindow('http://www.facebook.com/sharer.php?u=' + encodeURIComponent($RaU.shareTracking($url, 'facebook')));
			return false;
		});
		$('#share .twitter a').bind('click', function ($event) {
			$event.preventDefault();
			$RaU.shareWindow($RaU.shareTwitter($url, $text));
			return false;
		});
		$('#share .email a').attr('href', this.shareMailto($url));		
	}
};

/**
 * Share popup window open 
 * 
 * @param $url
 */
RaUtils.prototype.shareWindow = function($url) {
	
	if($url != null) {
		window.open($url, 'sharer', 'toolbar=0,status=0,width=626,height=436');
	}
};

/**
 * Generate mailto
 * 
 * @param $url
 * @return string
 */
RaUtils.prototype.shareMailto = function($url) {
	
	if($url != null) {
		$mailto = "mailto:" + encodeURIComponent('Enter Email Address') + '?' 
			+ '&subject=' + encodeURIComponent('A friend recommended you a page on Rise Art')
			+ '&body=' + encodeURIComponent("You've been recommended the following page on Rise Art: ")
			+ encodeURIComponent(this.shareTracking($url, 'email'));
		
		return $mailto;
	}
};

/**
 * Generate twitter sharing links
 * 
 * @param $url
 * @param $text
 * @return string
 */
RaUtils.prototype.shareTwitter = function($url, $text) {
	// Base URL
	$tweet = 'http://twitter.com/share?'; 
	$tweet += 'original_referer=' + encodeURIComponent($url); 
	$tweet += '&url=' + encodeURIComponent(this.shareTracking($url, 'twitter'));
	$tweet += '&via=' + RaUtils.TWITTER_HANDLE;
	$tweet += '&related=' + RaUtils.TWITTER_HANDLE;
	if($text != null) {
		$tweet += '&text=' + encodeURIComponent($text);
	}
	return $tweet;
};

/**
 * Generate tracking codes for share links
 * 
 * @param $url
 * @param $type
 * @return string
 */
RaUtils.prototype.shareTracking = function($url, $type) {
	
	if($url != null) {
		if($url.indexOf('?') < 0) {
			if($url.charAt($url.length -1) != '/') {
				$url += '/';
			}
			$url += '?';
		} else if($url.charAt($url.length -1) == '&') {
			$url += '&';
		}
		$url += 'utm_source=' + $type; 
		$url += '&utm_medium=social'; 
		$url += '&utm_campaign=web_share';
		return $url;
	}
};

/**
 * jCarousel plugin
 *
 * @param $selector
 * @param $visible
 */
RaUtils.prototype.jcarousel= function($selector, $visible) {

	jQuery('#'+$selector).jcarousel({
        scroll : 1,
		visible : $visible
    });
};

/**
 * tn3gallery plugin
 *
 * @param $selector
 * @param $delay
 * @param $transition
 */
RaUtils.prototype.tn3gallery = function($selector, $delay, $transition) {

	$('#' + $selector).tn3({
		skinDir : '/styles',
		startWithAlbums : true,
		autoplay : true,
		delay : $delay,
		image : {
			clickEvent : "dblclick",
			crop : false,
			maxZoom : 1,
			transitions : [{
				type : $transition,
				easing : "easeInQuad"
			}]
		}
	});
};

/**
 * Info Cloud
 * 
 * @param $id
 * @param $title
 * @param $description
 * @param $width
 * @param $height
 * @param $position
 */
RaUtils.prototype.infoCloud = function($id, $title, $description, $width, $height, $position) {
    
	var $offset = '-55 0';
	if($position == 'cloud-left') {
		$offset = '-245 0';
	}
    $('#cloud-'+$id).html('<div class="cloud-content"><h3>'+$title+'</h3><p>'+$description+'</p></div><img class="cloud-arrow" src="/img/cloud-arrow.png" />');
    var $dialog = $('#cloud-'+$id).dialog({
        open: function(event, ui){
			$('.ui-dialog-titlebar').hide();
			$('#cloud-'+$id).addClass($position);
		},
        autoOpen: false,
        minWidth: 160,
        width: $width,
        height: $height,
        resizable: false,
        title: false,
        close: false
    });
    if ($.browser.msie && $.browser.version == '7.0') {
        $('#'+$id).click(function() {           
        	$dialog.dialog('option','buttons', {
        	   Ok: function() {
            	   $(this).dialog('close');
               }
            });
        	$dialog.dialog('open');
        })
    } else {
        $('#'+$id).mouseover(function() {
            $dialog.dialog('option','position', {
            	my: 'left bottom',
            	at: 'right top',
            	of: $(this),
            	offset: $offset
            });
            $dialog.dialog('open');
        })
        .mouseout(function() {
            $dialog.dialog('close');
        });
    }
};

/**
 * Show More Text
 * 
 * @param $id
 */
RaUtils.prototype.showMoreText = function($id) {
	$('#'+$id+' .show-more').click(function() {
		if($(this).hasClass('inactive')) {
			$('#'+$id+' .short-text').hide();
			$('#'+$id+' .long-text').show();
			$(this).html('Show less&hellip;').removeClass('inactive').addClass('active');
		} else if($(this).hasClass('active')) {
			$('#'+$id+' .long-text').hide();
			$('#'+$id+' .short-text').show();
			$(this).html('Show more&hellip;').removeClass('active').addClass('inactive');
		}
	});
};

/**
 * Show overlay when hovering over selector 
 *
 * @param $selector1 The element hovered upon
 * @param $selector2 The element to show (a child of selector 1)
 */
RaUtils.prototype.showOverlay = function($selector1, $selector2) {
	$($selector1).hover(
		function () {$(this).children($selector2).fadeIn('slow');}, 
		function () {$(this).children($selector2).fadeOut('slow');}
	);
}

/**
 * Link in background
 *
 * @param $selector
 */
RaUtils.prototype.bgLink = function($selector) {
	$($selector).css('cursor', 'pointer').click(function($event){
		var $target = $event.target;
		var $href = '';
		if($target.nodeName == 'A') {
			$href = $target.attr('href');
			window.location = $href;
		} else if ($target.nodeName == 'INPUT') {
			$event.stopPropagation();
		} else {
			$href = $(this).attr('href');
			window.location = $href;
		}
		return true;
	});
}

/**
 * Encode HTML string
 * 
 * @param $value
 */
RaUtils.prototype.htmlEncode = function($value) {
	return $('<div/>').text($value).html();
};

/**
 * Decode HTML string
 * 
 * @param $value
 */
RaUtils.prototype.htmlDecode = function($value) {
	return $('<div/>').html($value).text();
}

/**
 * Instantiate default RA Utils Object
 */
var $RaU = new RaUtils;


//-----------------------------------------------------------------------------

/**
 * Define RA Image manipulation object
 */
function RaImage() {};

/**
 * Define preview image object
 */
RaImage.prototype.previewImage = function() {};

/**
 * Define master image object
 */
RaImage.prototype.masterImage = function() {};

/**
 * Initialize image cropping function
 * 
 * @param $previewSize
 * @param $minWidth
 * @param $minHeight
 * @param $usePreview
 */
RaImage.prototype.initCrop = function($previewSize, $minWidth, $minHeight, $usePreview) {
	
	// Configure preview box size
	if($usePreview == false) {
		this.previewImage.USE_PREVIEW = false;
	} else {
		this.previewImage.PREVIEW_BOX_WIDTH = $previewSize;
		this.previewImage.PREVIEW_BOX_HEIGHT = $previewSize;
		this.previewImage.USE_PREVIEW = true;
	}
	
	// Load JCrop
	$(window).load(function() {
		// Set minimum height and width
		if($minWidth == null)
			$minWidth = 0;
		if($minHeight == null)
			$minHeight = 0;
		
		// Calculate intial images size and coords
		$RaI.masterImage.w = $('#image-master').width();
		$RaI.masterImage.h = $('#image-master').height();
		$initialArea = $RaI.initialArea($RaI.masterImage.w, $RaI.masterImage.h);
		
		$('#image-master').Jcrop({
	        onSelect: $RaI.setCoords,
	        onChange: $RaI.setCoords,
	        minSize: [$minWidth, $minHeight],
	        setSelect: $initialArea,
	        aspectRatio: 1
	    });
	});
	
};

/**
 * Calculate initial select area dimensions
 * 
 * @param $imageWidth
 * @param $imageHeight
 * @returns {Array}
 */
RaImage.prototype.initialArea = function($imageWidth, $imageHeight) {
	
	// Calculate initial box coordinates
	if($imageWidth > $imageHeight) {
		$startWidth = Math.round(($imageWidth - $imageHeight)/2);
		$endWidth = ($startWidth + $imageHeight);
		$startHeight = 0;
		$endHeight = $imageHeight;
	} else {
		$startWidth = 0;
		$endWidth = $imageWidth;
		$startHeight = Math.round(($imageHeight - $imageWidth)/2);
		$endHeight = ($startHeight + $imageWidth);
	}
	
	return [$startWidth, $startHeight, $endWidth, $endHeight];
};

/**
 * Set crop form and preview image transformations
 * 
 * @param $coords
 */
RaImage.prototype.setCoords = function($coords) {
	
	// Save cropped dimensions to form
	$('#x0').attr('value', $coords.x);
	$('#y0').attr('value', $coords.y);
	$('#x1').attr('value', $coords.x2);
	$('#y1').attr('value', $coords.y2);
	$('#width').attr('value', $coords.w);
	$('#height').attr('value', $coords.h);
	
	if($RaI.previewImage.USE_PREVIEW == true) {
		// Get Ratios
		$rx = ($RaI.previewImage.PREVIEW_BOX_WIDTH / $coords.w);
		$ry = ($RaI.previewImage.PREVIEW_BOX_HEIGHT / $coords.h);
		// Scale and move tranformations to preview
		$('#image-preview').css({
			width: 	Math.round($rx * $RaI.masterImage.w) + 'px',
			height: Math.round($ry * $RaI.masterImage.h) + 'px',
			marginLeft: '-' + Math.round($rx * $coords.x) + 'px',
		    marginTop: '-' + Math.round($ry * $coords.y) + 'px'	
		});
	}
};

/**
 * Instantiate default RA Image Object
 */
var $RaI = new RaImage;

//-----------------------------------------------------------------------------

/**
 * Define RA Carousel object (sliding carousel)
 * 
 * @param int $speed
 * @param int $delay
 */
function RaCarousel($speed, $delay) {
	
	// Configure carousel
	this.carouselStack = $('.carousel-item');
	this.currentItem = 0;
	this.speed = $speed;
	this.delay = $delay;
	this.locked = false;
	this.scroll = false;
	this.timer = null;
	this.width = 940;
	this.height = 350;
	
	// Generate Section Buttons
	this.generateSectionButtons();
	this.makeButtonActive();
	
	// Attach Events
	$self = this;
	$('.carousel-container').bind('mouseenter', function () {
		$self.stopScroll();
	});
	$('.carousel-container').bind('mouseleave', function () {
		$self.startScroll();
	});
	$('#carousel-button-left').bind('click', function () {
		$self.animateLeft();
	});
	$('#carousel-button-right').bind('click', function () {
		$self.animateRight();
	});
	$('.carousel-section-button').bind('click', function () {
		$self.animateJumpTo($(this).attr('id'));
	});
	
	$container = document.getElementById('carousel-container');
	// Attach MouseWheel Listener on normal browsers
	if($container.addEventListener) {
		$container.addEventListener('DOMMouseScroll', function(e) {$self.mouseWheelMove(e);}, false);
		$container.addEventListener('mousewheel', function(e) {$self.mouseWheelMove(e);}, false);	
	}
	// Attach MouseWheel Listener for IE
	else if($container.attachEvent)
		$container.attachEvent("onmousewheel", function(e) {$self.mouseWheelMove(e);});
};

/**
 * Initializes the carousel
 */
RaCarousel.prototype.init = function() {
	this.carouselStack.first().css({left: '0px'});
	this.startScroll();
};

/**
 * Handles the mouse wheel event
 */
RaCarousel.prototype.mouseWheelMove = function(e) {
	e = e ? e : window.event;
	var event = e;
	var $wheelData = event.detail ? event.detail * -1 : event.wheelDelta / 40;
	if($wheelData > 0)
		this.animateRight();
	else
		this.animateLeft();
	// Non jQuery event intercept
	this.cancelScroll(e);
};

/**
 * Non jQuery event default intercept and stopper
 */
RaCarousel.prototype.cancelScroll = function(e) {
	
	e = e ? e : window.event;
	if(e.stopPropagation)
		e.stopPropagation();
	
	if(e.preventDefault)
    	e.preventDefault();
  
	e.cancelBubble 	= true;
	e.cancel 		= true;
	e.returnValue	= false;
	return false;
};

/**
 * Create the section buttons
 */
RaCarousel.prototype.generateSectionButtons = function () {
	var $elements = '';
	
	for($i = 0; $i < this.carouselStack.length; $i++) {
		$elements += '<div class = "carousel-section-button" id = "'+ $i +'">&nbsp;</div>';
	}
	$('.carousel-section-buttons-container').html($elements);
};

/**
 * Start autoscrolling
 */
RaCarousel.prototype.startScroll = function() {
	this.scroll = true;
	this.autoScroll();
};

/**
 *  Stop autoscrolling
 */
RaCarousel.prototype.stopScroll = function() {
	 this.scroll = false;
	 window.clearTimeout(this.timer);
     this.timer = null;
};

/**
 * Autoscroll management
 */
RaCarousel.prototype.autoScroll = function() { 
	$self = this;
	this.timer = window.setTimeout(function(){$self.doScroll();}, this.delay);
};

/**
 * Scrolling action
 */
RaCarousel.prototype.doScroll = function() {
	this.animateRight();
	this.autoScroll();
};

/**
 * Animate the carousel right
 */
RaCarousel.prototype.animateRight = function() {
	if(!this.locked)
	{
		if(this.currentItem == this.carouselStack.length-1) {
			this.move(this.carouselStack[0], this.carouselStack[this.currentItem], 'right');
			this.currentItem = 0;
		}
		else {
			this.move(this.carouselStack[Number(this.currentItem) + 1], this.carouselStack[this.currentItem], 'right');
			this.currentItem++;
		}
		this.makeButtonActive();
	}
};

/**
 * Animate the carousel left
 */
RaCarousel.prototype.animateLeft = function() {
	if(!this.locked)
	{
		if(this.currentItem == 0) {
			this.move(this.carouselStack[this.carouselStack.length-1], this.carouselStack[0], 'left');
			this.currentItem = this.carouselStack.length-1;
		}
		else {
			this.move(this.carouselStack[this.currentItem-1], this.carouselStack[this.currentItem], 'left');
			this.currentItem--;
		}
		this.makeButtonActive();
	}
};

/**
 * Make the active section-button highlighted;
 */
RaCarousel.prototype.makeButtonActive = function() {
	$('.carousel-section-button').css({background: 'transparent url(/img/SB.png) 0 0 no-repeat'});
	$('.carousel-section-buttons-container #'+this.currentItem).css({background: 'transparent url(/img/SBAct.png) 0 0 no-repeat'});
};

/**
 * Animate the carousel, jumping to the index supplied
 * 
 * @params int $carouselItem
 */
RaCarousel.prototype.animateJumpTo = function($carouselItem) {

	// Check if autoscroll was in effect
	if(this.scroll) {
		this.stopScroll();
		var $scrolling = true;
	}
	
	// Interrupt & Reset Carousel
	$(this.carouselStack).stop(true, true);
	this.currentItem = $carouselItem;
	this.makeButtonActive();
	
	this.locked = false;
	
	// Move items to correct places
	$(this.carouselStack).css({left: -this.width});
	$(this.carouselStack[$carouselItem]).css({left: '0px'});
};

/**
 * Move carousel item
 * 
 * @param jQuery Object $inItem
 * @param jQuery Object $outItem
 * @param string $direction
 */
RaCarousel.prototype.move = function($inItem, $outItem, $direction) {
	$self = this;
	this.locked = true;
	$($outItem).css({left: "0px"});
	$($inItem).css({left:  (($direction == 'right') ? $self.width : -$self.width) + 'px'});
	$($inItem).animate({left: "0px"}, {
		duration: $self.speed,
		step: function($currentLeft) {
			$($outItem).css({left: $currentLeft + (($direction == 'right') ? -$self.width : $self.width) +'px'});
		},
		complete: function() {
			$($outItem).css({left: -$self.width + "px"});
			$self.locked = false;
		}
	});
};

//-----------------------------------------------------------------------------

/**
 * Define RA Carousel2 object
 *
 * @see http://www.simplefadeslideshow.com/
 */
function RaCarousel2($speed, $interval){
	
	$('.main-wrapper').css('overflow', 'visible');
    jQuery('#carousel2-slideshow').fadeSlideShow({
        width: 598,
		height: 300,
		speed: $speed, // default animation transition speed
		interval: $interval, // default interval between image change
		PlayPauseElement: false, //'carousel2-play-pause',// default css id for the play / pause element or false
		NextElement: false, // default id for next button or false
		PrevElement: false, // default id for prev button or false
		ListElement: 'carousel2-numbers', // default id for image / content controll list
		ListLi: 'carousel2-number', // default class for li's in the image / content controll
		ListLiActive: 'carousel2-number-active', // default class for active state in the controll list
		allowKeyboardCtrl: false, // allow keyboard controlls left / right / space
		autoplay: true // autoplay the slideshow
    });
};

//-----------------------------------------------------------------------------
///**
// * Define RA Slider object
// *
// * @param int $speed
// */
//function RaSlider($speed, $sliderId) {
//
//	// Set variables
//	this.sliderId = $sliderId + " ";
//	this.sliderStack = $(this.sliderId + RaSlider.SLIDER_ITEM_CLASS).toArray();
//	this.currentItem = 0;
//	this.speed = $speed;
//	this.locked = false;
//	this.itemQueue = [];
//	this.width = 232;
//	this.height = 48;
//	this.itemWidth = 48 ;
//
//	if(this.sliderStack.length < 4) {
//		for($i in this.sliderStack) {
//			this.itemQueue.unshift(this.sliderStack[$i]);
//		}
//		this.init();
//		$(this.sliderId + RaSlider.SLIDER_BUTTON_LEFT_CLASS).css('display', 'none');
//		$(this.sliderId + RaSlider.SLIDER_BUTTON_RIGHT_CLASS).css('display', 'none');
//		// FIXME: Bit of a hack, leave until CSS is properly sorted then auto it.
//		$(this.sliderId + RaSlider.SLIDER_CONTAINER_CLASS).css('left', '10px');
//		return;
//	}
//
//	// Populate Queue with initial values
//	this.itemQueue.unshift(this.sliderStack[this.currentItem]);
//	this.itemQueue.unshift(this.sliderStack[this.currentItem+1]);
//	this.itemQueue.unshift(this.sliderStack[this.currentItem+2]);
//	this.itemQueue.unshift(this.sliderStack[this.currentItem+3]);
//	this.currentItem = this.currentItem + 3;
//
//	// Attach Events
//	$self = this;
//	$(this.sliderId + RaSlider.SLIDER_BUTTON_LEFT_CLASS).bind('click', function () {
//		$self.animateLeft();
//	});
//
//	$(this.sliderId + RaSlider.SLIDER_BUTTON_RIGHT_CLASS).bind('click', function () {
//		$self.animateRight();
//	});
//
//	// TODO: Implement this for multiple sliders
//	//$container = document.getElementById('slider-container');
//	// Attach MouseWheel Listener or normal browsers
//	//if($container.addEventListener) {
//	//	$container.addEventListener('DOMMouseScroll', function(e) {$self.mouseWheelMove(e);}, false);
//	//	$container.addEventListener('mousewheel', function(e) {$self.mouseWheelMove(e);}, false);
//	//}
//	// Attach MouseWheel Listener for IE
//	//else if($container.attachEvent)
//	//	$container.attachEvent("onmousewheel", function(e) {$self.mouseWheelMove(e);});
//
//	this.init();
//};
//
///**
// * Class Constants
// */
//RaSlider.SLIDER_CONTAINER_CLASS = ".slider-container";
//RaSlider.SLIDER_ITEM_CLASS = ".slider-item";
//RaSlider.SLIDER_BUTTON_LEFT_CLASS = ".slider-button-left";
//RaSlider.SLIDER_BUTTON_RIGHT_CLASS = ".slider-button-right";
//
///**
// * Initiates the Slider
// */
//RaSlider.prototype.init = function() {
//	var $location = 0;
//	for($i in this.itemQueue) {
//		$(this.itemQueue[$i]).css({left: $location+'px'});
//		$location += this.itemWidth + 10;
//	}
//};
//
///**
// * Handles the mouse wheel event
// */
//RaSlider.prototype.mouseWheelMove = function(e) {
//	e = e ? e : window.event;
//	var event = e;
//	var $wheelData = event.detail ? event.detail * -1 : event.wheelDelta / 40;
//	if($wheelData > 0)
//		this.animateRight();
//	else
//		this.animateLeft();
//	// Non jQuery event intercept
//	this.cancelScroll(e);
//};
//
///**
// * Non jQuery event default intercept and stopper
// */
//RaSlider.prototype.cancelScroll = function(e) {
//	e = e ? e : window.event;
//	if(e.stopPropagation)
//		e.stopPropagation();
//	if(e.preventDefault)
//    	e.preventDefault();
//	e.cancelBubble 	= true;
//	e.cancel 		= true;
//	e.returnValue	= false;
//	return false;
//};
//
///**
// * Animate the slider left.
// */
// RaSlider.prototype.animateLeft = function() {
//	if(!this.locked) {
//		if(this.currentItem == this.sliderStack.length-1) {
//			this.itemQueue.unshift(this.sliderStack[0]);
//			this.moveLeft('left');
//			this.currentItem = 0;
//		}
//		else {
//			this.itemQueue.unshift(this.sliderStack[this.currentItem + 1]);
//			this.moveLeft('left');
//			this.currentItem++;
//		}
//	}
//};
//
///**
// * Animate the slider Right.
// */
//RaSlider.prototype.animateRight = function() {
//	if(!this.locked) {
//		if((this.currentItem - 3) == 0 ) {
//			this.itemQueue.push(this.sliderStack[this.sliderStack.length-1]);
//			this.moveRight();
//			this.currentItem--;
//		}
//		else if((this.currentItem - 2) == 0 ) {
//			this.itemQueue.push(this.sliderStack[this.sliderStack.length-2]);
//			this.moveRight();
//			this.currentItem--;
//		}
//		else if((this.currentItem - 1)  == 0) {
//			this.itemQueue.push(this.sliderStack[this.sliderStack.length-3]);
//			this.moveRight();
//			this.currentItem--;
//		}
//		else if(this.currentItem  == 0) {
//			this.itemQueue.push(this.sliderStack[this.sliderStack.length-4]);
//			this.moveRight();
//			this.currentItem = this.sliderStack.length-1;
//		}
//		else {
//			this.itemQueue.push(this.sliderStack[this.currentItem - 4]);
//			this.moveRight();
//			this.currentItem--;
//		}
//	}
//};
//
///**
// * Move slider item left
// */
//RaSlider.prototype.moveLeft = function($direction) {
//	$self = this;
//	$newItem = this.itemQueue[0];
//	var $position = new Array();
//
//	this.locked = true;
//	$($newItem).css({left: -$self.itemWidth + 'px'});
//
//	/* @var $distance: this variable is the width + padding/margin */
//	$distance = $self.itemWidth + 10;
//
//	/* @var $position: this array contains all the initial left positions of the objects */
//	for($i in $self.itemQueue) {
//		if(this.itemQueue[$i] instanceof HTMLLIElement) {
//			$position[$i] = $($self.itemQueue[$i]).position().left;
//		}
//	}
//
//	$($newItem).animate({left: "0px"}, {
//		duration: $self.speed,
//		step: function($currentLeft) {
//				for($i in $self.itemQueue)
//					$($self.itemQueue[$i]).css({left: $position[$i] + ($distance - Math.abs($currentLeft))});
//		},
//		complete: function() {
//				$self.locked = false;
//				$self.itemQueue.pop();
//		}
//	});
//};
//
///**
// * Move slider item right
// */
//RaSlider.prototype.moveRight = function() {
//	var $direction = 'right';
//	var $self = this;
//	$(this.itemQueue[this.itemQueue.length - 1]).eq(0).css({left: this.width + 'px'});
//	var $position = new Array();
//
//	this.locked = true;
//
//	/* @var $distance: this variable is the width + padding/margin */
//	var $distance = $self.itemWidth + 10;
//
//	/* @var $position: this array contains all the initial left positions of the objects */
//	for($i in $self.itemQueue) {
//		if(this.itemQueue[$i] instanceof HTMLLIElement) {
//			$position[$i] = $($self.itemQueue[$i]).position().left;
//		}
//	}
//
//	$(this.itemQueue[0]).animate({left: -$distance + 'px'}, {
//		duration: $self.speed,
//		step: function($currentLeft) {
//			for($i in $self.itemQueue)
//				$($self.itemQueue[$i]).css({left: $position[$i] + ($currentLeft)});
//		},
//		complete: function() {
//			$self.locked = false;
//			$self.itemQueue.shift();
//		}
//	});
//};

//-----------------------------------------------------------------------------

/**
 * Define RA ProgressBar object
 * 
 */
function RaProgressBar() {};
RaProgressBar.URL_ENDPOINT = "/file/progress";

RaProgressBar.prototype.init = function($formId) {
	// Configure progress bar object
	this.timer = null;
	// Attach event action
    var $self = this;
    $('#' + $formId).submit(function() {
        // Style form and progress bar
        $self.update({percent:0});
		$('#' + $formId + ' ul.errors').hide();
		$('#' + $formId + ' input[type="submit"]').css('visibility','hidden');
        $('div.pg-progressbar').addClass($formId + '-pg-progressbar').show();
        $('#progressbar').attr('style', 'height:0px;width:0px;');
        // Start observing upload progress
        $self.observeProgress(1500);
    });
};

RaProgressBar.prototype.observeProgress = function($delay) {
	$self = this;
	this.timer = window.setTimeout(function(){$self.getProgress();}, $delay);
};

RaProgressBar.prototype.getProgress = function() {
	$self = this;
    $.ajax({
          url: "/file/progress",
          cache: false,
          async: false,
          type: "GET",
          dataType: "json",
          data: ({progress_key:$('#progress_key').val()}),
          success: function($response) {
              if ($response.finished) {
            	  $self.finish();
              } else {
            	  $self.update($response);
                  $self.observeProgress(1000);
              }
          }
    });
};

RaProgressBar.prototype.update = function($data) {
    $('#pg-percent').width($data.percent + '%');
    $('#pg-text-1').html(Math.round($data.percent) + '%');
    $('#pg-text-2').html(Math.round($data.percent) + '%');
};

RaProgressBar.prototype.finish = function() {
    $('#pg-percent').width('100%');
    $('#pg-text-1').html('Done...');
    $('#pg-text-2').html('Done...');
};

RaProgressBar.prototype.validateForm = function() {
     var emptyField = false;
     if ($('#upload-terms').attr('checked') == false) {
         emptyField = true;
         $('#upload-terms').blur();
     }
     if ($('#upload-copy').attr('checked') == false) {
         emptyField = true;
         $('#upload-copy').blur();
     }
     if (emptyField == true) {
         return false;
     }
     return true;
};

//-----------------------------------------------------------------------------

/**
 * Define RA FancyBox object
 * 
 */
function RaFancyBox() {};

/**
 * Init FancyBox dialogue
 *
 * @param $id
 * @param $url Optional
 * @param $height Optional
 * @param $width Optional
 */
RaFancyBox.prototype.init = function($id, $url, $height, $width) {

    $('#' + $id).live('click', function($event) {
		if($url == null) {
			$url = $(this).attr('href');
		}
		if($url == '' || typeof $url === 'undefined') {
			return true;
		}
		$event.preventDefault();
        $RaFB.dialogue($url, $height, $width);
    });
};

/**
 * FancyBox dialogue
 *
 * @param $url
 * @param $height
 * @param $width
 */
RaFancyBox.prototype.dialogue = function($url, $height, $width) {

	if($url != null) {
		var $data = {
			'href': $url,
			'type': 'ajax',
			'autoScale': false,
			'overlayColor': '#909381'
		};
		// Define FacyBox dimensions
		if ($height == 'auto') {
			var $size = $(window).height() - 100;
			$data.height = $size;
			$data.width = (($width != null) ? $width : 600);
			$data.autoDimensions = false;
		} else {
			if($height != null || $width != null) {
				$data.height = (($height != null) ? $height : 500);
				$data.width = (($width != null) ? $width : 500);
				$data.autoDimensions = false;
			} else {
				$data.autoDimensions = true;
				$data.scrolling = 'no';
			}
		}
		// Open FancyBox
		$.fancybox($data);
	}
};

/**
 * Close dialogue
 */
RaFancyBox.prototype.closefb = function() {
	$.fancybox.close();
};

/**
 * Instantiate default RaFancyBox Object
 */
var $RaFB = new RaFancyBox;

//-----------------------------------------------------------------------------

/**
 * Define RA Sorter object
 *
 */
function RaSorter() {};

/**
 * Init RaSorter
 *
 * @param $selector
 */
RaSorter.prototype.init = function($selector) {
    $("#" + $selector ).sortable();
	$("#" + $selector ).disableSelection();
	$('#sort-end').click(function(){
		var $result = $("#" + $selector ).sortable('toArray');
		var $order = $result.toString();
		$.ajax({
			url: "/art/save-sorting",
			type: "POST",
			dataType: "json",
			data: ({order:$order}),
			success: function($data){
				if ($data == true) {
					location.reload();
				} else {
					$RaFB.closefb();
				}
			}
		});
	});
};
//-----------------------------------------------------------------------------

/**
 * Define RA Widget object
 *
 */
function RaWidget() {};

/**
 * Init color picker
 */
RaWidget.prototype.initColorPickers = function() {
	$("#header_background_picker").farbtastic("#header_background_color");
	$("#header_text_picker").farbtastic("#header_text_color");
	$("#body_background_picker").farbtastic("#body_background_color");
	$("#body_text_picker").farbtastic("#body_text_color");
	$("#badge_background_picker").farbtastic("#badge_background_color");
};

/**
 * Display section with color settings
 */
RaWidget.prototype.showColorElements = function() {
	$('a#set_widget_colors').click(function() {
		$(this).hide();
		$('#header_background_group').show();
		$('#header_text_group').show();
		$('#body_background_group').show();
		$('#body_text_group').show();
		$('#widget_logo_element').show();	
	});
};

RaWidget.prototype.showColorPickers = function() {
	$('#header_background_color').focus(function() {
		$('#header_background_picker').show();
	});
	$('#header_text_color').focus(function() {
		$('#header_text_picker').show();
	});
	$('#body_background_color').focus(function() {
		$('#body_background_picker').show();
	});
	$('#body_text_color').focus(function() {
		$('#body_text_picker').show();
	});
	$('#badge_background_color').focus(function() {
		$('#badge_background_picker').show();
	});
};

RaWidget.prototype.setDefaultSettings = function() {
	$('select#size').change(function() {
		// Hide all color settings
		$('div.widget-options').hide();
		$('a#set_widget_colors').hide();
		$('#header_background_picker').hide();
		$('#header_background_group').hide();
		$('#header_text_picker').hide();
		$('#header_text_group').hide();
		$('#body_background_picker').hide();
		$('#body_background_group').hide();
		$('#body_text_picker').hide();
		$('#body_text_group').hide();
		$('#widget_logo_element').hide();
		$('#badge_background_picker').hide();
		$('#badge_background_group').hide();
		$('div.badge-group').hide();
		// Hide widget options
		$('div.widget-options').hide();
		var $size = $('select#size').val();
		if ($size == 1) { //badge
			$('div.badge-group').show();
			$('#badge_background_group').show();
			$('select#badge_logo_color').val('black');
			$('input#badge_background_color').val('#CCCDC7');
			$('input#badge_background_color').attr('style', 'background-color:#CCCDC7;color:#000;');
		} else if ($size == 2) { // Small
			$('div.widget-options').show();
			$('a#set_widget_colors').show();
			$('input#header_background_color').val('#5F6352');
			$('input#header_background_color').attr('style', 'background-color:#5F6352;color:#FFF;');
			$('input#header_text_color').val('#FFFFFF');
			$('input#header_text_color').attr('style', 'background-color:#FFFFFF;');
			$('input#body_background_color').val('#CCCDC7');
			$('input#body_background_color').attr('style', 'background-color:#CCCDC7;');
			$('input#body_text_color').val('#5F6352');
			$('input#body_text_color').attr('style', 'background-color:#5F6352;color:#FFF;');
			$('select#widget_logo_color').val('medium');
		}else if ($size == 3) { // Medium
			$('div.widget-options').show();
			$('a#set_widget_colors').show();
			$('input#header_background_color').val('#E4E4DE');
			$('input#header_background_color').attr('style', 'background-color:#E4E4DE;');
			$('input#header_text_color').val('#5A5A5A');
			$('input#header_text_color').attr('style', 'background-color:#5A5A5A;color:#FFF;');
			$('input#body_background_color').val('#FBFBFB');
			$('input#body_background_color').attr('style', 'background-color:#FBFBFB;');
			$('input#body_text_color').val('#5F6352');
			$('input#body_text_color').attr('style', 'background-color:#5F6352;color:#FFF;');
			$('select#widget_logo_color').val('medium');
		}
	});
};

RaWidget.prototype.preview = function() {
	$('#preview').click(function() {
		var $size = $('#size').val();
		var $width = 235;
		var $height = 75;
		if ($size == '3') {
			$width = 310;
			$height = 355;
		} else if ($size == '2') {
			$width = 210;
			$height = 420;
		}
		var $option = 0;
		$('input.option-element:checked').each(function(){
			$option += parseInt($(this).val());
		});
		var $colorHeaderBackground = $('#header_background_color').val().replace(/#/g, '');
		var $colorHeaderText = $('#header_text_color').val().replace(/#/g, '');
		var $colorBodyText = $('#body_text_color').val().replace(/#/g, '');
		if ($size == '1') {
			var $colorBodyBackground = $('#badge_background_color').val().replace(/#/g, '');
			var $colorLogo = $('#badge_logo_color').val();
		} else {
			var $colorBodyBackground = $('#body_background_color').val().replace(/#/g, '');
			var $colorLogo = $('#widget_logo_color').val();
		}
		$url = '/widget/preview/'
			+'size/' + $size
			+'/option/' + $option
			+'/colorBodyBackground/' + $colorBodyBackground
			+'/colorBodyText/' + $colorBodyText
			+'/colorHeaderBackground/' + $colorHeaderBackground
			+'/colorHeaderText/' + $colorHeaderText
			+'/colorLogo/' + $colorLogo;
		
		// Open FancyBox
		$.fancybox({
			'href': $url,			
			'type': 'iframe',
			'autoScale': false,
			'overlayColor': '#909381',
			'scrolling': 'no',
			'autoDimensions': true,
			'width': $width,
			'height': $height
		});
	});
};

//-----------------------------------------------------------------------------

/**
 * Define RA Content Object - Implements singleton pattern
 *
 */
var RaContent = (function() {
	// Hold singleton instance
	var _instance = null;
	
	// Class private constructor
	function __RaContent() {
		
		this.initialized = false;
		
		// Initiailize the AJAX hash and history management
		$(document).ready(function(){
			$.history.init(
		    	function($hash) {
			        if($hash == '' || $hash == null) {
			            // Initialize AJAX state
			        	if(RaContent.getInstance().getBaseTarget() != null) {
			        		RaContent.getInstance().load(RaContent.getInstance().getBaseTarget());
			        	}
			        } else {
			            // Restore the state from hash
			        	var $target = RaContent.getInstance().getParameter($hash, RaContent.URL_PARAM_TARGET);
			        	if($target != null) {
			        		$target = decodeURIComponent($target);
			        	} else if($target == null && RaContent.getInstance().getBaseTarget() != null) {
			        		$target = RaContent.getInstance().getBaseTarget();
			        	}
			        	var $path = RaContent.getInstance().getOption($target, 'path');
			        	if($path != null) {
			        		var $url = $path.replace(/\/$/, '') + '/?' + $hash;
			        	} else if(RaContent.getInstance().getBaseUrl() != null) {
			        		var $url = RaContent.getInstance().getBaseUrl().replace(/\/$/, '') + '/?' + $hash;
			        	} else {
			        		var $url = './?' + $hash;
			        	}
			        	RaContent.getInstance().load($target, $url);
			        }
		    	}
		    );
	    });
		
		/**
		 * Set autload property
		 * 
		 * @param $autoload
		 * @returns boolean
		 */
		this.setAutoLoad = function($autoload) {
			if($autoload === true) {
				this.autoload = true;
			} else {
				this.autoload = false;
			}
			return true;
		};
		
		/**
		 * Get autoload property
		 * 
		 * @returns boolean
		 */
		this.getAutoLoad = function() {
			if(typeof this.autoload !== 'undefined') {
				return this.autoload;
			} else {
				return false;
			}
		};
		
		/**
		 * Get selector configuration option from the stack
		 * 
		 * @param $selector
		 * @param $name
		 * @returns mixed
		 */
		this.getOption = function($selector, $name) {
        	if($selector in this.stack) {
        		if (typeof this.stack[$selector][$name] !== 'undefined') {
        			return this.stack[$selector][$name];
        		}
        	}
			return null;
		};
		
		/**
		 * Set base URL property
		 * 
		 * @param $baseurl
		 * @returns boolean
		 */
		this.setBaseUrl = function($baseurl) {
			this.baseurl = $baseurl;
			return true;
		};
		
		/**
		 * Get base URL property
		 * 
		 * @returns string
		 */
		this.getBaseUrl = function() {
			if(typeof this.baseurl !== 'undefined') {
				return this.baseurl;
			} else {
				return null;
			}
		};
		
		/**
		 * Set base target property
		 * 
		 * @param $target
		 * @returns boolean
		 */
		this.setBaseTarget = function($target) {
			this.baseTarget = $target;
			return true;
		};
		
		/**
		 * Get base target property
		 * 
		 * @returns string
		 */
		this.getBaseTarget = function() {
			if(typeof this.baseTarget !== 'undefined') {
				return this.baseTarget;
			} else {
				return null;
			}
		};
		
		/**
		 * Push hashtag into browser URL
		 * 
		 * @param string $url
		 * @param object $params
		 */
		this.push = function($url, $params) {
			if(typeof $params === 'object') {
				for(var $param in $params) {
					$url = this.appendHashtag($url, $param, $params[$param]);
				}
			}
			$hash = $url.replace(/^.*#/, '');
			$.history.load(decodeURIComponent($hash));
			return false;
		};
		
		/**
		 * Init content section object
		 * 
		 * @param options - An object with any of the following configuration options
		 *   selector - Required, the content area selector
		 *   url - The URL to load for the content area
		 *   mode - The load mode for the content area
		 *   waiting - Selector for the element to hold the loading display
		 *   autoload - (true/false) Whether the content area should be loaded upon initialization (requires URL)
		 *   path - The path to use for the requests (i.e. the /controller/action)
		 *   loader - Function to decide whether to load any additional selectors
		 *   effect - (true/false) Whether we animate the transition
		 */
		this.init = function($options) {
			if(typeof $options.selector === 'undefined') {
				return false;
			}
			var $selector = $options.selector;
			// Build parameters for content area
			var $params = [];
			$params['status'] = RaContent.STATUS_IDLE;
			$params['url'] = (typeof $options.url !== 'undefined') ? $options.url : null;
			if(typeof $options.mode === 'undefined' || $options.mode === null) {
				$params['mode'] = RaContent.LOAD_MODE_PREPEND;
			} else {
				switch($options.mode){
					case RaContent.LOAD_MODE_APPEND:
						$params['mode'] = RaContent.LOAD_MODE_APPEND;
						break;
					case RaContent.LOAD_MODE_PREPEND:
						$params['mode'] = RaContent.LOAD_MODE_PREPEND;
						break;
					case RaContent.LOAD_MODE_REPLACE:
						$params['mode'] = RaContent.LOAD_MODE_REPLACE;
						break;
					case RaContent.LOAD_MODE_REWRITE:
						$params['mode'] = RaContent.LOAD_MODE_REWRITE;
						break;
					default:
						$params['mode'] = RaContent.LOAD_MODE_PREPEND;
						break;
				}
			}
			if(typeof $options.waiting === 'undefined' || $options.waiting === null) {
				$params['waiting'] = null;
			} else {
				$params['waiting'] = $options.waiting;
			}
			if(typeof $options.autoload === 'boolean') {
				$params['autoload'] = $options.autoload;
			} else {
				$params['autoload'] = null;
			}
			if(typeof $options.path === 'string' && $options.path !== '') {
				$params['path'] = $options.path;
			} else {
				$params['path'] = null;
			}
			if(typeof $options.loader !== 'undefined' && $options.loader !== null) {
				$params['loader'] = $options.loader;
			}else {
				$params['loader'] = null;
			}
			if(typeof $options.effect === 'boolean') {
				$params['effect'] = $options.effect;
			} else {
				$params['effect'] = null;
			}
			// Add content area to content stack
			if(this.stack == null || typeof this.stack === 'undefined') {
				this.stack = Array();
			} else if($selector in this.stack) {
				this.stack.splice($selector, 1);
			}
			this.stack[$selector] = $params;
			// Load contents for content area
			if(($params['autoload'] === true || ($params['autoload'] !== false && this.autoload === true)) && $params['url'] != null) {
				this.load($selector);
			}
		};
		
		/**
		 * Load content for content object
		 * 
		 * @param $selector
		 * @param $url
		 * @param $scroll
		 * @param $parent For internal use only, defines the parent content area for cascading requests
		 * @returns boolean
		 */
		this.load = function($selector, $url, $scroll, $parent) {
			if(!($selector in this.stack)) {
				return false;
			}
			if($url == null || typeof $url === 'undefined' || $url === "") {
				$url = this.stack[$selector]['url'];
				if($url == null || typeof $url === 'undefined' || $url === "") {
					return false;
				}
			} else {
				this.stack[$selector]['url'] = $url;
			}
			// Append parameters to URL
			$url = this.appendParameter($url, RaContent.URL_PARAM_TARGET, $selector, true);
			$load = (this.initialized !== true) ? 1 : 0;
			$url = this.appendParameter($url, RaContent.URL_PARAM_LOAD, $load, true);
        	if(this.stack[$selector]['path'] != null) {
        		$url = this.replacePath($url, this.stack[$selector]['path']);
        	}
			// Define callback function
			var $callback = function($response) {
				RaContent.getInstance().renderResponse($selector, $response);
				return false;
			};
			// Set loading status and send request
			this.waitingStart($selector);
			if($scroll !== false) this.scrollToTop($selector);
			$RaJ.send(null, $url, $callback, $callback, true);
			// Load any additional selectors
			if(typeof this.stack[$selector]['loader'] === 'function') {
				$items = this.stack[$selector]['loader']($url, $parent);
				if($parent == null) $parent = $selector;
				if(typeof $items === 'object') {
					for(var $item in $items) {
						this.load($item, $url, $scroll, $parent);
					}
				} else if (typeof $items === 'string') {
					this.load($items, $url, $scroll, $parent);
				}
			}
			return false;
		};
		
		/**
		 * Reload content from a specific content area
		 * 
		 * @param $selector
		 * @param $scroll
		 * @returns boolean
		 */
		this.reload = function($selector, $scroll) {
			
			return this.load($selector, null, $scroll);
		};

		/**
		 * Render JSON response object
		 * 
		 * @param $selector
		 * @param $response
		 * @returns boolean
		 */
		this.renderResponse = function($selector, $response) {
			
			if($response == null)
				return false;
			
			// Display any returned content
			if(typeof $response['content'] !== 'undefined' && $response['content'] !== null) {
				this.renderContent($selector, $response['content']);
			}
			// Display any additional HTML
			if($response['html']) {
				for(var $key in $response['html']) {
					this.renderContent($key, $response['html'][$key]);
				}
			}
			// Display any page error messages
			if(typeof $response['messages'] !== 'undefined' && $response['messages'] !== null) {
				this.renderContent(RaContent.MESSAGES_SELECTOR, $response['messages']);
			} else {
				this.renderContent(RaContent.MESSAGES_SELECTOR, null);
			}
			// Execute any scripts returned
			if(typeof $response['scripts'] !== 'undefined' && $response['scripts'] != null) {
				if(typeof $response['scripts'] === 'object' && $response['scripts'].length > 0) {
				    $.each($response['scripts'], function($index, $script) {
				        $.globalEval($script);
				    });
				} else if (typeof $response['scripts'] === 'string') {
					$.globalEval($response['scripts']);
				}
			}
			// Render done, remove loading status and mark object as initialized
			this.waitingStop($selector);
			this.initialized = true;
			return true;
		};

		/**
		 * Render a specific content area
		 * 
		 * @param $selector
		 * @param $content
		 * @returns boolean
		 */
		this.renderContent = function($selector, $content) {
			
			if($selector == null)
				return
			// Get the load mode and effect for the selector
			var $effect = false;
			var $speed = 400;
			var $mode = RaContent.LOAD_MODE_REWRITE;
			if($selector in this.stack) {
				$mode = this.stack[$selector]['mode'];
				$effect = this.stack[$selector]['effect'];
			} else if($selector === RaContent.MESSAGES_SELECTOR) {
				$mode = RaContent.MESSAGES_LOAD_MODE;
			}
			
			// Fix for HTML5 elements in IE8 and earlier
			var $scripts = null;
			if ($content != null && $.browser.msie && parseInt($.browser.version, 10) < 9) {
				// Turn effects off by default for IE8 and earlier
				$effect = false;
				// Extract any inline scripts from HTML and run content through innerShiv
				if (typeof innerShiv === 'function') {
					var $regexp = /<script[^>]*>([\s\S]+?)<\/script>/gi;
					$scripts = $content.match($regexp);
					if ($scripts != null && $scripts.length) {
					    $content = $content.replace($regexp, '');
					}
					$content = innerShiv($content, false);
				}
			}
			// Display the content
			switch($mode) {
				case RaContent.LOAD_MODE_APPEND:
					if($effect === true) {
						$($selector).fadeOut($speed, function(){
							$(this).append($content).fadeIn($speed);
						});
					} else {
						$($selector).append($content);
					}
					break;
				case RaContent.LOAD_MODE_PREPEND:
					if($effect === true) {
						$($selector).fadeOut($speed, function(){
							$(this).prepend($content).fadeIn($speed);							
						});
					} else {
						$($selector).prepend($content);
					}
					break;
				case RaContent.LOAD_MODE_REPLACE:
					if($effect === true) {
						$($selector).fadeOut($speed, function(){
							$(this).html($content).fadeIn($speed);
						});
					} else {
						$($selector).html($content);
					}
					break;
				case RaContent.LOAD_MODE_REWRITE:
				default:
					$($selector).replaceWith($content);
					break;
			}
			// For IE8 and before, execute any scripts
			if ($scripts != null && $scripts.length > 0) {
			    $.each($scripts, function($index, $script) {
			        $.globalEval($($script).html());
			    });
			}
			return true;
		};
		
		/**
		 * Append a parameter to the URL query string
		 * 
		 * @param string $url
		 * @param string $name
		 * @param string $value
		 * @param boolean $replace
		 * @returns string
		 */
		this.appendParameter = function($url, $name, $value, $replace) {
			if($url == null || $name == null)
				return $url;
			$name = encodeURIComponent($name);
			$value = encodeURIComponent($value);
			// Parse URL
			$parts = parseUri($url);
			// Check if parameter is already in the path
			if($parts.path != null && $parts.path != '') {
				var $path = $parts.path.split('/');
				if($path.indexOf($name) >= 0) {
					return $url;
				}
			}
			// Check if parameter is in queryString and replace/add
			if($name in $parts.queryKey) {
				if($replace === true) {
					$parts.queryKey[$name] = $value;
					$url = glueUri($parts);
				}
				//return $url;
			} else {
				$url += ($url.indexOf('?') >= 0 ? '&' : '?') + $name + '=' + $value;
			}
			return $url;
		};
		
		/**
		 * Replace the path in the URL
		 * 
		 * @param string $url
		 * @param string $path
		 * @returns string
		 */
		this.replacePath = function($url, $path) {
			if($url == null)
				return $path;
			// Parse and glue URL
			$parts = parseUri($url);
			$parts.path = $path;
			return glueUri($parts);
		};
		
		/**
		 * Append a parameter to the URL hashtag string
		 * 
		 * @param string $url
		 * @param string $name
		 * @param string $value
		 * @returns string
		 */
		this.appendHashtag = function($url, $name, $value) {
			if($url == null || $name == null)
				return $url;
			$name = encodeURIComponent($name);
			$value = encodeURIComponent($value);
			// Check if parameter is in hashtag string
			if($url.indexOf('#') >= 0) {
				var $hash = parseQuery(decodeURIComponent($url.substring($url.indexOf('#') + 1)));
				if($name in $hash) {
					return $url;
				} else {
					$url += encodeURIComponent('&' + $name + '=' + $value);
					return $url;
				}
			} else {
				$url += '#' + encodeURIComponent($name + '=' + $value);
				return $url;
			}
		};
		
		/**
		 * Get a parameter from the URL query string
		 * 
		 * @param string $url
		 * @param string $name
		 * @returns string
		 */
		this.getParameter = function($url, $name) {
			if($url == null || $name == null)
				return null;
			// Parse URL
			$name = encodeURIComponent($name);
			$parts = parseUri($url);
			// Check if parameter is in the path
			if($parts.path != null && $parts.path != '') {
				var $path = $parts.path.split('/');
				if(($key = $path.indexOf($name)) >= 0) {
					if(typeof $path[$key + 1] !== 'undefined' && $path[$key + 1] != null) {
						return $path[$key + 1];
					}
				}
			}
			// Check if parameter is in queryString
			if($name in $parts.queryKey) {
				return $parts.queryKey[$name];
			}
			// Check if parameter is in hashtag string
			if($url.indexOf('=') >= 0) {
				var $query = parseQuery($url);
				if($name in $query) {
					return $query[$name];
				}
			}
			return null;
		};
		
		this.scrollToTop = function($selector) {
			if($selector in this.stack) {
				if(this.stack[$selector]['mode'] !== RaContent.LOAD_MODE_APPEND && ($offset = $($selector).offset()) != null){
					$position = $offset.top - 50;
					if(this.stack[$selector]['waiting'] != null && ($offset = $(this.stack[$selector]['waiting']).offset()) != null) {
						$waiting = $offset.top - 50;
						if($waiting < $position) $position = $waiting;
					}
					if($position < 0) $postion = 0;
					$scrollbar = $(window).scrollTop();
					if($scrollbar > $position) {
						$(window).scrollTop($position);
					}
				}
			}
		};
		
		this.waitingStart = function($selector) {
			// Set status to loading
			if($selector in this.stack) {
				if(this.stack[$selector]['waiting'] != null) {
					$(this.stack[$selector]['waiting']).addClass(RaContent.STATUS_LOADING_CLASS);
				} else {
					$($selector).addClass(RaContent.STATUS_LOADING_CLASS);
				}
				this.stack[$selector]['status'] = RaContent.STATUS_LOADING;
			}
			return true;
		};

		this.waitingStop = function($selector) {
			// Set status to idle
			if($selector in this.stack) {
				var $update = true;
				var $waiting = (this.stack[$selector]['waiting'] != null) ? this.stack[$selector]['waiting'] : $selector;
				this.stack[$selector]['status'] = RaContent.STATUS_IDLE;
				if($waiting != $selector && $waiting in this.stack) {
					if(this.stack[$waiting]['status'] == RaContent.STATUS_LOADING){
						$update = false;
					}
				}
				if($update === true) {
					for(var $key in this.stack) {
						if(this.stack[$key]['waiting'] == $waiting && this.stack[$key]['status'] == RaContent.STATUS_LOADING) {
							$update = false;
							break;
						}
					}
				}
				if($update === true)
					$($waiting).removeClass(RaContent.STATUS_LOADING_CLASS);
			}
			return true;
		};

		this.waitingReset = function($selector) {
			// Reset status for all content areas or the provided one
			if($selector != null && $selector in this.stack) {
				this.stack[$selector]['status'] = RaContent.STATUS_IDLE;
			} else if($selector == null) {
				for(var $key in this.stack) {
					$($key).removeClass(RaContent.STATUS_LOADING_CLASS);
					this.stack[$key]['status'] = RaContent.STATUS_IDLE;
				}
			}
			return true;
		};
	};
	
	// Get singleton instance method
	return new function() {
		this.getInstance = function() {
			if (_instance == null) {
				_instance = new __RaContent();
				_instance.constructor = null;
			}
			return _instance;
		};
	};
})();

/**
 * Class constants
 */
RaContent.URL_PARAM_TARGET = '__target';
RaContent.URL_PARAM_LOAD = '__load';
RaContent.LOAD_MODE_APPEND = 'append';
RaContent.LOAD_MODE_PREPEND = 'prepend';
RaContent.LOAD_MODE_REPLACE = 'replace';
RaContent.LOAD_MODE_REWRITE = 'rewrite';
RaContent.STATUS_IDLE = 0;
RaContent.STATUS_LOADING = 1;
RaContent.STATUS_LOADING_CLASS = 'loading';
RaContent.MESSAGES_SELECTOR = '#page-messages';
RaContent.MESSAGES_LOAD_MODE = RaContent.LOAD_MODE_REPLACE;

//-----------------------------------------------------------------------------

/**
 * parseUri 1.2.2
 * (c) Steven Levithan <stevenlevithan.com>
 * MIT License  
 */
function parseUri (str) {
	var	o   = parseUri.options,
		m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
		uri = {},
		i   = 14;

	while (i--) uri[o.key[i]] = m[i] || "";

	uri[o.q.name] = {};
	uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
		if ($1) uri[o.q.name][$1] = $2;
	});

	return uri;
};
function parseQuery(str) {
	var	o = parseUri.options, query = {};
	str.replace(o.q.parser, function ($0, $1, $2) {
		if ($1) query[$1] = $2;
	});
	return query;
};
function glueUri(parts) {
	var url = "";
	if(parts.protocol != null && parts.protocol != "") {
		url = parts.protocol + '://';
	}
	if(parts.authority != null && parts.authority != "") {
		url += parts.authority;
	}
	if(parts.path != null && parts.path != "") {
		url += ('/' + parts.path.replace(/^\//, '')); 
	}
	if(parts.query != null && parts.query != "") {
		var query = "";
		for(var key in parts.queryKey) {
			if(key != "" && key != null) {
				query += ((query == "" ? "" : "&") + key + ((parts.queryKey[key] != "" && parts.queryKey[key] != null) ? "=" + parts.queryKey[key] : ""));
			}
		}
		if(query != "" && query != null) {
			url = url.replace(/\/$/, '') + '/?' + query;
		}
	}
	if(parts.anchor != null && parts.anchor != "") {
		url += ('#' + parts.anchor);
	}
	return url;
};
parseUri.options = {
	strictMode: false,
	key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
	q:   {
		name:   "queryKey",
		parser: /(?:^|&)([^&=]*)=?([^&]*)/g
	},
	parser: {
		strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
		loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
	}
};

