Trevor D.
Trevor D.

Reputation: 33

Unable to append multiple videos

function selectVideo() {
        var x = document.getElementById("myFile");
        var txt = [];
        if ('files' in x) {
            if (x.files.length == 0) {
                txt = "Select one or more files.";
            } else {
                for (var i = 0; i < x.files.length; i++) {
                    var file = x.files[i];
                    if ('name' in file) {
                        txt[i] = file.name;
                    }
                }
            }
        }
        else {
            if (x.value == "") {
                txt += "Select one or more files.";
            } else {
                alert("The files property is not supported by your browser!");
                console.log("The path of the selected file: " + x.value);
            }
        }

        console.log(txt); 

        for (var j = 0; j < txt.length; j++) {
            $("#chooseVideos").append(" <div id=\"vid" + j + "\" class=\"embed-responsive embed-responsive-16by9\">");
            $("#vid" + j).append("<video width=\"320\" height=\"240\"> <source src=\"videos/" + txt[j] + "\" type=\"video/mp4\"></video>");
        }

    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="chooseVideos" class="container">
        <div id="choosevid">
            <input type="file" id="myFile" multiple onchange="selectVideo()" />
            <p id="demo"></p>
        </div>
 </div>

I am trying to append multiple videos when they are selected by the user. I have a input file loader that the user will select which videos to upload to the site. All of this is working fine, and I'm saving the video file names into an array named txt. The problem is when I'm testing with just two videos, it only appends the video at txt[1]. Here is my code:

for (var j = 0; j < txt.length; j++) {       
    $("#demo").append("<video width=\"320\" height=\"240\"> <source src=\"videos/" + txt[j] + "\" type=\"video/mp4\"></video>");
}

I even tried doing it using javascript instead of jquery like so:

for (var j = 0; j < txt.length; j++) {

      var video = document.createElement("video");
      video.src = "videos/" + txt[j];        

      document.getElementById("demo").appendChild(video);
}

I want it to be able to append both the video at txt[0] and at txt[1], but it seems to default to the last element in the array and only appends the one. What am I doing wrong?

For reference, here is the html where I am attempting to append them:

<div id="chooseVideos" class="container">
    <div id="choosevid" class="embed-responsive embed-responsive-16by9">
        <input type="file" id="myFile" multiple onchange="selectVideo()" />
        <p id="demo"></p>
    </div>
</div>

Upvotes: 1

Views: 195

Answers (2)

Patrick Roberts
Patrick Roberts

Reputation: 51886

Here's some code that uses various good practices to make code cleaner and more efficient.

For example, you don't have to check things like if a File contains a name, because it will always contain a name. Similarly, you'll almost never come across a browser now that doesn't support the input[type="file"].files, so it's relatively safe to assume that it will be there.

Feel free to post comments asking specific questions for clarification if anything below is unclear.

$(function () {
  var $demo = $('#demo');
  var $temp = $('#video').children();
  var media = $temp[0];
  var $plce = $('#placeholder').children();

  $('#myFile').change(function () {
    var input = this;
    var files = input.files;
    var file, type;
    
    $demo.empty().each(function () {
      var src = $(this).find('source').attr('src');
      
      if (src) URL.revokeObjectURL(src);
    });
    
    if (files.length > 0) {
      for (var i = 0; i < files.length; i++) {
        file = files[i];
        type = file.type;
        
        if (media.canPlayType(type)) {
          $temp
            .clone()
            .appendTo($demo)
            .find('source')
            .attr({ type: type, src: URL.createObjectURL(file)});
        } else {
          $plce
            .clone()
            .appendTo($demo)
            .find('pre')
            .text(type);
        }
      }
    } else {
      $demo.text("No files selected");
    }
  }).change();
});
.template {
  display: none;
}

#demo > * {
  background-color: #222222;
  color: #FFFFFF;
}

.placeholder {
  display: inline-block;
  box-sizing: padding-box;
  width: 320px;
  height: 240px;
  padding: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="template" id="video">
  <video width="320" height="240" controls>
    <source />
  </video>
</div>
<div class="template" id="placeholder">
  <div class="placeholder">
    <span>Cannot play video of type: <pre></pre></span>
  </div>
</div>
<div id="chooseVideos" class="container">
  <div id="choosevid" class="embed-responsive embed-responsive-16by9">
    <input id="myFile" type="file" accept="video/*" multiple />
    <p id="demo"></p>
  </div>
</div>

Upvotes: 1

Trevor D.
Trevor D.

Reputation: 33

I solved my own problem. The issue here is where I was trying to append the videos. I was trying to place both videos in the same <div> but I noticed it was in the class="embed-responsive embed-responsive-16by9. This was placing the videos on top of each other, as it only allowed one responsive <video> to be seen. In the javascript I made sure to create a new <div> for each video:

for (var j = 0; j < txt.length; j++) {
        $("#chooseVideos").append(" <div id=\"vid" + j + "\" class=\"embed-responsive embed-responsive-16by9\">");
        $("#vid" + j).append("<video width=\"320\" height=\"240\"> <source src=\"videos/" + txt[j] + "\" type=\"video/mp4\"></video>");
    }

Works exactly how I want it to now.

Upvotes: 0

Related Questions