Validating jQuery image for dynamically cloned form

I have a form in my HTML that will be cloned and added dynamically when the user clicks the #addOne button. The form is successfully checked for input errors, the only problem that I am now facing is that it does not work correctly for images. Let's say I upload an image for the first form, it works fine. But when I click the #addOne button and load the image for the second form, this is when problems arise. Before loading the image for the second form, it already displays the image from the previous form on the page. Uploading an image for this form will not update form 2. Rather, it will change the displayed image of form 1. How can I make it so that each form displays its own uploaded image and is validated correctly? Here my jsFiddle

HTML

<div class="article_properties">

  <form class="article_properties_form" action="" method="POST" enctype="multipart/form-data">
    <p style="display: inline">Page Number</p>
    <div style="background-color: #FF355E; padding: 5px; display: inline; margin-left: 5px">

      <p style="display: inline" class="pageNumber"></p>
    </div>
    <textarea style="display: none" class="inputNumber" name="pages"></textarea>
    <p>Image</p>
    <input style="padding: 0px" type="file" name="image" class="pageImg">
    <div class="imgContainer">
    </div>
    <p>Subtitle</p>
    <input type="text" name="subtitle">

    <p>Text</p>
    <textarea name="text" rows="4"></textarea>
    <input id="properties_btn" type="submit" value="Submit/Update" name="properties_submit">
    <hr style="border: 1px dotted lightgray; margin-bottom: 50px">
  </form>


  <a style="display: none; text-align: center; margin: 50px; font-size: 25px" class="expand" href="#">

  </a>
</div>
<!--End of article properties div-->
<div id="addOne">
  <p>+Add page</p>
</div>

<div class="nextBtn" style="display: none">
  <p>Finalize my article</p>
</div>

JQuery

var numPagesTemp = 4;
$('.pageNumber:last').text(numPagesTemp);
$('.inputNumber:last').text(numPagesTemp);
//Invoke functions for first form
add_validation_for_forms();
add_image_construction();

//Form validation
function add_validation_for_forms() {
  $(".article_properties_form").each(function() {
    $(this).validate({
      errorElement: 'div',

      rules: {
        image: {
          required: true,
          extension: "jpg|jpeg|png",
          minImageSize: {
            width: 600,
            height: 400
          }
        },

        subtitle: {
          required: true,
          minlength: 2,
          maxlength: 25
        },
        text: {
          required: true,
          minlength: 35,
          maxlength: 275
        }
      },

      messages: {
        image: {
          required: "This page needs an image",
          extension: "You're only allowed to upload jpg or png images."
        },

        subtitle: {
          required: "You have to provide a subtitle for this page!",
          minlength: "Your subtitle must be at least 2 characters long",
          maxlength: "Your subtitle must be less than 25 characters long"
        },
        text: {
          required: "Please enter text for this page",
          minlength: "Your text must be at least 35 characters long",
          maxlength: "Your text must be less than 275 characters long"
        },
      },
    });
  });
}
//Adding a form
$('#addOne').click(function() {

  numPagesTemp--;

  var articlePropsTemplate = $('.article_properties_form:last').clone();
  articlePropsTemplate.show();
  $('.article_properties').append(articlePropsTemplate);

  var articlePropsExpand = $('.expand:last').clone();
  articlePropsExpand.text("Expand " + numPagesTemp);
  articlePropsExpand.hide();

  $('.article_properties').append(articlePropsExpand);

  $('.pageNumber:last').text(numPagesTemp);
  $('.inputNumber:last').text(numPagesTemp);
  articlePropsTemplate[0].reset();
  add_validation_for_forms();

  add_image_construction();
  articlePropsTemplate.validate().resetForm();

  if (numPagesTemp == 1) {
    $('#addOne').hide();
    $(".nextBtn").show();
  }

});

//Adding Method
$.validator.addMethod('minImageSize', function(value, element, minSize) {
  var imageSize = $(element).data('imageSize');
  return (imageSize) && (imageSize.width >= minSize.width) && (imageSize.height >= minSize.height);
}, function(minSize, element) {
  return ($(element).data('imageSize')) ? ("Your image size must be at least " + minSize.width + "px by " + minSize.height + "px") : "Selected file is not an image.";
});

//Image Uploading
var $properties_btn = $('properties_btn'),
  $imgContainer = $('.imgContainer'),
  $pageImg = $('.pageImg');

