0

Im working on a video selection using JS, and I came across this answer which helped me out. The problem is

  1. The answer is nearly 7 years old
  2. Im only able to test on chrome, but I get an error saying Uncaught TypeError: video.appendChild is not a function This is the snippet of js/html of where the error is coming from.

var video = document.getElementsByClassName("player");
var source = document.createElement("source");

source.setAttribute("src", "../shows/2020.mp4");


video.appendChild(source);
video.play();

$(document).on("change", "vid-select", function() {
  var show = $("option:selected", this).data("show")
  source.setAttribute("src", "../shows/" + show + ".mp4")
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="past-player">
  <select class="vid-select" data-target= ".past-player .player">
    <option data-show: "2020">2020</option>
    <option>1</option>
    <option>2</option>
    <option>3</option>
    <option>4</option>
    <option>5</option>
    <option>6</option>
    <option>7</option>
  </select>
  <video class="player"></video>
</div>

I just want to know what is going wrong with the video var and why it cant have a child added to it to show the video.

I had originally tried getElementById with the <video id="player"> on the first line of js, but this returned null.

EDIT: I have also tried querySelector and still recieved null

  • All attributes, and their values, are assigned using `=` never with `:` (unless you’re using a templating or scripting language I’m unfamiliar with). When is your JavaScript running, do the elements on the page exist when the JavaScript runs? – David Thomas May 25 '21 at 23:47
  • @DavidsaysreinstateMonica The OP is not assigning anything with `:`. The only `:` I see in the code is to reference the `selected` CSS pseudo-class. – Scott Marcus May 25 '21 at 23:50
  • @Scott: but ` – David Thomas May 25 '21 at 23:51
  • @DavidsaysreinstateMonica that is not part of my issue at the moment, though I will bear that in mind! –  May 25 '21 at 23:53
  • @DavidsaysreinstateMonica Ah, my mistake! I didn't see that one. ;) – Scott Marcus May 25 '21 at 23:54

2 Answers2

0

Since you are only interested (it seems) in working with the first video element, query for it with .querySelector() because .getElementsByClassName() returns a "live" node list (which is a collection) and node lists (collections) don't have an .appendChild method like individual elements do.

And, in your HTML you have data-target: and data-show:, which should be: data-target= and data-show=

And, you probably want to have your code run when the select value is changed not when the document is changed.

And, you really don't need data-show as option elements have their own value attribute, which is for exactly what you are doing here.

Also, don't use .getElementsByClassName() even when you do want a collection, use .querySelectorAll() for that.

Lastly, make sure your script is located just prior to the closing body tag so that by the time it is encountered, all the HTML will have been parsed into memory and your queries will find the appropriate elements.

<!doctype html>
<html>
<head>
  <title>My Page</title>
</head>
<body>
  <div class="past-player">
    <select class="vid-select" data-target=".past-player .player">
      <option value = "2020">2020</option>
      <option value = "2021">1</option>
      <option value = "2022">2</option>
      <option value = "2023">3</option>
      <option value = "2024">4</option>
      <option value = "2025">5</option>
      <option value = "2026">6</option>
      <option value = "2027">7</option>
    </select>
    <video class="player"></video>
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>  
  <script>
    var video = document.querySelector(".player");
    var source = document.createElement("source");

    source.src = "../shows/2020.mp4";

    video.appendChild(source);
    video.play();

    // Just access the select and set up an event on it
    $("select.vid-select").on("change", function() {
      var show = $("option:selected", this).val();
      source.src = "../shows/" + show + ".mp4";
      
      console.log(source.src); // Just for testing
    });
  </script>
</body>
</html>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
-1

getElementsByClassName returns an html collection, that is like an array, so you can use video[0].appendChild(source);, or get the element with querySelector