4

Preface:

I want say I have tried my best to avoid making this a duplicate question, i.e. searched Google on my own, read a lot of other similar questions, etc. I found a lot of really helpful things that have led me to this specific situation for which I have code to show, so hopefully my final question will be clear and answerable.

I have a simple website built with plain HTML and Bootstrap for the CSS. There is an embedded, full-screen Youtube video on the homepage showcasing some singers. So sound on the videos is wanted, but I also want a mute button without giving all the controls of the youtube video (pause/play, quality, captions, etc.).

I have successfully accomplished this in a JSFiddle using the Youtube API found on their developer pages. http://jsfiddle.net/Bvance/8bzxp9c2/

Problem:

The problem is that with the exact same code from the working JsFiddle on my website I get the error Uncaught TypeError: player.isMuted is not a function at HTMLDivElement.<anonymous> (main.js:154)

Here is my HTML:

<div class="container-fluid video-background" id="home">
    <iframe id="myPlayer" width="100%" height="100%" src="https://www.youtube.com/embed/videoseries?list=PLr3L2qYLOPjj8caQDOfdhuvHSWQdrUAjq&
    autoplay=1
    &disablekb=1
    &enablejsapi=1
    &loop=1
    &controls=0
    &mute=0
    &index=1
    " frameborder="0" allowfullscreen></iframe>

    <a href="#welcome" title="Welcome" id="welcome-down">
        <span class="glyphicon glyphicon-chevron-down"></span>
    </a>

    <div id="muteButton">
</div>

Here is my Javascript:

//Necessary to laod the Youtube API
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

var player;
function onYouTubeIframeAPIReady() {

  console.log(player);

  player = new YT.Player('myPlayer', {
    events: {
      'onReady': onPlayerReady,
      'onStateChange': onPlayerStateChange,
      'onError': onPlayerError
    }
  }); 
}

function onPlayerError(event) {
  alert(event.data);
}

function onPlayerReady() {
  alert("hey Im ready");
  //do whatever you want here. Like, player.playVideo();

}

function onPlayerStateChange() {
  alert("my state changed");

}
//Setting the event listener to the mute button
document.getElementById("muteButton").addEventListener('click', function (event) {
      console.log(player);

      if(player.isMuted())
      {
        player.unMute();
      } else {
        player.mute();
      }
});

This javascript is just a snippet of the full file but it is the first thing in the file. I use some JQuery and have a $(document).ready{ below this portion of code. I understand that putting the API calls in that would not work (and I've tried it).

What I've tried:

In my debugging I have been printing the player object to the console before and after I make the YT.Player() call and an object is returning. Though for some reason it has no access to any of it's functions on my site. When checking the JSFiddle code, however, it does show everything when printed to the console.

You can compare this to the printed player object in the console while using the JSFiddle Screenshot of console for printed 'player' object

I've tried moving the document.getElementById("muteButton").addEventListener to different places including inside of onYouTubeIframeAPIReady() to no avail. I have also tried moving this whole chunk of javascript to then end of the js file and inside the $(document).ready{ just to try different things. Nothing.

What am I missing? Thanks for reading this far!

UPDATE:

So i was messing around with JSFIddle and trying to trim down the hosted site code until it could function like the working JSFiddle, but I even got to the point where both fiddles were identical and one still didn't work. I'm stumped. I even copied and pasted the working fiddle into a new one and the new one didn't work either! I really don't know what's going on..

Brandon Vance
  • 53
  • 3
  • 7
  • Rather that moving the whole API script into the `jQuery` DOM ready function, have you tried to place just the script to bring the event listener for your mute button? This shouldn't cause problems as `player` is already defined and the youtube player API is no doubt ready to use before you bind the mute event. – NewToJS Aug 22 '17 at 00:35
  • @NewToJS That's a good thought! Though I tried it and got the same results :/ One thing to note is that not even the OnPlayerReady() or onPlayerStateChange() are evoked. So something is messing up and not allowing the player to fully be 'ready'... – Brandon Vance Aug 22 '17 at 16:47
  • Maybe try swap your `myPlayer` element from an `iframe` to a `div`, not really sure why you have an iframe, the player API will take care of the rest. Not 100% sure it will be that causing the issue and I can't really test anything for myself at this moment in time otherwise I would check and give you a solid answer. – NewToJS Aug 23 '17 at 00:44
  • @NewToJS I'll be darned, that did it! I'm not sure why that fixed it either. On the API documentation it does say it's possible with an existing iFrame, and as seen in the fiddle it can work sometimes. But making it a div was the trick! Thanks! On a latter note, would you mind posting that as an answer to my post so I could accept it as a correct answer? – Brandon Vance Aug 25 '17 at 02:11
  • @BrandonVance can you please share the complete code that solved your issue? – hockey2112 Jun 12 '18 at 13:37

1 Answers1

2

The trouble here is that "player.isMuted()" doesn't have to return Boolean value. It could / could not. So you should make sure your check returns Boolean value. The quick way in this case is using double negation trick. So:

Try changing:

if(player.isMuted())
      {
        player.unMute();
      } else {
        player.mute();
      }

into

if(!!player.isMuted())
      {
        player.unMute();
      } else {
        player.mute();
      }

worked for me that way.

If you want to get more info about this solution check out those articles: codereviewvideos.com/blog/example-javascript-double-negative or sitepoint.com/javascript-double-negation-trick-trouble or Jamie Treworgy answer in this: stackoverflow.com/questions/10467475/double-negation-in-javascript-what-is-the-purpose

Adam Orłowski
  • 4,268
  • 24
  • 33
  • 2
    Thank you for this code snippet, which might provide some limited, immediate help. A proper explanation [would greatly improve](//meta.stackexchange.com/q/114762) its long-term value by showing *why* this is a good solution to the problem, and would make it more useful to future readers with other, similar questions. Please [edit] your answer to add some explanation, including the assumptions you've made. – Toby Speight Dec 13 '17 at 14:34