Search code examples
jqueryhtmlformsclone

Clone form fields with jQuery and increment 'id' and 'for' attributes?


I'm looking at creating an RSVP form:

http://adrianandemma.com/

The form contains a guest name and a radio button for yes/no.

I have added an option to 'add further guest' which clones the name filed and the radio buttons, but they are keeping the same id's and for attributes, so the radio buttons in particular are getting messed up!

Is there a way than once I clone the name and radio fields I could also amend the id and for elements also?

Perhaps have the initial fields as id="guest1" and radios for="guest1-yes"/for="guest1-no" and then have these increment each time they are cloned?

Here's my code so far:

HTML:

<div class="form-row guest">
   <div class="field-l">
      <input type="text" name="name" id="name" required />
   </div>
   <div class="field-r">
      <input type="radio" name="coming" id="coming-yes" value="Yes" required><label for="coming-yes">Yes</label>
      <input type="radio" name="coming" id="coming-no" value="No"><label for="coming-no">No</label>
   </div>
</div>
<a class="addguest" href="#">Add further guest</a>

jQuery:

   $('.addguest').on('click', function(e) {
       e.preventDefault();
       $('.guest').first().clone().find("input").val('').end().insertBefore(this);
   });

and here's how it's laid out:

enter image description here

Any help would be great, as I've looked for similar questions, but can't get anything to work!


Solution

  • In order to increment the IDs and FORs of your input and label fields you can use:

    .attr( attributeName, function )

    In your css you need to change from:

    .field-r input[type="radio"]#coming-yes+label {
       cursor: url('/assets/images/happy.png'), pointer;    
    }
    .field-r input[type="radio"]#coming-no+label {
       cursor: url('/assets/images/sad.png'), pointer;  
    }
    

    To:

    .field-r input[type="radio"].coming-yesRadio+label {
        cursor: url('/assets/images/happy.png'), pointer;
    }
    .field-r input[type="radio"]..coming-noRadio+label {
        cursor: url('/assets/images/sad.png'), pointer;
    }
    

    Instead to address each element by id in your CSS you may use a class. That means to add the corresponding class to your input elements.

    The snippet:

    $('.addguest').on('click', function(e) {
        e.preventDefault();
        //
        // get the current number of ele and increment it
        //
        var i = $('.guest').length + 1;
        $('.guest').first().clone().find("input").attr('id', function(idx, attrVal) {
            return attrVal + i;  // change the id
        }).attr('name', function(idx, attrVal) {
            return attrVal + i;  // change the name
        }).val('').removeAttr('checked').end().find('label').attr('for', function(idx, attrVal) {
            return attrVal + i; // change the for
        }).end().insertBefore(this);
    });
    @font-face {
        font-family: 'dk_vermilionregular';
        src: url('http://adrianandemma.com/assets/fonts/dk_vermilion-webfont.woff2') format('woff2'),
        url('http://adrianandemma.com/assets/fonts/dk_vermilion-webfont.woff') format('woff');
        font-weight: normal;
        font-style: normal;
    }
    * {
        font-weight:normal;
        box-sizing:border-box;
        font-family:'dk_vermilionregular', arial, sans-serif;
    }
    body {
        font-family:'dk_vermilionregular', arial, sans-serif;
        color:#363e3f;
        line-height: 1.2;
    }
    .box {
        text-align:center;
        max-width: 60%;
        margin:0 auto;
    }
    h1 {
        font-size:86px;
        margin:0.5em 0;
    }
    h1 span {
        display:block;
        font-size: 40px;
    }
    h2 {
        font-size:68px;
        margin:0.5em 0;
    }
    p {
        font-size: 40px;
        margin:0.5em 0;
    }
    a {
        color: #363e3f;
    }
    
    a.btn {
        display: inline-block;
        font-size:24px;
        color:#363e3f;
        text-decoration: none;
        padding:12px 20px 8px;
        border:1px solid #363e3f;
        margin: 20px 0 0;
    }
    
    /*** Images ***/
    img {
        max-width:100%;
    }
    img.ae {
        width:260px;
    }
    img.ceremony {
        width:300px;
        margin:0 0 20px;
    }
    
    /*** Forms ***/
    #rsvp {
        z-index: 110;
        display: table;
        table-layout: fixed;
        position: fixed;
        width:100%;
        height: 100%;
        top: 0px;
        bottom: 0px;
        left: 0px;
        right: 0px;
        background: rgba(255,255,255,1);
    }
    
    .form-container {
        display: table-cell;
        vertical-align: middle;
    }
    
    form {
        width: 600px;
        max-width: 60%;
        margin:0 auto;
    }
    
    form p {
        font-size:24px;
        margin: 0;
    }
    
    .form-row {
        overflow: auto;
        margin:0 0 10px;
    }
    
    .field-l {
        float:left;
        width: 70%;
        padding-right: 20px;
    }
    
    .field-r {
        float:right;
        width: 30%;
        text-align: right;
        cursor: default;
    }
    
    .field-l input {
        display:block;
        width: 100%;
        height: 40px;
        vertical-align: middle;
        padding: 0 10px;
        box-shadow: none;
        border:1px solid #363e3f;
    }
    
    .field-r label {
        font-size:20px;
        height: 40px;
        line-height: 40px;
        display: inline-block;
        padding: 0 10px;
        border: 1px solid #ddd;
        width: 40%;
        margin:0 0 0 5px;
        text-align: center;
    }
    
    .field-r input[type="radio"]:checked+label {
        border: 1px solid #363e3f;
    }
    
    .field-r input[type="radio"].coming-yesRadio+label {
        cursor: url('http://adrianandemma.com/assets/images/happy.png'), pointer;
    }
    .field-r input[type="radio"].coming-nosRadio+label {
        cursor: url('http://adrianandemma.com/assets/images/sad.png'), pointer;
    }
    
    .field-r input {
        width: 0;
        margin: 0;
        visibility: hidden;
        cursor: default;
    }
    
    form button {
        display: block;
        width:100%;
        border:1px solid #363e3f;
        background: #fff;
        margin:30px 0 0;
        font-size: 24px;
        padding: 10px 0 7px;
        cursor: pointer;
    }
    
    form button:hover {
        background: #fcfcfc;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    
    <div class="form-row guest">
        <div class="field-l">
            <input type="text" name="name" id="name" required />
        </div>
        <div class="field-r">
            <input type="radio" name="coming" class="coming-yesRadio" id="coming-yes" value="Yes" required><label for="coming-yes">Yes</label>
            <input type="radio" name="coming" class="coming-yesRadio" id="coming-no" value="No"><label for="coming-no">No</label>
        </div>
    </div>
    <a class="addguest" href="#">Add further guest</a>