views:

27

answers:

0

Hi, Im using the jQuery dynamic form plugin, but i need support for nested field duplication.

I would like some advice on how to modify the plugin to add such functionality. Im not a javascript/jQuery developer, so any advice on which route to take will be much appreciated.

I can provide the plugin's code:

/**
 * @author Stephane 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();
        });
    }

};