/*

jQuery opaqueChildren plugin 1.0

$Id: jquery.opaqueChildren.js 43 2010-04-09 00:55:06Z christian $

Sets opacity while keeping children 100% opaque. 
Automated implementation of this CSS based solution:
http://www.visibilityinherit.com/code/css-opacity.php

ASSUMPTION:
	- the container to make transparent has a display
		of block, either by default or user-defined;

TESTED:
	On Windows: IE6-7-8, FF3.5.9, Safari4.0.5, Opera10.51, Chrome4.1

*/

(function($) {

	var pluginName = 'opaqueChildren';

	$.fn[pluginName] = function(params) {

		var // functions

		buildSettings = function() {
			var out = {};
			if (typeof params == 'object')
				$.extend(out, defaults, params);
			else
				$.extend(out, defaults);
			return out;
		},

		firstValid = function(values, type) {
			for (var i = 0; i < values.length; i++)
				if (isValid(values[i], type))
					return values[i];
		},

		fixBugs = function(extraDiv) {
			// dynamic CSS for IE6 and IE7 in quirks mode
			var style = extraDiv.get(0).style;
			if (this.innerHeight() > extraDiv.innerHeight()){
				if (style.setExpression) {
					style.setExpression("height","this.parentNode.clientHeight");
				}
			}
			if (this.innerWidth() > extraDiv.innerWidth()){
				if (style.setExpression) {
					style.setExpression("width","this.parentNode.clientWidth");
				}
			}
			// IE bug related to alpha filter and clearType
			var style = this.get(0).style;
			if (style.removeAttribute) {
				style.removeAttribute('filter');
			}
		},

		preferedInput = function(type, cssInput){
			return firstValid([
				getParam(type),
				cssInput,
				defaults[type]
			], type);
		},

		getBgcolor = function(cssInput){
			return preferedInput('bgcolor', cssInput);
		},

		getOpacity = function(cssInput){
			return preferedInput('opacity', cssInput);
		},

		getParam = function(key) {
			if (key == 'opacity' && ( typeof params == 'number' || typeof params == 'string') )
				return params;
			if (typeof params == 'object')
				return params[key];
			return undefined;
		},

		getPosition = function(pos) {
			if (pos == 'fixed' || pos == 'absolute')
				return pos;
			return 'relative';
		},

		isValid = function(v, type) {

			if (v === undefined)
				return false;

			var valid = false;
			switch (type) {
				case 'opacity' : {
					var n = Number(v);
					valid = (n < 1 && n > 0);
					break;
				};
				case 'bgcolor' : {
					valid = (String(v).length > 0);
					break;
				};
			};
			return valid;
		},

		make = function(){
			if (this.data( pluginName ))
				return;
			var extraDiv,
				opacity = getOpacity( this.css('opacity') ),
				bgcolor = getBgcolor( this.css('background-color') ),
				position = getPosition( this.css('position') );
			prepare.call( this, position );
			extraDiv = putExtraDiv.call( this, bgcolor, opacity );
			fixBugs.call( this, extraDiv );
			this.data( pluginName, true );
		},

		prepare = function(position){
			return this.css({
				'position' : position,
				'background-color' : 'transparent',
				'opacity' : '1'
			});
		},

		putExtraDiv = function(bgcolor, opacity){
			return $('<div />')
				.addClass(settings.extraDivClass)
				.css({
					'background-color' : bgcolor,
					'bottom' : '0',
					'left' : '0',
					'opacity' : opacity,
					'position' : 'absolute',
					'top' : '0',
					'width' : '100%',
					'z-index' : '-100',
					'-moz-border-radius' : '6px',
					'-webkit-border-radius' : '6px',
					'border-radius' : '6px'
				})
				.prependTo(this);
		};

		var // variables

		defaults = {
			'opacity' : 0.5,
			'bgcolor' : 'transparent',
			'extraDivClass' : pluginName + '-extraDiv'
		},

		settings = buildSettings();

		// run

		this.each(function(){
			make.call( $(this) );
		});

		return this;

	};

})(jQuery);