function add_image_construction() {

  $('.pageImg').change(function() {
    $pageImg.removeData('imageSize');
    $imgContainer.hide().empty();

    var file = this.files[0];

    if (file.type.match(/image\/.*/)) {
      $properties_btn.attr('disabled', true);

      var reader = new FileReader();

      reader.onload = function() {
        var $img = $('<img />').attr({
          src: reader.result
        });

        $img.on('load', function() {
          $imgContainer.append($img).show();

          $pageImg.data('imageSize', {
            width: $img.width(),
            height: $img.height()
          });

          $img.css({
            width: '400px',
            height: '200px'
          });

          $properties_btn.attr('disabled', false);

          validator.element($pageImg);
        });
      }

      reader.readAsDataURL(file);
    } else {
      validator.element($pageImg);
    }
  });
}
0
2

:

, .

, JavaScript, .

:

(1) , , .

var $CLONED_FORM = $('.article_properties_form:first').clone();

(2) , , .

function initializeForm($form, pageNum) {
  // Set up form validation here.
  // Also attach the change-event handler for the file input here.
}

(3) , .

$('.article_properties_form').each(function() {
  initializeForm($(this), numPagesTemp--);
});

(4) , .

$('#addOne').click(function() {
  var $newForm = $CLONED_FORM.clone().appendTo('.article_properties').show();

  initializeForm($newForm, numPagesTemp--);

  if (numPagesTemp == 0) {
    $('#addOne').hide();
    $(".nextBtn").show();
  }
});

jsfiddle


validator.

