/*

VERSION: Drop Shadow jQuery Plugin 1.6 12-13-2007

Updated 09-2010 by linFox -
	- render an shadow colour only, no longer duplicates entire elements.
		good on performance, avoids lots of quirks
		only be able to create shadows on square block elements though now
	- fuller window resize support, resizes and repositions all shadows properly on resize event
		because IE doesn't like 100% dimensions, each component layer of each shadow needs to be recalculated as well
		bad on performance, but necessary
	- maintains any preexisting z-indexing on elements
	- smarter id creation for shadow elements
	- most doco removed to shrink file (author + orig code http://dropshadow.webvex.limebits.com/)
	TODO: look at working around subpixel precision differences between browsers (old IE does it right!)

*/


(function($) {

	var dropShadowZindex = 1; // z-index counter

	$.fn.dropShadow = function(options) {
		// Default options
		var opt = $.extend({
			left: 4,
			top: 4,
			blur: 2,
			opacity: .5,
			color: '#000000',
			swap: false
		}, options);
		var jShadows = $([]); // empty jQuery collection
		
		// Loop through original elements
		this.not('.dropShadow').each(function() {
			var jthis = $(this);
			var shadows = [];
			var blur = (opt.blur <= 0) ? 0 : opt.blur;
			var opacity = (blur == 0) ? opt.opacity : opt.opacity / (blur * 8);
			// linFox: retain set z-indexing
			var zOriginalReal = jthis.css('zIndex') != 'auto' ? parseInt(jthis.css('zIndex')) : dropShadowZindex;
			var zOriginal = (opt.swap) ? zOriginalReal : zOriginalReal + 1;
			var zShadow = (opt.swap) ? zOriginalReal + 1 : zOriginalReal;

			// Create ID for shadow
			var shadowId = (this.id)
				? this.id + '_dropShadow'
				// linFox
				: 'ds' + zShadow;

			// Modify original element
			$.data(this, 'shadowId', shadowId); // store id in expando
			$.data(this, 'shadowOptions', options); // store options in expando
			jthis.attr('shadowId', shadowId).css('zIndex', zOriginal);
			if (jthis.css('position') != 'absolute') {
				jthis.css({
					position: 'relative'
					// linFox: removed, breaks my design (I specify this myself where needed)
					/* zoom: 1 //for IE layout*/
				});
			}

			// Create first shadow layer
			/*
			bgColor = jthis.css('backgroundColor');
			if (bgColor == 'rgba(0, 0, 0, 0)')
				bgColor = 'transparent'; // Safari
			if (bgColor != 'transparent' || jthis.css('backgroundImage') != 'none' || this.nodeName == 'SELECT' || this.nodeName == 'INPUT'|| this.nodeName == 'TEXTAREA') {
				shadows[0] = $('<div></div>').css('backgroundColor', opt.color);
			}
			else {
				shadows[0] = jthis
					.clone()
					.removeAttr('id')
					.removeAttr('name')
					.removeAttr('shadowId')
					.css('color', opt.color);
			}
			*/
			// linFox: removed all of above in order to explicitly create a simple solid colour shadow and not a duplicate of the content.
			// This makes my 100% screen width element shadow correctly.
			shadows[0] = $('<div></div>')
				.addClass('dropShadow')
				.css({
					backgroundColor: opt.color,
					position: 'absolute',
					top: blur,
					left: blur,
					// linFox: this breaks IE at the moment. remove requirement for absolute position on these
					// height: '100%',
					// width: '100%',
					// linFox
					height: jthis.outerHeight(),
					width: jthis.outerWidth(),
					opacity: opacity,
					zIndex: zShadow
				});
				// alert(jthis.outerWidth() + ' ' + parseFloat(this.offsetWidth));

			// Create other shadow layers
			var layers = (8 * blur) + 1;
			for (i = 1; i < layers; i++) {
				shadows[i] = shadows[0].clone();
			}

			// Position layers
			var i = 1;
			var j = blur;
			while (j > 0) {
				shadows[i].css({left: j * 2, top: 0}); // top
				shadows[i + 1].css({left: j * 4, top: j * 2}); // right
				shadows[i + 2].css({left: j * 2, top: j * 4}); // bottom
				shadows[i + 3].css({left: 0, top: j * 2}); // left
				shadows[i + 4].css({left: j * 3, top: j}); // top-right
				shadows[i + 5].css({left: j * 3, top: j * 3}); // bottom-right
				shadows[i + 6].css({left: j, top: j * 3}); // bottom-left
				shadows[i + 7].css({left: j, top: j}); // top-left
				i += 8;
				j--;
			}
			// Create container
			var divShadow = $('<div></div>')
				.attr('id', shadowId) 
				.addClass('dropShadow')
				.css({
					position: 'absolute',
					top: jthis.position().top + opt.top - blur,
					left: jthis.position().left + opt.left - blur,
					marginTop: jthis.css('marginTop'),
					marginRight: jthis.css('marginRight'),
					marginBottom: jthis.css('marginBottom'),
					marginLeft: jthis.css('marginLeft'),
					zIndex: zShadow,
					// linFox
					height: jthis.outerHeight(),
					width: jthis.outerWidth()
				});

			// Add layers to container
			for (i = 0; i < layers; i++) {
				divShadow.append(shadows[i]);
			}

			// Add container to DOM
			jthis.after(divShadow);

			// Add shadow to return set
			jShadows = jShadows.add(divShadow);

			// Re-align shadow on window resize
			$(window).resize(function() {
				try {
					var w = jthis.outerWidth();
					var h = jthis.outerHeight();
					divShadow.css({
						// linFox
						height: h,
						width: w,
						left: jthis.position().left + opt.left - blur,
						top: jthis.position().top + opt.top - blur
					});
					// linFox: bad on performance no doubt. If issue with 100% dimensions are fixed this can be removed
					for (var i in shadows)
						shadows[i].css({width: w, height: h});
				}
				catch(e) {}
			});

			// Increment z-index counter
			dropShadowZindex += 2;

		}); // end each
		return this.pushStack(jShadows);
	};

	$.fn.redrawShadow = function() {
		// Remove existing shadows
		this.removeShadow();
		
		// Draw new shadows
		return this.each(function() {
			var shadowOptions = $.data(this, 'shadowOptions');
			$(this).dropShadow(shadowOptions);
		});
	};

	$.fn.removeShadow = function() {
		return this.each(function() {
			var shadowId = $(this).shadowId();
			$('div#' + shadowId).remove();
		});
	};

	$.fn.shadowId = function() {
		return $.data(this[0], 'shadowId');
	};

	$(function() {
		// Suppress printing of shadows
		$('head').append('<style type="text/css" media="print">.dropShadow { visibility: hidden; }</style>');
	});

})(jQuery);
