/*
 * forRef 0.1.5	http://jlix.net/extensions/jquery/forRef/0.1.5
 * 2008-07-15
 *
 * overLabel 0.1.7	http://jlix.net/extensions/jquery/overLabel/0.1.7
 * 2008-10-03
 *
 * popLink 0.1.8	http://jlix.net/extensions/jquery/popLink/0.1.8
 * 2008-07-24
 *
 * Copyright (c) 2009 Sander Aarts	(jlix.net)
 * Dual licensed under the MIT (http://jlix.net/MIT.txt)
 * and GPL (http://jlix.net/GPL.txt) licenses.
 *
 * Requires jQuery to work	(jquery.com). Tested with version 1.2.6
 *
 */
(function($) {
	$.fn.extend( {
		forRef: function() { // v0.1.5
			//	Finds corresponding label(s), input, select or textarea, based on for= attribute of first matched element. Works both ways.
			return this.is("label[for]") ? $("#" + this[0].htmlFor) : $("label[for='" + this[0].id + "']");
		},
		
		overLabel: function() { // v0.1.7
			//	Makes 'overLabel' behavior possible. Works both on labels and form fields.
			//	Concept based on http://www.alistapart.com/articles/makingcompactformsmoreaccessible/
			//	CSS:		.jsOverLabel (on label)
			//				.jsOverLabelBlur (on parent of form field: blur)
			//	Deps.:	forRef() method (v0.1+)
			return this
				.each( function() {
					var jThis = $(this);
					var jRef = jThis.forRef();
					if ( jThis.is("label[for]") ) {
						var jFormControl = jRef;
						var jLabels = jThis;
					} else {
						var jFormControl = jThis;
						var jLabels = jRef;
					}
					if ( !( jFormControl.length > 0 && jLabels.length > 0 ) ) return true;	// continue
					
					jLabels.each( function() {
						$(this).addClass("jsOverLabel");
						if ( jFormControl.val() === "" ) jFormControl.parent().addClass("jsOverLabelBlur");
						jFormControl
							.focus( function() { $(this).parent().removeClass("jsOverLabelBlur"); } )
							.blur( function() { 
								var jFormControl = $(this);
								if ( jFormControl.val() === "" ) jFormControl.parent().addClass("jsOverLabelBlur");
							} )
							.click( function() { 						// needed for Webkit to pass focus to input
								$(this).forRef().each( function() {	// .focus() does not seem to work on every matched element, therefore .each() 
									this.focus();
								} );
							} );
					} );
				} );
		},
		
		popLink: function( props ) { // v0.1.8
			// Opens matching links in popup. Default properties can be overridden with props argument
			// Args.:	props:	[Object]		Key/value pairs of properties that differ from default
			//	CSS:		.jsPopup (on link, default class name can be overridden)
			
			// Default properties may be changed and can be overridden on function call:
			var defProps = {
				target: "_blank",			// [String]		Target name of popup
				blank: false,				// [Boolean]	Blank window: true > no properties are applied / false > properties are applied 
				width: 500,					// [Integer]	Width popup window
				height: 550,				// [Integer]	Height popup window
				absH: false,				// [Boolean]	Horizontal positioning: true > absolute / false > center
				absV: false,				// [Boolean]	Vertical positioning: true > absolute / false > center
				popH: 640,					// [Integer]	Horizontal position. If absHor is false, this value will be used as minimal screen width in case the available screen width is unknown
				popV: 480,					// [Integer]	vertical position. If absVert is false, this value will be used as minimal screen height in case the available screen height is unknown
				print: false,				// [Boolean]	Print version. If true, the toolbar will be shown in case the browser does not support window.print
				props: ["resizable"],	// [Array]		Array with, comma seperated, window propertie names [String] which must be 'on'. E.g. ['location','scrollbars']
				keepRef: false,			// [Boolean]	Keep reference to popup window. If true a reference will be kept in $.data("ref") stored on the link
				className: "jsPopup",	// [String]		Class name set on popup link
				replaceLoc: false			// [Boolean]	Replace popup location in browser's history or not
			};
			
			// Do not change code below:
			if ( !props ) props = {};
			for ( var p in defProps ) if ( !props[p] ) props[p] = defProps[p];
			
			var propString = "";
			if ( !props.blank ) {
				if ( props.print && !window.print && $.inArray("toolbar", props.props) == -1 ) props.props.push("toolbar");
				
				function calcPos( prop, dim ) {
					if (window.screen && window.screen.availWidth) prop = window.screen["avail" + dim];
					return Math.round((prop - props[dim.toLowerCase()]) / 2);
				};
				if ( !props.absH ) props.popH = calcPos( props.popH, "Width" );
				if ( !props.absV ) props.popV = calcPos( props.popV, "Height" );
				
				propString = "width=" + props.width + ",height=" + props.height + ",left=" + props.popH + ",top=" + props.popV;
				if ( props.props.length > 0 ) propString = propString + "," + props.props.join(",");
			};
			
			return this
				.filter("a[href], area[href]")
				.each( function() {
					$(this)
						.data("popup", {
							target:	props.target,
							props:	propString,
							repl:		props.replaceLoc,
							keepRef:	props.keepRef
						} )
						.click( function(e) {
							var popProps = $(this).data("popup");
							var popup = window.open(this.href, popProps.target, popProps.props, popProps.repl);
							if ( popProps.keepRef ) $(this).data("ref", popup);
							e.preventDefault();;
						} )
						.addClass(props.className);
				} );
		}
	} );
} )(jQuery);