var validator = $form.validate({

, id. id , , , , .

+1

,

class="properties_btn" id="properties_btn", document id; validator change.

$(function() {
  var numPagesTemp = 4;
  $('.pageNumber:last').text(numPagesTemp);
  $('.inputNumber:last').text(numPagesTemp);
  //Invoke functions for first form
  add_validation_for_forms();
  add_image_construction();

  //Form validation
  function add_validation_for_forms() {
      $(".article_properties_form").each(function() {
        $(this).validate({
          errorElement: 'div',

          rules: {
            image: {
              required: true,
              extension: "jpg|jpeg|png",
              minImageSize: {
                width: 600,
                height: 400
              }
            },

            subtitle: {
              required: true,
              minlength: 2,
              maxlength: 25
            },
            text: {
              required: true,
              minlength: 35,
              maxlength: 275
            }
          },

          messages: {
            image: {
              required: "This page needs an image",
              extension: "You're only allowed to upload jpg or png images."
            },

            subtitle: {
              required: "You have to provide a subtitle for this page!",
              minlength: "Your subtitle must be at least 2 characters long",
              maxlength: "Your subtitle must be less than 25 characters long"
            },
            text: {
              required: "Please enter text for this page",
              minlength: "Your text must be at least 35 characters long",
              maxlength: "Your text must be less than 275 characters long"
            },
          },
        });
      });
    }
    //Adding a form
  $('#addOne').click(function() {

    numPagesTemp--;

    var articlePropsTemplate = $('.article_properties_form:last')
      .clone();
    articlePropsTemplate.find("img").remove();
    $('.article_properties').append(articlePropsTemplate);

    var articlePropsExpand = $('.expand:last').clone();
    articlePropsExpand.text("Expand " + numPagesTemp);
    articlePropsExpand.hide();


    $('.article_properties').append(articlePropsExpand);

    $('.pageNumber:last').text(numPagesTemp);
    $('.inputNumber:last').text(numPagesTemp);
    $("form:last")[0].reset();
    add_validation_for_forms();

    // add_image_construction();
    articlePropsTemplate.validate().resetForm();

    if (numPagesTemp == 1) {
      $('#addOne').hide();
      $(".nextBtn").show();
    }
    

  });

  //Adding Method
  $.validator.addMethod('minImageSize', function(value, element, minSize) {
    var imageSize = $(element).data('imageSize');
    return (imageSize) && (imageSize.width >= minSize.width) && (imageSize.height >= minSize.height);
  }, function(minSize, element) {
    return ($(element).data('imageSize')) ? ("Your image size must be at least " + minSize.width + "px by " + minSize.height + "px") : "Selected file is not an image.";
  });

  //Image Uploading
  //  var $properties_btn = $('.properties_btn'),
  //  $imgContainer = $('.imgContainer'),
  //  $pageImg = $('.pageImg');

  function add_image_construction() {

    $(document).on("change", ".pageImg", function(e) {
      var form = $(this).closest("form");
      var validator = form.validate();
      $(this).removeData('imageSize');
      form.find('.imgContainer').hide().empty();

      var file = this.files[0];

      if (file.type.match(/image\/.*/)) {
        form.find('.properties_btn').attr('disabled', true);

        var reader = new FileReader();

        reader.onload = function() {
          var $img = $('<img />').attr({
            src: reader.result
          });

          $img.on('load', function() {
            form.find('.imgContainer').append($img).show();

            $(e.target).data('imageSize', {
              width: $img.width(),
              height: $img.height()
            });

            $img.css({
              width: '400px',
              height: '200px'
            });

            form.find('.properties_btn').attr('disabled', false);

            validator.element(e.target);
          });
        }

        
        reader.readAsDataURL(file);
      } else {
        validator.element(e.target);
      }
      
    });
  }
  
})
form {
  border: 1px solid blue;
  padding: 10px;
  margin: 10px;
}
<script src="https://code.jquery.com/jquery-3.0.0.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.15.0/jquery.validate.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.15.0/additional-methods.min.js"></script>
<div class="article_properties">

  <form class="article_properties_form" action="" method="POST" enctype="multipart/form-data">
    <p style="display: inline">Page Number</p>
    <div style="background-color: #FF355E; padding: 5px; display: inline; margin-left: 5px">

      <p style="display: inline" class="pageNumber"></p>
    </div>
    <textarea style="display: none" class="inputNumber" name="pages"></textarea>
    <p>Image</p>
    <input style="padding: 0px" type="file" name="image" class="pageImg">
    <div class="imgContainer">
    </div>
    <p>Subtitle</p>
    <input type="text" name="subtitle">

    <p>Text</p>
    <textarea name="text" rows="4"></textarea>
    <input class="properties_btn" type="submit" value="Submit/Update" name="properties_submit">
    <hr style="border: 1px dotted lightgray; margin-bottom: 50px">
  </form>


  <a style="display: none; text-align: center; margin: 50px; font-size: 25px" class="expand" href="#">

  </a>
</div>
<!--End of article properties div-->
<div id="addOne">
  <p>+Add page</p>
</div>

<div class="nextBtn" style="display: none">
  <p>Finalize my article</p>
</div>
Hide result

, ,

// maximum number of `form` elements which `document` should contain
var n = 4;
// display `form` index
function handleLabel() {
  $("label").html(function(index, html) {
    return "form #" + index 
  })
}

handleLabel();

function processFile() {
  // preview uploaded image
  $("<img>", {src: URL.createObjectURL(this.files[0])})
  .insertAfter(this.nextElementSibling).after("<br>");
  
}
// handle file upload; delegate event to `document`
$(document).on("change", ":file", processFile);
// append cloned `form` to page
$("button").on("click", function() {
  // if less than `n` forms
  if ($("form").length < 4) {
  // copy last `form` `.outerHTML` instead of using `.clone()`
  $($("form:last")[0].outerHTML)
    // remove `img` from `html`
    .find("img").remove().end()
    .insertAfter("form:last");
    // update `form` `label` elements
    handleLabel();
  } else {
    // detach `click` event from `button`
    // when four `form` elements exist in `document`
    $(this).off("click")
  }
});
// handle `form` submit event
$(document).on("submit", "form", function(e) {
  var img = $(this).find("img")[0];
  // check `img` `width`, `height`
  if (img.naturalWidth < 600 
    || img.naturalHeight < 400) {
      e.preventDefault();
      this.reset();
      alert("invalid img width or height")
    }
})
form {
  border: 1px solid blue;
  padding: 10px;
  margin: 10px;
}
<script src="https://code.jquery.com/jquery-3.0.0.js"></script>
<form>
  <fieldset>
    <label></label><br>
    <input name="file" type="file" accept=".jpg,.jpeg,.png" required />
    <br>
    <input type="submit" />
  </fieldset>
</form>
<button>
  add form
</button>
Hide result

jsfiddle https://jsfiddle.net/hLjvffpv/5/

0

Source: https://habr.com/ru/post/1648073/


All Articles