/*
	AUTHOR: Larry Stevens (McLars@eyebulb.com)

	VERSION: Drop Shadow 1.0  11-29-2007

	SYNTAX: $(selector).dropShadow([pxLeft][, pxTop]);

	REQUIRES: jquery.js and jquery.dimensions.js

	RETURNS: jQuery object collection

	This jQuery UI plug-in adds soft drop shadows to page elements. It has only 
	one public method, dropShadow, which accepts two optional parameters. These
	parameters specify the distance and direction (x,y coordinates) in pixels, 
	to offset the shadow.

	If no parameters are provided, the default offset is 4 pixels in the bottom-
	right direction. The first parameter specifies the left offset, and the second
	parameter specifies the top offset. If only one parameter is provided, it will
	be used for both left and top offsets. Positive values move the shadowto the 
	bottom and to the right, while negative values move the shadow to the top and	
	to the left.

	The dropShadow method attempts to determine whether the selected elements have
	transparent backgrounds. If you want to shadow the inside of an element, like 
	text or a transparent image, it must not have a background-color or background-
	image style. If the element has a solid background it will create a rectangular
	shadow around the outside box.

	Newly created shadow elements are given a random ID and two classes (see 
	following section). The original elements are given a new attribute named 
	"shadow," which is set to the ID of the associated shadow. The shadow elements
	are positioned absolutely one layer below the original element, which is 
	positioned relatively. 

	When styling, the interior shadows have the class "dropShadowInner" and use the
	color style property while the outside shadows have the class "dropShadowOuter"
	and use the background style property. For example:

		.dropShadowInner {color: red !important;}   for transparent elements, or
		.dropShadowOuter {background: red !important;}   for solid elements
		
	All shadows have the "dropShadow" class, which may be used to globally change 
	the opacity or visibility. To access a single shadow, read the "shadow"
	attribute of the original element (only available at run-time) and then use 
	that for finding the ID of the shadow. For example:
	
		var ShadowId = $("#myText").attr("shadow");
		$("#" + ShadowId + " .dropShadowInner").css("color", "red");

	The dropShadow method supports chaining, so you can add multiple shadows in a 
	single statement. This is useful for darkening or expanding the shadow.
	However, only the last shadow's ID will be available in the original element.
	If you need to manipulate the shadows later, you should store each ID before 
	applying additional shadows.

	EXAMPLES:
		$("h1").dropShadow();           //default offset, 4 pixels at bottom-right
		$("h1").dropShadow(-4,4)        //bottom-left
		$("h1").dropShadow(4,-4)        //top-right
		$("h1").dropShadow(-4)          //top-left
		$("h1").dropShadow(0,4)         //bottom
		$("h4").dropShadow(1);          //smaller offset
		$("#MyGIF").dropShadow(6);      //larger offset
		$("#MyDiv").dropShadow().dropShadow(6);  //larger and darker

	ISSUES: 
		1) Limited styling of shadowed elements by ID, prefer class or inline styles. 
		2) Some elements don't re-adjust properly when page content resizes/reflows.
		3) A few elements, like checkboxes and radio buttons, do not shadow well.
			 Form elements shadow as transparent elements in Opera.
		4) Shadow positions are off when printing. Recommend using the following:
					<style type="text/css" media="print">
						.shadowIn, .shadowOut { visibility: hidden; }
					</style>
*/

var zIndx = 1;

jQuery.fn.dropShadow = function(pxLeft, pxTop)
{
	// Set default offset distances
	pxLeft = (isNaN(pxLeft)) ? 4 : pxLeft;
	pxTop = (isNaN(pxTop)) ? pxLeft : pxTop;

	// Loop through collection of elements
	return this.each(function()
	{
		var shadows = [];
		var jthis = jQuery(this);
		var randomId = "ds" + (1 + Math.floor(9999 * Math.random()));

		// Check original element for transparency
		var bgc, bgi, pos;
		if (this.currentStyle) {
			bgc = this.currentStyle.backgroundColor;
			bgi = this.currentStyle.backgroundImage;
			pos = this.currentStyle.position;
		}
		else {
			bgc = document.defaultView.getComputedStyle(this, null)
						.getPropertyValue("background-color");
			bgi = document.defaultView.getComputedStyle(this, null)
						.getPropertyValue("background-image");
			pos = document.defaultView.getComputedStyle(this, null)
						.getPropertyValue("position");
			if (bgc == "rgba(0, 0, 0, 0)") bgc = "transparent";  // Safari fix
		}

		// Modify original element
		jthis
			.attr("shadow", randomId)
			.css("zIndex", zIndx + 1);
		if (pos != "absolute") {
			jthis.css({
				position: "relative",
				zoom: 1  // IE fix
			});
		}

		// Create first shadow layer
		if (bgc == "transparent" && bgi == "none") {  
			// Copy the original element
			shadows[0] = jthis
				.clone()
				.removeAttr("id")
				.removeAttr("name")
				.removeAttr("shadow")
				.addClass("dropShadowInner")
				.css({
					color: "black",
					height: jthis.outerHeight(),
					width: jthis.outerWidth()
				});
		}
		else {  
			// Create blank div
			shadows[0] = $("<div></div>")
				.addClass("dropShadowOuter")
				.css({
					background: "black"
				});
			switch(this.nodeName) {
				case "SELECT":
					shadows[0].css({
						height: jthis.height() - 1,
						width: jthis.width() - 1
					});
					break;
				case "TEXTAREA":
					shadows[0].css({
						height: jthis.innerHeight() + 1,
						width: jthis.innerWidth() + 1
					});
					break;
				case "TABLE":
					shadows[0].css({
						height: jthis.outerHeight() + 1,
						width: jthis.outerWidth() + 1
					});
					break;
				default:
					shadows[0].css({
						height: jthis.outerHeight(),
						width: jthis.outerWidth()
					});								
			}
		}
		// End if transparent
		shadows[0]
			.addClass("dropShadow")
			.css({
				left: 2,
				opacity: 0.05,
				position: "absolute",
				top: 2,
				zIndex: zIndx
			});

		// Create other shadow layers
		for (i = 1; i < 9; i++) {
			shadows[i] = shadows[0].clone();
		}
		shadows[1].css({left: 2, top: 0});		// Top
		shadows[2].css({left: 4, top: 2});		// Right
		shadows[3].css({left: 2, top: 4});		// Bottom
		shadows[4].css({left: 0, top: 2});		// Left
		shadows[5].css({left: 3, top: 1});		// Top-right
		shadows[6].css({left: 3, top: 3});		// Bottom-right
		shadows[7].css({left: 1, top: 3});		// Bottom-left
		shadows[8].css({left: 1, top: 1});		// Top-left

		// Create shadow container
		var divShadow = $("<div></div>")
			.attr("id", randomId) 
			.addClass("dropShadow")
			.css({
				left: jthis.position().left + pxLeft - 2,
				position: "absolute",
				top: jthis.position().top + pxTop - 2,
				zIndex: zIndx
			});

		// Add layers to container	
		for (i = 0; i < 9; i++) {
			$(divShadow).append(shadows[i]);
		}
		// Add container to DOM
		jthis.after(divShadow);

		// Re-align shadow on window resize
		$(window).resize(function()
		{
			$("#" + randomId).css({
				left: jthis.position().left + pxLeft - 2,
				top: jthis.position().top + pxTop - 2
			});
		});

		// Increment layer counter
		zIndx += 2;

	});  // End each
	
}
