john
john

Reputation: 1273

how to find closest next img tag with jquery

I have a couple of these html blocks in a foreach loop:

<label class="">Replace video:</label>              
<input type="file" name="replaced_main_video" class="input-video-preview" />                                            
            
<!-- replaced main video -->            
<video class="video" controls>
    <source type="video/mp4">
</video>
<canvas></canvas>               
<label class="">Preview replaced video:</label><br />
<img class="video-preview" width="100" src="#" />

For showing a preview from the chosen video that is uploaded, is use this js code:

$(function() {
    var video = $('.video');
    var thumbnail = $('canvas');
    var input_video_preview = $('.input-video-preview');
    var ctx = thumbnail.get(0).getContext("2d");
    var duration = 0;
    var img = $('.video-preview');

    input_video_preview.on('change', function(e) {
        var file = e.target.files[0];
        // Set video source
        video.find('source').attr('src', URL.createObjectURL(file));
        // Load the video
        video.get(0).load();
        // Load metadata of the video to get video duration and dimensions
        video.on('loadedmetadata', function(e) {
            duration = video.get(0).duration;
            // Set canvas dimensions same as video dimensions
            thumbnail[0].width = video[0].videoWidth;
            thumbnail[0].height = video[0].videoHeight;
            // Set video current time to get some random image
            video[0].currentTime = Math.ceil(duration / 2);
            // Draw the base-64 encoded image data when the time updates
            video.one("timeupdate", function() {
                ctx.drawImage(video[0], 0, 0, video[0].videoWidth, video[0].videoHeight);
                
                //$('.video-preview').attr("src", thumbnail[0].toDataURL());// THIS WORKS, but all imgs get src
                $('.input-video-preview').next('.video-preview').attr("src", thumbnail[0].toDataURL()); // bind to the next img with class 'video-preview'
            });
        });
    });
});

This works fine, but because the html blocks are repeated by a foreach, every img gets the source. and i want only the next img tag after the input type="file"

I tried to achieve this with this line below in the function:

$('.input-video-preview').next('.video-preview').attr("src", thumbnail[0].toDataURL()); // get input with class 'input-video-preview', take the next img with class '.video-preview' and bind it to the `src` attribute

But unfortunatley, this does not work.... How can i achieve this?

Fiddle

Upvotes: 1

Views: 141

Answers (1)

francisco neto
francisco neto

Reputation: 807

To reference the specific input, usually we use $(this) inside the function:

$(this).next('.video-preview')

instead of

$('.input-video-preview').next('.video-preview')

Edit

As you have many nested calls to on(), the command $(this) may change context and not target the <input> component. So you may need to do something like this:

input_video_preview.on('change', function(e) {
  var selectedInput = $(this);

   //...


  //...


  selectedInput.nextAll('.video-preview').eq( 0 ).attr("src", thumbnail[0].toDataURL());

});

Edit 2

Besides the topic of your question, there are other aspects of your code that may prevent it from working.

You should not before hand define the video, thumbnail and img vars. This vars depend on the input that was choosen.

So you should define than inside the on() using the nextAll() as well, like that:

$(function() {
  var input_video_preview = $('.input-video-preview');
  var duration = 0;

  input_video_preview.on('change', function(e) {
      var selectedInput = $(this);
    
      var video = selectedInput.nextAll('.video');
      var thumbnail = selectedInput.nextAll('canvas');
      var ctx = thumbnail.get(0).getContext("2d");
      var img = selectedInput.nextAll('.video-preview');
      var file = e.target.files[0];

    //...


  });
})

Upvotes: 2

Related Questions