project/static/jquery/jquery-dynamic-form.js
changeset 91 dd6426394a9a
equal deleted inserted replaced
90:587e9c025c73 91:dd6426394a9a
       
     1 /**
       
     2  * @author Stéphane Roucheray
       
     3  * @extends jQuery
       
     4  */
       
     5 
       
     6 jQuery.fn.dynamicForm = function (plusElmnt, minusElmnt, options){
       
     7 	var source = jQuery(this),
       
     8 	minus = jQuery(minusElmnt),
       
     9 	plus = jQuery(plusElmnt),
       
    10 	template = source.clone(true),
       
    11 	fieldId = 0,
       
    12 	formFields = "input, checkbox, select, textarea",
       
    13 	insertBefore = source.next(),
       
    14 	clones = [],
       
    15 	defaults = {
       
    16 		duration:1000
       
    17   	};
       
    18 	
       
    19   	// Extend default options with those provided
       
    20   	options = $.extend(defaults, options);
       
    21 	
       
    22 	isPlusDescendentOfTemplate = source.find("*").filter(function(){
       
    23 		return this == plus.get(0);
       
    24 	});
       
    25 	
       
    26 	isPlusDescendentOfTemplate = isPlusDescendentOfTemplate.length > 0 ? true : false;
       
    27 	
       
    28 	function normalizeElmnt(elmnt){
       
    29         elmnt.find(formFields).each(function(){
       
    30             var nameAttr = jQuery(this).attr("name"), 
       
    31 			idAttr = jQuery(this).attr("id");
       
    32 
       
    33             /* Normalize field name attributes */
       
    34             if (!nameAttr) {
       
    35 				jQuery(this).attr("name", "field" + fieldId + "[]");
       
    36 			}
       
    37 			
       
    38 			if (!/\[\]$/.exec(nameAttr)) {
       
    39 				jQuery(this).attr("name", nameAttr + "[]");
       
    40 			}
       
    41 			
       
    42             /* Normalize field id attributes */
       
    43             if (idAttr) {
       
    44 				/* Normalize attached label */
       
    45 				jQuery("label[for='"+idAttr+"']").each(function(){
       
    46 					jQuery(this).attr("for", idAttr + fieldId);
       
    47 				});
       
    48 				
       
    49                 jQuery(this).attr("id", idAttr + fieldId);
       
    50             }
       
    51             fieldId++;
       
    52         });
       
    53     };
       
    54 	
       
    55 	/* Hide minus element */
       
    56 	minus.hide();
       
    57 	
       
    58 	/* If plus element is within the template */
       
    59 	if (isPlusDescendentOfTemplate) {
       
    60 		function clickOnPlus(event){
       
    61 			var clone,
       
    62 			currentClone = clones[clones.length -1] || source;
       
    63 			event.preventDefault();
       
    64 			
       
    65 			/* On first add, normalize source */
       
    66 			if (clones.length == 0) {
       
    67 				normalizeElmnt(source);
       
    68 				currentClone.find(minusElmnt).hide();
       
    69 				currentClone.find(plusElmnt).hide();
       
    70 			}else{
       
    71 				currentClone.find(plusElmnt).hide();
       
    72 			}
       
    73 			
       
    74 			/* Clone template and normalize it */
       
    75 			clone = template.clone(true).insertAfter(clones[clones.length - 1] || source);
       
    76 			normalizeElmnt(clone);
       
    77 			
       
    78 			/* Normalize template id attribute */
       
    79 			if (clone.attr("id")) {
       
    80 				clone.attr("id", clone.attr("id") + clones.length);
       
    81 			}
       
    82 			
       
    83 			
       
    84 			plus = clone.find(plusElmnt);
       
    85 			minus = clone.find(minusElmnt);
       
    86 			
       
    87 			minus.get(0).removableClone = clone;
       
    88 			minus.click(clickOnMinus);
       
    89 			plus.click(clickOnPlus);
       
    90 			
       
    91 			if (options.limit && (options.limit - 2) > clones.length) {
       
    92 				plus.show();
       
    93 			}else{
       
    94 				plus.hide();
       
    95 			}
       
    96 			
       
    97 			clones.push(clone);
       
    98 		}
       
    99 		
       
   100 		function clickOnMinus(event){
       
   101 			event.preventDefault();
       
   102 			
       
   103 			if (this.removableClone.effect && options.removeColor) {
       
   104 				that = this;
       
   105 				this.removableClone.effect("highlight", {
       
   106 					color: options.removeColor
       
   107 				}, options.duration, function(){that.removableClone.remove();});
       
   108 			} else {
       
   109 			
       
   110 				this.removableClone.remove();
       
   111 			}
       
   112 			clones.splice(clones.indexOf(this.removableClone),1);
       
   113 			if (clones.length == 0){
       
   114 				source.find(plusElmnt).show();
       
   115 			}else{
       
   116 				clones[clones.length -1].find(plusElmnt).show();
       
   117 			}
       
   118 		}
       
   119 		
       
   120 		/* Handle click on plus */
       
   121 		plus.click(clickOnPlus);
       
   122 		
       
   123 		/* Handle click on minus */
       
   124 		minus.click(function(event){
       
   125 			
       
   126 		});
       
   127 		
       
   128 	}else{
       
   129 	/* If plus element is out of the template */
       
   130 		/* Handle click on plus */
       
   131 		plus.click(function(event){
       
   132 			var clone;
       
   133 			
       
   134 			event.preventDefault();
       
   135 			
       
   136 			/* On first add, normalize source */
       
   137 			if (clones.length == 0) {
       
   138 				normalizeElmnt(source);
       
   139 				jQuery(minusElmnt).show();
       
   140 			}
       
   141 			
       
   142 			/* Clone template and normalize it */
       
   143 			clone = template.clone(true).insertAfter(clones[clones.length - 1] || source);
       
   144 			if (clone.effect && options.createColor) {
       
   145 				clone.effect("highlight", {color:options.createColor}, options.duration);
       
   146 			}
       
   147 			normalizeElmnt(clone);
       
   148 			
       
   149 			/* Normalize template id attribute */
       
   150 			if (clone.attr("id")) {
       
   151 				clone.attr("id", clone.attr("id") + clones.length);
       
   152 			}
       
   153 			if (options.limit && (options.limit - 3) < clones.length) {
       
   154 				plus.hide();
       
   155 			}
       
   156 			clones.push(clone);
       
   157 		});
       
   158 		
       
   159 		/* Handle click on minus */
       
   160 		minus.click(function(event){
       
   161 			event.preventDefault();
       
   162 			var clone = clones.pop();
       
   163 			if (clones.length >= 0) {
       
   164 				if (clone.effect && options.removeColor) {
       
   165 					that = this;
       
   166 					clone.effect("highlight", {
       
   167 						color: options.removeColor, mode:"hide"
       
   168 					}, options.duration, function(){clone.remove();});
       
   169 				} else {
       
   170 					clone.remove();
       
   171 				}
       
   172 			}
       
   173 			if (clones.length == 0) {
       
   174 				jQuery(minusElmnt).hide();
       
   175 			}
       
   176 			plus.show();
       
   177 		});
       
   178 	}
       
   179 	
       
   180 };