12

I am able to add events fine.

addEventListener("onStateChange", "handleStateChange");

but when trying to remove the event, it does not.

removeEventListener("onStateChange", "handleStateChange");

handleStateChange is still being called whenever I pause/play the video. Has anyone run into this and have a solution? or is there a bug on the API?

2 Answers 2

7

I think the issue is that the player object of the YouTube API has no removeEventListener method. Keep in mind that when you call addEventListener, you are doing so as a method of the constructed youtube player object rather than using the one defined as a method of DOM elements (the YouTube API chooses to name their method the same in order to be more familiar for developers).

One suggestion which has worked for others in the past is to, when you're in a situation that might need to remove the event listener, you instead just redefine your state change callback ... something like:

handleStateChange = function() {};
Sign up to request clarification or add additional context in comments.

4 Comments

however, the changelog says that method was added on April 28, 2014 developers.google.com/youtube/… if I still can't get it to work, I believe your suggested method will work. thanks
Huh ... guess I missed that in the changelogs; but you're absolutely right that it isn't functioning at all; I've tried with all the different events that the API exposes. You might want to file a bug: code.google.com/p/gdata-issues/issues/… ... in any case, this workaround should serve your needs until the engineers get it figured out.
Still an issue here in 2018
Still an issue in March 2019. Event the suggestion above does not work.
2

This was problematic enough for my application that I made a sort of event emitting proxy for the YouTube player object.

Usage (where player is your YouTube Iframe API Player instance):

const playerEventProxy = new YouTubeEventProxy(player);

function handleStateChange(e) {
  // …
}

playerEventProxy.on('stateChange', handleStateChange);
playerEventProxy.off('stateChange', handleStateChange);

Class:

/**
 * YouTubeEventProxy
 * Quick and dirty hack around broken event handling in the YouTube Iframe API.
 * Events are renamed, dropping the "on" and lower-casing the first character.
 * Methods 'on', 'off', etc. are supported, as-provided by event-emitter.
 * See also:  https://stackoverflow.com/q/25880573/362536
 * 
 * Brad Isbell <[email protected]>
 * License: MIT <https://opensource.org/licenses/MIT>
 */

import EventEmitter from 'event-emitter';

// From: https://developers.google.com/youtube/iframe_api_reference#Events
const ytApiEvents = [
  'onApiChange',
  'onError',
  'onPlaybackQualityChange',
  'onPlaybackRateChange',
  'onReady',
  'onStateChange'
];

export default class YouTubeEventProxy extends EventEmitter {
  constructor(player) {
    super();

    this.player = player;

    ytApiEvents.forEach((eventName) => {
      player.addEventListener(
        eventName,
        this.emit.bind(
          this,
          eventName.substr(2, 1).toLowerCase() + eventName.substr(3)
        )
      );
    });

  }
}

This is the event-emitter package: https://www.npmjs.com/package/event-emitter

1 Comment

Another thing to note is that sometimes the YouTube player will fire multiple events in the same synchronous block of code. This happens e.g. when calling nextVideo(), which fires pause and unstarted state changes. If for example using react hooks, this can cause a headache. Can be solves by changing the this.emit.bind...-line to: e => setTimeout(() => this.emit(eventName.substr(2, 1).toLowerCase() + eventName.substr(3), e), 0),

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.