title: Javascript HTML5 video event canplay not firing on Safari
body: <p>I have a HTML page including Javascript which is intended to allow a video (actually just audio content in this case) to play using HTTP Live Streaming on any browser.  In most cases it uses <code>hls.js</code> but, in the case of Apple products, I need to do things differently as Safari has native HLS support.</p>
  
  <p>The full page is reproduced below but the important lines are these:</p>
  
  <pre><code>else if (video.canPlayType('application/vnd.apple.mpegurl')) {
      video.src = 'music.m3u8';
      video.addEventListener('canplay', startPlaying);
      //document.addEventListener('DOMContentLoaded', startPlaying);
  }
  </code></pre>
  
  <p>What should happen is that when the <code>canplay</code> event fires the <code>startPlaying()</code> function is called and this makes visible a button that the user can press to begin playing the video.  However, on my friend's iPhone 8plus (iOS 11.3.1), this doesn't work: no button is ever visible.  If, instead, I comment out the <code>video.addEventListener()</code> line and replace it with the <code>document.addEventListener()</code> line then it all works fine: the button is made visible and he can play the stream.</p>
  
  <p>Can anyone spot what I'm doing wrong?  Could be a rookey mistake as I'm not very experienced with this web/script stuff, gives me nose bleeds...  I could, of course, leave it with the DOM load approach but it's not <em>right</em> and I'd rather be right.</p>
  
  <pre><code>&lt;!DOCTYPE html PUBLIC "-//Netscape Comm. Corp.//DTD HTML//EN"&gt;
  &lt;html&gt;
  &lt;script src="hls.js/dist/hls.js"&gt;&lt;/script&gt;
  
  &lt;head&gt;&lt;meta http-equiv="content-type" content="text/html; charset=UTF-8"&gt;&lt;/head&gt;
  &lt;body&gt;
  &lt;video id="video"&gt;&lt;/video&gt;
  &lt;button id="play" hidden&gt;Loading&lt;/button&gt;
  &lt;script&gt;
  'use strict';
  var video = document.getElementById('video');
  var playButton = document.getElementById('play');
  
  function startPlaying() {
      // For mobile browsers the start of playing has to
      // be performed by a user action otherwise it will
      // be ignored
      playButton.addEventListener('click', function() {
          video.play();
          video.muted = false;
          video.volume = 1;
          playButton.innerHTML = "Playing";
      });
      playButton.hidden = false;
      playButton.innerHTML = "Ready to play";
  }
  
  if (Hls.isSupported()) {
      var hls = new Hls();
      hls.loadSource('music.m3u8');
      hls.attachMedia(video);
      hls.on(Hls.Events.MANIFEST_PARSED, startPlaying);
  }
  // hls.js is not supported on platforms that do not have Media Source Extensions (MSE) enabled.
  // When the browser has built-in HLS support (check using `canPlayType`), we can provide an HLS manifest (i.e. .m3u8 URL) directly to the video element through the `src` property.
  // This is using the built-in support of the plain video element, without using hls.js.
  else if (video.canPlayType('application/vnd.apple.mpegurl')) {
      video.src = 'music.m3u8';
      video.addEventListener('canplay', startPlaying);
      //document.addEventListener('DOMContentLoaded', startPlaying);
  }
  &lt;/script&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>