1

So I have this code but I tought it was too repetitive, anyone has an idea how I could do that? When a upload a new image, I want a new image box to show up. My solution works, but what if I would like to have 1000 new images? I can't just type one at the time. What could I do to optimise this problem?

HTML:

<div class="wrapper">
    <div class="box box_image" id="box_image_1">
        <div class="js--image-preview"></div>
        <div class="upload-options">
            <label>
                <input type="file" class="image-upload" id="image1" data-show='box_image_2' name="IgniteFormObject.Image1" accept="image/*" enctype="multipart/form-data" />
            </label>
        </div>
    </div>
    <div class="box box_image" id="box_image_2">
        <div class="js--image-preview"></div>
        <div class="upload-options">
            <label>
                <input type="file" class="image-upload" id="image2" data-show='box_image_3' name="IgniteFormObject.Image2" accept="image/*" enctype="multipart/form-data" />
            </label>
        </div>
    </div>
    <div class="box box_image" id="box_image_3">
        <div class="js--image-preview"></div>
        <div class="upload-options">
            <label>
                <input type="file" class="image-upload" id="image3" data-show='box_image_4' name="IgniteFormObject.Image3" accept="image/*" enctype="multipart/form-data" />
            </label>
        </div>
    </div>
    <div class="box box_image" id="box_image_4">
        <div class="js--image-preview"></div>
        <div class="upload-options">
            <label>
                <input type="file" class="image-upload" id="image4" data-show='box_image_5' name="IgniteFormObject.Image4" accept="image/*" enctype="multipart/form-data" />
            </label>
        </div>
    </div>
    <div class="box box_image" id="box_image_5">
        <div class="js--image-preview"></div>
        <div class="upload-options">
            <label>
                <input type="file" class="image-upload" id="image5" name="IgniteFormObject.Image5" accept="image/*" enctype="multipart/form-data" />
            </label>
        </div>
    </div>
</div>

Javascript:

When an image is uploaded, this JQuery is called.

$('#image1').change(function (ev) {
    $("#box_image_2").show();
});

$('#image2').change(function (ev) {
    $("#box_image_3").show();
});

$('#image3').change(function (ev) {
    $("#box_image_4").show();
});

$('#image4').change(function (ev) {
    $("#box_image_5").show();
});
3
  • show your markup structure. Seems weird to me you have image1 > box2 Commented Mar 8, 2019 at 20:46
  • can you post the entire code? with html i am actually trying to picture out how the change being triggered Commented Mar 8, 2019 at 20:47
  • Yes, you can create loops with counters and all that but I think there is a smarter way using selectors, depending on your markup. Commented Mar 8, 2019 at 20:49

5 Answers 5

3

You can use data attribute and multiple selector. In the data attribute pass the id of the element which you want to show & on change get that attribute

$('#image1,#image2,#image3,#image4').on('change', function(ev) {
  let toShow = $(this).data('show');
  console.log(toShow);
  // $('#'+toShow).show();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id='image1' type='checkbox' data-show='box_image_2'>
<input id='image2' type='checkbox' data-show='box_image_3'>
<input id='image3' type='checkbox' data-show='box_image_4'>
<input id='image4' type='checkbox' data-show='box_image_5'>

You can also use wildcard selector where id begins with image

$('input[id^="image"]').on('change', function(ev) {
  let toShow = $(this).data('show');
  console.log(toShow);
  // $('#'+toShow).show();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id='image1' type='checkbox' data-show='box_image_2'>
<input id='image2' type='checkbox' data-show='box_image_3'>
<input id='image3' type='checkbox' data-show='box_image_4'>
<input id='image4' type='checkbox' data-show='box_image_5'>

Sign up to request clarification or add additional context in comments.

4 Comments

It works! But what if I had one hundred images? $('#image1,#image2,#image3 ... #image100').on('change', function(ev) {
In that case use common class and in jquery use class selector
And how I would do it with IDs?
id is always unique. You can use wild card selector. Updated answer
1

You can simply use classes like this:

$('.image').change(function (ev) {
    $(this).next(".box_image").show();
});

Comments

1

You can try this method using for loop.

  • Create a for loop
  • Inside the loop set change function to image${i}.
  • And inside the change function call show() on box_image_${i+1}

I also used Template Literals in my code

for(let i = 1;i<=4;i++){
   $(`#image${i}`).change(function (ev) {
      $(`#box_image_${i+1}`).show();
   })
}

2 Comments

that is some nice ecma :) lurve it!
@brk No we don't need iife it will work fine without it. Thanks for information
0

Stick it in a loop?

for(var i = 1; i <= 4; i++){
    $('#image'+i).change(function (ev) {
        $("#box_image_"+(i+1)).show();
    });

}

2 Comments

You might need parseInt() to get the addition to work.
you are missing a ) - $("#box_image_" + (i + 1)).show();
0

Strictly based on your markup and how you had unique ids for each elements...

The key is to retreive that id from the parent container and increment by one to show the next.

// Hide all containers except the first, on load (possibly already achieved via CSS)
$("[id^='box_image_']").not(":first").hide();

// Change handler
$("[id^='image']").change(function(ev) {

  // Retreive the index part of the container's id
  var parent_box_image_id = $(this).closest("[id^='box_image_']").attr("id").split("box_image_")[1];
  console.log(parent_box_image_id);
  
  // Increment by one
  parent_box_image_id++;

  // Show the next one!
  $("#box_image_"+parent_box_image_id).show();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="wrapper">
  <div class="box box_image" id="box_image_1">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
          <input type="file" class="image-upload" id="image1" data-show='box_image_2' name="IgniteFormObject.Image1" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" id="box_image_2">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" id="image2" data-show='box_image_3' name="IgniteFormObject.Image2" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" id="box_image_3">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" id="image3" data-show='box_image_4' name="IgniteFormObject.Image3" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" id="box_image_4">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" id="image4" data-show='box_image_5' name="IgniteFormObject.Image4" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" id="box_image_5">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" id="image5" name="IgniteFormObject.Image5" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
</div>


But there could be another way to do the same more efficiently... Like squarely forgetting about the ids and use classes... Have a look at this other snippet below. ;)

// Hide all containers except the first, on load (possibly already achieved via CSS)
$(".box_image").not(":first").hide();

// Change handler
$(".image-upload").change(function(ev) {
  $(this).closest(".box_image").next().show();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="wrapper">
  <div class="box box_image" class="box_image">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
          <input type="file" class="image-upload" name="IgniteFormObject[]" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" class="box_image">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" name="IgniteFormObject[]" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" class="box_image">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" name="IgniteFormObject[]" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" class="box_image">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" name="IgniteFormObject[]" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" class="box_image">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" name="IgniteFormObject[]" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.