3

I'm trying to create an upload form. It's working well so far and i'm trying to sort out a couple of bugs that I dislike.

The line that I seem to be having trouble with is

$(element).find(">:first-child").attr("value", "");

When cloning the form, it clones the div and replaces the value with nothing leaving a blank form, this works well, if I were to delete that line I would get the previous form's value, so it would be nice for a blank form to show.

The issue i'm having is when you delete a form all the forms values delete, What I want is when you delete a form, leave the value alone for the other forms.

Here's a fiddle http://jsfiddle.net/d77pd/1/ or see code below

HTML

<button class="clone">Add an Image</button>
<div id="upload_image_sets">
    <div id="clonedInput1" class="clonedInput">
        <input type="text" id="upload_image_link_1" class="image" size="36" name="hero_options[upload_image_link_1]" value="' . $hero_options['upload_image_link_1'] . '" />
        <input id="show_upload_image_link_button_1" class="button upload_images" type="button" value="Upload Image" />
        <button class="remove">Remove</button>
    </div>
</div>

JavaScript

function updateClonedInput(index, element) {
    $(element).appendTo("#upload_image_sets").attr("id", "clonedInput" + index);
    $(element).find(">:first-child").attr("id", "cs_product_menu_img_src_" + index);
    $(element).find(">:first-child").attr("name", "hero_options[upload_image_link_" + index + "]");
    $(element).find(">:first-child").attr("value", "");
    $(element).find(">:first-child").next().attr("id", "cs_product_menu_img_src_" + index + "_button");
    displayRemove();
}

function displayRemove() {
    if ($('.clonedInput').length === 1) {
        $('.remove').hide();
    } else {
        $('.remove').show();
    }
}
displayRemove();

$(document).on("click", ".clone", function (e) {
    e.preventDefault();
    var cloneIndex = $(".clonedInput").length + 1;
    var new_Input = $(this).closest('.clonedInput').length ? $(this).closest('.clonedInput').clone() : $(".clonedInput:last").clone();
    updateClonedInput(cloneIndex, new_Input);
});
$(document).on("click", ".remove", function (e) {
    e.preventDefault();
    $(this).parents(".clonedInput").remove();
    $(".clonedInput").each(function (cloneIndex, clonedElement) {
        updateClonedInput(cloneIndex + 1, clonedElement);
    })
});

Clone the form a few times, if you delete any form apart form the 1st one with the content, you'll notice the first form's content deletes, I want this left alone.

andyb
  • 43,435
  • 12
  • 121
  • 150
Dan
  • 1,565
  • 3
  • 23
  • 43
  • Is there a specific requirement for incrementing `id` attributes on every clone? I only ask because the cloning, appending and clearing values could be performed with a lot less code. – andyb Feb 28 '14 at 12:13

2 Answers2

0

First approach: call $(element).find(">:first-child").attr("value", ""); after calling updateClonedInput(cloneIndex, new_Input); from add function.

Working Demo First approach:

Second Approach:

I have modified some code. pass one more bool argument in function updateClonedInput.which will be set true when added and set false when dom is removed.This will prevent the value getting replaced on remove function:

  function updateClonedInput(index, element,param) {
    $(element).appendTo("#upload_image_sets").attr("id", "clonedInput" +  index);
    $(element).find(">:first-child").attr("id", "cs_product_menu_img_src_" + index);
    $(element).find(">:first-child").attr("name", "hero_options[upload_image_link_" + index + "]");
if(param)
    $(element).find(">:first-child").attr("value", "");
    $(element).find(">:first-child").next().attr("id", "cs_product_menu_img_src_" + index + "_button");
    displayRemove();
}

function displayRemove() {
if($('.clonedInput').length === 1) {
    $('.remove').hide();
} else {
    $('.remove').show();
}
 }
 displayRemove();

$(document).on("click", ".clone", function(e){
    e.preventDefault();
    var cloneIndex = $(".clonedInput").length + 1;
    var new_Input = $(this).closest('.clonedInput').length ? $(this).closest('.clonedInput').clone() : $(".clonedInput:last").clone();
    updateClonedInput(cloneIndex, new_Input,true);    
});
$(document).on("click", ".remove", function(e){
    e.preventDefault();
    $(this).parents(".clonedInput").remove();
    $(".clonedInput").each( function (cloneIndex, clonedElement) {
        updateClonedInput(cloneIndex + 1, clonedElement,false);
    })
});

Working Demo Second Approach

Milind Anantwar
  • 81,290
  • 25
  • 94
  • 125
0

An alternate solution that creates a blank clone from the first element once, then uses this every time a new row is required. It also uses CSS to hide/show the Remove button based on the fact that you only need Remove buttons on all rows unless it's the only child.

Disclaimer: I have removed the id manipulation as I am unsure if you really need it. I can update if necessary.

Demo

HTML

<button class="clone">Add an Image</button>
<div id="upload_image_sets">
    <div class="clonedInput">
        <input type="text" class="image" size="36" name="hero_options[upload_image_link_1]" value="an initial value" />
        <input class="button upload_images" type="button" value="Upload Image" />
        <button class="remove">Remove</button>
    </div>
</div>

CSS

.clonedInput .remove {
    display:inline-block;
}

.clonedInput:only-child .remove {
    display:none;
}

JavaScript

function resetForm($form) {
    $form.find('input:text, input:password, input:file, select, textarea').val('');
    $form.find('input:radio, input:checkbox').removeAttr('checked').removeAttr('selected');
}

var $blankClone = $('.clonedInput').clone();
resetForm($blankClone);

$(document).on('click', '.clone', function(e) {
    e.preventDefault();
    $blankClone.clone().appendTo('#upload_image_sets');
});

$('#upload_image_sets').on('click', '.remove', function(e) {
    e.preventDefault();
    $(this).closest('.clonedInput').remove();
});

resetForm() borrowed from Resetting a multi-stage form with jQuery

Community
  • 1
  • 1
andyb
  • 43,435
  • 12
  • 121
  • 150