(function($j) {
	
	$j.fn.shadowEnable  = function() { return $j(this).find("+ .fx-shadow").show().end();   };
	$j.fn.shadowDisable = function() { return $j(this).find("+ .fx-shadow").hide().end();   };
	$j.fn.shadowDestroy = function() { return $j(this).find("+ .fx-shadow").remove().end(); };
	
	$j.fn.shadow = function(options) {
		options = $j.extend({
			offset:  1,
			opacity: 0.2,
			color:   "#000",
			monitor: false
		}, options || {});
		options.offset -= 1;
		
		return this.each(function() {
			
			// Remove an existing shadow if it exists
			var $jelement = $j(this).shadowDestroy(),
			
			// Create a shadow element
			$jshadow = $j("<div class='fx-shadow' style='position: relative;'></div>").hide().insertAfter($jelement);
			
			// Figure the base height and width
			baseWidth  = $jelement.outerWidth(),
			baseHeight = $jelement.outerHeight(),
			
			// Get the offset
			position = $jelement.position(),
			
			// Get z-index
			zIndex = parseInt($jelement.css("zIndex")) || 0;
			
			// Append smooth corners
			$j('<div class="fx-shadow-color fx-shadow-layer-1"></div>').css({ position: 'absolute', opacity: options.opacity - 0.05,  left: options.offset,     top: options.offset,     width: baseWidth + 1, height: baseHeight + 1 }).appendTo($jshadow);
			$j('<div class="fx-shadow-color fx-shadow-layer-2"></div>').css({ position: 'absolute', opacity: options.opacity - 0.10,  left: options.offset + 2, top: options.offset + 2, width: baseWidth,     height: baseHeight - 3 }).appendTo($jshadow);
			$j('<div class="fx-shadow-color fx-shadow-layer-3"></div>').css({ position: 'absolute', opacity: options.opacity - 0.10,  left: options.offset + 2, top: options.offset + 2, width: baseWidth - 3, height: baseHeight     }).appendTo($jshadow);
			$j('<div class="fx-shadow-color fx-shadow-layer-4"></div>').css({ position: 'absolute', opacity: options.opacity,         left: options.offset + 1, top: options.offset + 1, width: baseWidth - 1, height: baseHeight - 1 }).appendTo($jshadow);
			
			// Add color
			$j("div.fx-shadow-color", $jshadow).css("background-color", options.color);
			
			// Set zIndex +1 and make sure position is at least relative
			// Attention: the zIndex will get one higher!
			$jelement
				.css({
					zIndex: zIndex + 1,
					position: ($jelement.css("position") == "static" ? "relative" : "")
				});
			
			// Copy the original z-index and position to the clone
			// alert(shadow); If you insert this alert, opera will time correctly!!
			$jshadow.css({
				position:     "absolute",
				zIndex:       zIndex,
				top:          position.top+"px",
				left:         position.left+"px",
				width:        baseWidth,
				height:       baseHeight,
				marginLeft:   $jelement.css("marginLeft"),
				marginRight:  $jelement.css("marginRight"),
				marginBottom: $jelement.css("marginBottom"),
				marginTop:    $jelement.css("marginTop")
			}).fadeIn();
			
			
			if ( options.monitor ) {
				function rearrangeShadow() {
					var $jelement = $j(this), $jshadow = $jelement.next();
					// $jshadow.css( $jelement.position() );
					$jshadow.css({
						top:  parseInt($jelement.css("top"))  +"px",
						left: parseInt($jelement.css("left")) +"px"
					})
					$j(">*", $jshadow).css({ height: this.offsetHeight+"px", width: this.offsetWidth+"px" });
				}
			
				// Attempt to use DOMAttrModified event
				$jelement.bind("DOMAttrModified", rearrangeShadow);
			
				// Use expressions if they exist (IE)
				if( $jshadow[0].style.setExpression ) {
					$jshadow[0].style.setExpression("top" , "parseInt(this.previousSibling.currentStyle.top ) + 'px'");
					$jshadow[0].style.setExpression("left", "parseInt(this.previousSibling.currentStyle.left) + 'px'");
				}
			}

		});
	};
	
})(jQuery);