/* 
 * traceBox Plugin
 * v. 1.0 
 * Jon Cazier
 * 9/25/09
 *
 *---------------------------------------------------------------------------------------------------
 * About
 *---------------------------------------------------------------------------------------------------
 * To be used in place of the JavaScript alert() method. There's nothing more annoying 
 * than accidentally calling an alert() in an infinite loop. This was built to drag and
 * drop into a project, so all the styles are handled inside the plugin so that you don't
 * need to worry about adding an additional stylesheet.
 *
 *---------------------------------------------------------------------------------------------------
 * Installation
 *---------------------------------------------------------------------------------------------------
 * This plugin requires the jQuery UI script as well as the core jQuery file. To quickly 
 * drag and drop the plugin, use google's hosted jQuery files:
 *
 * 		<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
 * 		<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js" type="text/javascript"></script>
 *
 * Link to this file:
 *
 *		<script src="[root path]/jquery.traceBox.js" type="text/javascript"></script>
 *
 * Attach the trace box to the body like this:
 *
 * 		$(document).ready(function(){
 * 			$("body").traceBox();			  
 * 		});
 *
 * Then call the trace box anywhere in your code with the following:
 *
 * 		$.trace("insert your message here");
 *
 *---------------------------------------------------------------------------------------------------
 * Configuration
 *---------------------------------------------------------------------------------------------------
 *
 * The configurable options are:
 *
 * 		width		- Sets the fixed width of the box. Default is "400px".
 *					$("body").traceBox({width: "400px"});
 *
 *		minHeight	- Sets the minimum height. Default is "50px".
 *					$("body").traceBox({minHeight: "50px"});
 *
 *  	maxHeight	- Sets the maximum height. Default is "200px".
 *					$("body").traceBox({maxHeight: "200px"});
 *
 *		position	- Sets the position. Default is "topRight".
 *					$("body").traceBox({position: "topRight"});
 *
 *					Available options are:
 *					"topLeft"
 *					"topRight"
 *					"bottomLeft"
 *					"bottomRight"
 *
 *		listStyle	- Determines the style of the listed messages. Default is "decimal".
 *					$("body").traceBox({listStyle: "decimal"});
 *
 *					Any CSS list-style-type property is available such as:
 *					"none"
 *					"circle"
 *					"disc"
 *					"square"
 *					"armenian"
 *					"decimal"
 *
 *		draggable	- Determines whether or not the box is draggable. Default is true
 *					$("body").traceBox({draggable: true});
 *
 *					This option takes a boolean value:
 *					true
 *					false
 *
 */

jQuery.fn.traceBox = function(options){

	//-----------------------------------------------------------------------------------------------
	// Configuration Defaults and Options
	//-----------------------------------------------------------------------------------------------

	var defaults = {
		width: "400px",
		minHeight: "50px",
		maxHeight: "200px",
		position: "topRight",
		listStyle: "decimal",
		draggable: true
	};
	
	var d = $.extend(defaults, options)

	//-----------------------------------------------------------------------------------------------
	// Styles and Functionality
	//-----------------------------------------------------------------------------------------------
	
	// This creates the box where the magic happens
	jQuery(this).prepend("<div class='traceBoxWrapper'><div class='traceBox'><ol></ol></div></div>");
	
	// Based on the option selected, determine the default absolute positioning for the box
	switch(d.position){
		case "topLeft":
			jQuery(".traceBoxWrapper").css({top: "10px", left: "10px"});
			break;
		case "topRight":
			jQuery(".traceBoxWrapper").css({top: "10px", right: "10px"});
			break;
		case "bottomLeft":
			jQuery(".traceBoxWrapper").css({top: "20px", left: "10px"});
			break;
		case "bottomRight":
			jQuery(".traceBoxWrapper").css({bottom: "20px", right: "10px"});
			break;
		default:
			jQuery(".traceBoxWrapper").css({bottom: "20px", right: "10px"});
	};
	
	// traceBoxWrapper Styles and Functionality
	var wrapperCSS = {
		width: d.width,
		background: "#EFEFEF",
		border: "solid 1px #CCC",
		font: "12px 'Courier New', Courier, monospace",
		color: "#333",
		position: "fixed",
		display: "none",
		opacity: 0,
		zIndex: "1000",
		lineHeight: "16px"
	};
	jQuery(".traceBoxWrapper")
		.css(wrapperCSS)
		.prepend("<div class='dragBox'><b>close</b></div>")
		.append("<div class='controlBox'><b>clear</b></div>");
		
	if(d.draggable){
		jQuery(".traceBoxWrapper").draggable({ handle: '.dragBox', opacity: 0.45 });
	};
	
	// traceBox Styles and Functionality
	var boxCSS = {
		padding: "10px",
		minHeight: d.minHeight,
		maxHeight: d.maxHeight,
		overflow: "scroll"
	};
	jQuery(".traceBox").css(boxCSS);	
	
	// dragBox Styles and Functionality
	var dragCSS = {
		background: "#666",
		borderBottom: "solid 1px #CCC",
		cursor: "move",
		textAlign: "right",
		color: "#EFEFEF",
		padding: "2px 10px"
	};
	var closeCSS = {
		cursor: "pointer",
		font: "12px Verdana, Geneva, sans-serif"
	};
	jQuery(".dragBox")
		.css(dragCSS)
		.find("b")
		.css(closeCSS)
		.click(function(){
			hideBox();
		});
	if(!d.draggable){
		jQuery(".dragBox").css({cursor: "default"});	
	};
	
	// Clear Button Styles and Functionality
	var clearCSS = {
		cursor: "pointer"
	};
	jQuery(".controlBox b")
		.css(clearCSS)
		.click(function(){
			clearBox();					
		});	

	// controlBox Styles and Functionality
	var controlCSS = {
		padding: "2px 10px",
		textAlign: "right",
		font: "9px Verdana, Geneva, sans-serif",
		color: "#666"
	};
	jQuery(".controlBox").css(controlCSS);
	
	// controlBox List Items Styles and Functionality
	if(d.listStyle == "none"){
		var traceBoxOl = {
			listStyleType: d.listStyle,
			padding: "0",
			margin: "0"
		};
	} else {
		var traceBoxOl = {
			listStyleType: d.listStyle,
			padding: "0 0 0 15px",
			margin: "0 0 0 10px"
		};
	}
	jQuery(".traceBox ol").css(traceBoxOl);
	
	var traceBoxLi = {padding: "2px 5px"};

	//-----------------------------------------------------------------------------------------------
	// Common methods such as showing and hiding the box
	//-----------------------------------------------------------------------------------------------

	// This is called everytime something is traced to the box to add zebra striping
	function addStripes(){
		jQuery(".traceBox li").css(traceBoxLi);
		jQuery(".traceBox li:odd").css({background: "#DFDFDF"});
	};
	
	// This shows the box
	function showBox(){
		jQuery(".traceBoxWrapper")
			.css({display: "block"})
			.animate({
				opacity: 1						  
			});
	};
	
	// This makes the box disappear
	function hideBox(){
		jQuery(".traceBoxWrapper")
			.animate({
				opacity: 0						  
			}, 200)
			.css({display: "none"});
	};
	
	// This clears the contents of the box
	function clearBox(){
		jQuery(".traceBox ol").html("");
	};
	
	// This is what is called externally to trace messages to to the box
	jQuery.trace = function(msg){
		showBox();
		jQuery(".traceBox ol").append("<li>"+msg+"</li>");
		jQuery(".traceBox").attr({ scrollTop: jQuery(".traceBox").attr("scrollHeight") });
		addStripes()
	};
};
