Mathias Schnell
Mathias Schnell

Reputation: 902

How would I duplicate form elements AND the data inside them with jQuery?

See this form - http://schnell.dreamhosters.com/form.php

This form has a portion of it where you enter data and can choose to add more of the same data by clicking a button called 'Add A Site' and it will make another of that section to enter another site. This is the jQuery that performs the duplication...

$(function ()   {
    var sites = 1;
    var siteform = $("#site1").html();

    $(".addsites").live("click", function(e) {
        e.preventDefault();
        sites++;
        $("#events").append("<div id='site" + sites + "'>"
            + "<br /><hr><br />"
            + siteform
            + "<center><button class='removesites' title='site"
            + sites + "'>Remove This Site</button><br />"
            + "<button class='addsites'>Add Another Site</button>"
            + "</center></div>");           
    });

    $(".removesites").live("click", function(e) {
        e.preventDefault();
        var id = $(this).attr("title");
        $("#" + id).remove();
    });     
});

The duplication works perfectly, but one thing that's bugging me is that when I have to enter data for someone claiming a LOT of sites, it gets very annoying having to repeat same or similar parts of this section of the form (like every site is in the same city, on the same day, by the same person, etc.) So I had the idea that with each duplication, the values of the form elements would also carry over and I just edit what's not the same. The current implementation only duplicates the elements, not the data. I'm not sure how to easily copy the data into new sections, and I can't find any jQuery tools to do that.

PS - This part isn't as important, but I've also considered using this same form to load the data back in for viewing/editing, etc. The only problem with this is that the reprinting of the form means that there will be a form section with the id "Site7" or something, but jQuery starts its numbering at 1, always. I've thought about using selectors to find the highest number site and start off the variable 'sites' at that number, but I'm not sure how. Any advice how to do this, or a better system overall, would be much appreciated.

Upvotes: 1

Views: 605

Answers (5)

Donny van V
Donny van V

Reputation: 961

Dont forget to create a function for registering the event! Its very important because when the DOM is loaded, all new attributes need to be registrated to the DOM.

Small example:

<script>
    $(document).ready(function(){
        $('#click-me').click(function(){
            registerClickEvent();
        })

        function registerClickEvent(){
            $('<input type="text" name="input_field_example[]">').appendTo('#the-div-you-want')
        }

        registerClickEvent();
    })
</script>

Upvotes: 0

Mathias Schnell
Mathias Schnell

Reputation: 902

Ok I finally figured this out. It's, more or less, an expansion on Alex Pakka's answer.

        sites++;
        $("#events").append("<div id='site" + sites + "'>"
            + "<hr><br />"
            + siteform
            + "<center><button class='removesites' title='site"
            + sites + "'>Remove This Site</button><br />");
        $("#site1").find("input:checked, input:text, textarea, select").each(function() {
            var name = $(this).attr("name");
            var val = $(this).val();
            var checked = $(this).attr("checked");
            var selected = $(this).attr("selectedIndex");

            $('#site' + sites + ' [name="'+name+'"]').val(val);
            $('#site' + sites + ' [name="'+name+'"]').attr("checked", checked);
            $('#site' + sites + ' [name="'+name+'"]').attr("selectedIndex", selected);
        });

I used extra vars for readability sake, but it should do just as fine if you didn't and used the methods directly.

Upvotes: 0

Flambino
Flambino

Reputation: 18773

You could consider using cloneNode to truely clone the previous site-div and (by passing true to cloneNode) all of its descendants and their attributes. Just know that the clone will have the same id as the original, so you'll have to manually set its id afterwards

Try this in your click-function

var clone = $("#site" + sites).clone(true, true); // clone the last div
sites++; // increment the number of divs
clone.attr('id', "site" + sites); // give the clone a unique id
$("#events").append(clone); // append it to the container

As Scuzzy points out in a comment jQuery does have its own clone() method (I don't use jQuery much, so I didn't know, and I didn't bother to check before answering). Probably better to use jQuery's method than the built-in cloneNode DOM method, since you're already using jQuery for event listeners. I've updated the code

Upvotes: 1

Alex Pakka
Alex Pakka

Reputation: 9706

The query to transfer values is quite simple (please, check the selector for all the right types on the form):

$("#site1").find("input[checked], input:text, input:hidden, input:password, input:submit, option:selected, textarea")
            //.filter(":disabled")
            .each(function()
{
   $('#site2 [name="'+this.name+'"]').val(this.value);
}

Upvotes: 0

sg3s
sg3s

Reputation: 9567

You want to itterate over the input fields in siteform and store them in an object using their name attribute as a key.

Then after the duplication of the object you made and look for the equivelant fields in the new duplicated form ans set their values.

Somthing like this (not tested, just the idea)

var obj = new Object();

$("#site1 input").each(function(){
    obj[this.id] = this.value;
);

// Dupicate form

$.each(obj, function(key, value){
    $('#newform input[name="'+key+'"]').value = value;
});

Mind you these two each() functions differ from each other.

http://api.jquery.com/jQuery.each/ http://api.jquery.com/each/

Upvotes: 1

Related Questions