/*
	Name: jQuery Context Menu Plugin
	By: James Harris
	Creation Date: 4/6/2010
	Revision Date: 4/27/2010
	
	Purpose:
		In supporting browsers displays a customizable context menu on right click
	
	Global Variables:
		currentMousePos - Updated automatically
		contextMenuLoadingGraphic - Filepath to an image to be used as a loading graphic
			www.loadinfo.net Has many customizable gifs should you desire to get a new graphic
		closeHandlerBound - Leave false. Updated automatically
	
	Options:
		clickHandler - Function that gets called when an element in the popup is clicked.
					   The trigger entity and the event are passed in.
		contextTypeAttribute - The attribute of the trigger entity to be passed to the menu file as [contextType]
					   Reccomended usage of this data is to dynamically display certain options (switch(contextType))
		menuFile - Location of the menu file to be loaded into the context menu
		triggerElement - What type of HTML entity will trigger the clickHandler
		cache - Whether or not to cache the menu. This provides for faster loading on following clicks
		immediate - True or False. Whether or not to open the Context Menu on creation
		startingMousePos - Extra data. Useful for immediate mode. When creating the context object use event.pageX/Y as values.
*/
(function($) {
	$.fn.contextMenu = function(settings) {
		//Defaults
		settings = $.extend({
			clickHandler: defaultMenuClickHandler,
			contextTypeAttribute: 'contextType',
			menuFile: '/menuFile.html',
			menuTriggerElements: 'a',
			cache: true,
			immediate: false,
			startingMousePos: {pageX: 0, pageY: 0}
		}, settings);
		
		//Bind all elements setup to open the context menu
		this.each(function() {
			//Default data for the element
			$(this).data('cachedMenu', '');
			$(this).data('settings', settings);
			
			//Bind the handler.
			$(this).bind('contextmenu', function(event) {				
				//Save the mouse position from the event into our global variable
				currentMousePosition = {pageX: event.pageX, pageY: event.pageY};
				
				//Execute the menu as normal
				showMenu(this);
				
				//Stop the browser's context menu from opening
				return false;
			});
			
			//If this context is set as "immediate" let's load it using the predefined mouse position
			if(settings.immediate) {
				//Store the mouse data into the global variable and execute the menu
				currentMousePosition = settings.startingMousePos;
				showMenu(this);
			}
		});
		
		/***********************
		****Element Triggers****
		***********************/
		
			//Append the container to the body. There can only be one context menu div
			if($('div#context-menu').size() == 0)
				$(document.body).append("<div id='context-menu'></div>");
			
			//Bind a click on the document to close the context menu
			if(!closeHandlerBound) {
				$(document).click(function() {closeContextMenu();});
				closeHandlerBound = true;
			}
		
		return this;
	}
})(jQuery);

/*****************************************************************
****Public variables that all Context Menu objects will access****
*****************************************************************/
var currentMousePosition = {pageX: 0, pageY: 0};
var closeHandlerBound = false;
var contextMenuLoadingGraphic = "<img src='/_javascript/jQuery/contextMenu/images/loading.gif' />";

/***********************************************************
****Functions That Should Only Be Called From The Plugin****
***********************************************************/
//Close the context menu down
function closeContextMenu() {
	$('div#context-menu').html('').css('display', 'none');
}

function bindMenuTriggers(triggerElement, settings, theMenu) {
	//Bind the trigger element clicks
	$(settings.menuTriggerElements, theMenu).click(function(event) {
		//Execute the click handler they set up
		var retVal = settings.clickHandler(triggerElement, this, event);
		
		//Close the context menu
		closeContextMenu();
		
		//Return the retrieved return value from the handler
		return retVal;
	});
}

function showMenu(triggerElement) {
	//Retrieve the settings for this element
	var settings = $(triggerElement).data('settings');
	
	//Set the menu position prier to showing it
	$('div#context-menu').css('top', currentMousePosition.pageY).css('left', currentMousePosition.pageX);

	//If caching is on, and this menu has been cached, load the cache, not the ajax call.
	if(settings.cache == true && $(triggerElement).data('cachedMenu').length > 0) {
		$('div#context-menu').html($(triggerElement).data('cachedMenu')).css('display', 'block');
		
		//Bind the trigger element clicks
		bindMenuTriggers(triggerElement, settings, $('div#context-menu'));
	} else {
		$('div#context-menu').css('display', 'block').html(contextMenuLoadingGraphic).load(settings.menuFile, {contextType: $(triggerElement).attr(settings.contextTypeAttribute), triggerElementText: $(triggerElement).html()}, function() {		
			//Bind the trigger element clicks
			bindMenuTriggers(triggerElement, settings, this);
			
			//If they wanted caching let's save this for faster access next time around
			if(settings.cache == true)
				$(triggerElement).data('cachedMenu', $(this).html());
		});
	}
}

/*****************************************************
****General Functions That Everyone Can Know About****
*****************************************************/
function removeContextTrigger(triggerElement) {
	$(triggerElement).remove();
}

function genContextMenu(event) {
	//Store the mouse position
	event.data.settings.startingMousePos = {pageX: event.pageX, pageY: event.pageY};
	
	//Attach the context menu
	$(event.data.theElement).contextMenu(event.data.settings);
	
	//Unbind the contextMenu handler so we don't try to create anymore for this object
	$(event.data.theElement).unbind('contextmenu', genContextMenu);
	
	//Kill the document's context menu
	return false;
}

function defaultMenuClickHandler(triggerElement, theLink, event) {
	//They clicked a link
	switch($(theLink).attr('action')) {
		case "link":
			window.open($(theLink).attr('href'));
			break;
		case "load":
			//If the load tab is set do the load.
			if($(theLink).attr('loadTab')) {
				$('div.tab-body').load($(theLink).attr('href'), '', function() {
				});
			}
			break;
		case "post":
			$.post($(theLink).attr('href'), {}, function(data) {
				if(data.indexOf('true') != -1) {
					if($(theLink).attr('rel').indexOf('callback:') != -1)
						eval($(theLink).attr('rel').split('callback:')[1].split(']')[0])(data);
				}
			});
			break;
	}
	
	//Return false so the link doesn't execute in this window
	return false;
}