project/static/jquery/jquery-dynamic-form.js
changeset 91 dd6426394a9a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/static/jquery/jquery-dynamic-form.js	Thu Jan 14 21:06:43 2010 +0530
@@ -0,0 +1,180 @@
+/**
+ * @author Stéphane Roucheray
+ * @extends jQuery
+ */
+
+jQuery.fn.dynamicForm = function (plusElmnt, minusElmnt, options){
+	var source = jQuery(this),
+	minus = jQuery(minusElmnt),
+	plus = jQuery(plusElmnt),
+	template = source.clone(true),
+	fieldId = 0,
+	formFields = "input, checkbox, select, textarea",
+	insertBefore = source.next(),
+	clones = [],
+	defaults = {
+		duration:1000
+  	};
+	
+  	// Extend default options with those provided
+  	options = $.extend(defaults, options);
+	
+	isPlusDescendentOfTemplate = source.find("*").filter(function(){
+		return this == plus.get(0);
+	});
+	
+	isPlusDescendentOfTemplate = isPlusDescendentOfTemplate.length > 0 ? true : false;
+	
+	function normalizeElmnt(elmnt){
+        elmnt.find(formFields).each(function(){
+            var nameAttr = jQuery(this).attr("name"), 
+			idAttr = jQuery(this).attr("id");
+
+            /* Normalize field name attributes */
+            if (!nameAttr) {
+				jQuery(this).attr("name", "field" + fieldId + "[]");
+			}
+			
+			if (!/\[\]$/.exec(nameAttr)) {
+				jQuery(this).attr("name", nameAttr + "[]");
+			}
+			
+            /* Normalize field id attributes */
+            if (idAttr) {
+				/* Normalize attached label */
+				jQuery("label[for='"+idAttr+"']").each(function(){
+					jQuery(this).attr("for", idAttr + fieldId);
+				});
+				
+                jQuery(this).attr("id", idAttr + fieldId);
+            }
+            fieldId++;
+        });
+    };
+	
+	/* Hide minus element */
+	minus.hide();
+	
+	/* If plus element is within the template */
+	if (isPlusDescendentOfTemplate) {
+		function clickOnPlus(event){
+			var clone,
+			currentClone = clones[clones.length -1] || source;
+			event.preventDefault();
+			
+			/* On first add, normalize source */
+			if (clones.length == 0) {
+				normalizeElmnt(source);
+				currentClone.find(minusElmnt).hide();
+				currentClone.find(plusElmnt).hide();
+			}else{
+				currentClone.find(plusElmnt).hide();
+			}
+			
+			/* Clone template and normalize it */
+			clone = template.clone(true).insertAfter(clones[clones.length - 1] || source);
+			normalizeElmnt(clone);
+			
+			/* Normalize template id attribute */
+			if (clone.attr("id")) {
+				clone.attr("id", clone.attr("id") + clones.length);
+			}
+			
+			
+			plus = clone.find(plusElmnt);
+			minus = clone.find(minusElmnt);
+			
+			minus.get(0).removableClone = clone;
+			minus.click(clickOnMinus);
+			plus.click(clickOnPlus);
+			
+			if (options.limit && (options.limit - 2) > clones.length) {
+				plus.show();
+			}else{
+				plus.hide();
+			}
+			
+			clones.push(clone);
+		}
+		
+		function clickOnMinus(event){
+			event.preventDefault();
+			
+			if (this.removableClone.effect && options.removeColor) {
+				that = this;
+				this.removableClone.effect("highlight", {
+					color: options.removeColor
+				}, options.duration, function(){that.removableClone.remove();});
+			} else {
+			
+				this.removableClone.remove();
+			}
+			clones.splice(clones.indexOf(this.removableClone),1);
+			if (clones.length == 0){
+				source.find(plusElmnt).show();
+			}else{
+				clones[clones.length -1].find(plusElmnt).show();
+			}
+		}
+		
+		/* Handle click on plus */
+		plus.click(clickOnPlus);
+		
+		/* Handle click on minus */
+		minus.click(function(event){
+			
+		});
+		
+	}else{
+	/* If plus element is out of the template */
+		/* Handle click on plus */
+		plus.click(function(event){
+			var clone;
+			
+			event.preventDefault();
+			
+			/* On first add, normalize source */
+			if (clones.length == 0) {
+				normalizeElmnt(source);
+				jQuery(minusElmnt).show();
+			}
+			
+			/* Clone template and normalize it */
+			clone = template.clone(true).insertAfter(clones[clones.length - 1] || source);
+			if (clone.effect && options.createColor) {
+				clone.effect("highlight", {color:options.createColor}, options.duration);
+			}
+			normalizeElmnt(clone);
+			
+			/* Normalize template id attribute */
+			if (clone.attr("id")) {
+				clone.attr("id", clone.attr("id") + clones.length);
+			}
+			if (options.limit && (options.limit - 3) < clones.length) {
+				plus.hide();
+			}
+			clones.push(clone);
+		});
+		
+		/* Handle click on minus */
+		minus.click(function(event){
+			event.preventDefault();
+			var clone = clones.pop();
+			if (clones.length >= 0) {
+				if (clone.effect && options.removeColor) {
+					that = this;
+					clone.effect("highlight", {
+						color: options.removeColor, mode:"hide"
+					}, options.duration, function(){clone.remove();});
+				} else {
+					clone.remove();
+				}
+			}
+			if (clones.length == 0) {
+				jQuery(minusElmnt).hide();
+			}
+			plus.show();
+		});
+	}
+	
+};