/*
 * DragForm.js
 * DragForm was built to simply help me learn how to create some fun plugins for
 * jQuery (and to learn some of the new 1.4 methods).  DragForm is a plugin that allows you to
 * create a user interface with drag and drop form elements to let your users manage the optional
 * form components as they see fit.  It's a simple alternative to the 'Add' buttons that are
 * commonly found on existing web sites.
 *
 * @author		Adrian Scott
 * @created		March 7, 2010
 * @version		0.1
 * @req				jQuery 1.4+, jQueryUI 1.7.2+
 *
 * @updated		March 9, 2010 - Fixed issue where the name replacement was changing all tags rather
 *						than just those with names
 */
(function($) {
	var DragForm = function(element, options) {
		element = $(element);
		
		var settings = $.extend({
			class: 'df',
			max: null,
			uniqueID: false,
			uniqueName: false
		}, options);
		
		// provide a counter to know how many elements are in the form
		var currentTotal = 0;
		
		// set it to be draggable
		element.addClass(options.class).draggable({
			opacity: 0.75,
			helper: 'clone'
		});
		
		// public methods
		this.dropped = function(target) {
			if (settings.max == null || (currentTotal < settings.max)) {
				var currentElement = element.find('.df-content').clone().show().appendTo(target);
				currentElement.find('.remove').click(function() {
					$(this).closest('.df-content').remove();
					currentTotal--;
					checkTotal();
					return false;
				});
				
				if (settings.uniqueID || settings.uniqueName) {
					// create unique identifier
					var uid = 'df-' + (new Date()).getTime();
					
					// add a 'df' hidden input to the content box so that it can be parsed easier
					$('<input />', {
						name: 'df',
						type: 'hidden',
						val: uid
					}).prependTo(currentElement);
				}
				
				// if uniqueID property is true, modify the id values so they're unique
				if (settings.uniqueID) {
					// find all 'id' values and prepend the uid to them
					currentElement.find('[id]').each(function() {
						$(this).attr('id', uid + '-' + $(this).attr('id'));
					});
					
					// do the same with the 'for' attribute in labels
					currentElement.find('label[for]').each(function() {
						$(this).attr('for', uid + '-' + $(this).attr('for'));
					});
				}
				
				// if uniqueName property is true, modify the name values so they're unique
				if (settings.uniqueName) {
					// find all 'name' values and prepend the uid to them
					currentElement.find('[name][name!=df]').each(function() {
						$(this).attr('name', uid + '-' + $(this).attr('name'));
					});
				}

				currentTotal++;
				checkTotal();
			}
		};
		
		// private methods
		var checkTotal = function() {
			if (settings.max != null) {
				if (currentTotal >= settings.max) element.addClass('df-disabled').draggable('disable');
				else element.removeClass('df-disabled').draggable('enable');
			}
		};
	};
	
	$.fn.dragform = function(target, options) {
	
		var settings = $.extend({
			class: 'df'
		}, options || {});
	
		// set the target area to be droppable and to accept the class provided
		$(target).droppable({
			accept: '.' + settings.class,
			activeClass: 'df-active',
			drop: function(event, ui) {
				// call this object's drop method and pass in the target
				ui.draggable.data('dragform').dropped(target);
			}
		});
	
		return this.each(function() {
			var element = $(this);
			
			// if plugin already has instance, return
			if (element.data('dragform')) return;
			
			var dragform = new DragForm(this, settings);
			
			// store plugin in the element's data
			element.data('dragform', dragform);
		});					
	};

})(jQuery);
