Search code examples
javascripthtmlpolymerweb-component

HTML <video> tag not playing source videos that pass through insertion point


Below is the definition of my 'video-player' element. You'll notice in its template tag that it expects source tags to be in the light dom, and if this is the case it wraps these source tags around a video tag.

<link rel="import" href="../../bower_components/polymer/polymer.html">

<link rel="import" href="../../bower_components/core-icons/core-icons.html"/>
<link rel="import" href="../../bower_components/core-icon-button/core-icon-button.html"/>
<link rel="import" href="../../bower_components/core-icons/av-icons.html">
<link rel="import" href="../../custom_components/content-pane/content-pane.html">


<polymer-element name="video-player">
<template>

   <!--STYLES OMMITED-->

<content-pane hint = "This is a video." label="Video">
 <core-icon-button id="play" icon="av:play-arrow" on-click="{{toggle}}"></core-icon-button>
<video>

<content id = "content" select = "source">
</content>

</video>
</content-pane>

</template>

  <script>
    Polymer('video-player', {       
       toggle: function(e) {
        console.log("TOGGLE CALLED")
          var video = this.shadowRoot.querySelector("video")
          var play = this.shadowRoot.querySelector("#play")
          play.style.display = "none";
          video.play()
          video.style.opacity = "1";
          video.onended = function() {
            video.load()
            video.style.opacity = ".5"
            play.style.display = "inline"
          }
        },
        domReady : function () {

          console.log("DOM IS READY")
          console.log(this.shadowRoot.querySelector("#content").getDistributedNodes())
        }

}) 
  </script>
</polymer-element>

However, when I use the element like so (from within a different custom element's shadom dom)...

<video-player>
<source src="../../assets/video/toy.mp4" type="video/mp4"/>
<source src="../../assets/video/toy.ogv" type="video/ogv"/>

</video-player>

No videos appear. Videos DO appear if I simply write:

<video>
    <source src="../../assets/video/toy.mp4" type="video/mp4"/>
    <source src="../../assets/video/toy.ogv" type="video/ogv"/>
</video

But that's no fun, for obvious reasons (I want extra things to be happening in the video-player element).

Why is this happening? My best guess is that light dom source nodes getting distributed into a video tag in the shadow dom aren't "technically" getting attached as children. Do I have to find a way to add the source nodes to the element's SHADOW dom, rather than inserting into the light Dom? And if so, how?


Solution

  • I think I answered my own question. It does appear that you have to bring in the source elements to the shadow root in order to get the video tag to actually recognize them.

    So putting this code in the video-player constructor did the trick:
    
    attached : function () {    
              for (var i = 0; i <= this.children.length - 1; i++) {
                  var child = this.children[i];
                  this.shadowRoot.querySelector("video").appendChild(child)
    }
            }
    

    Perhaps this is because the content tag refers only to RENDERING light dom nodes in a particular location. Content tags do not literally insert the elements into your shadow dom. That is my understanding, at least.