onChange() {
    if (!this.video.duration) {
      // Can't seek yet.  Ignore.
      return;
    }

    // Update the UI right away.
    this.update();

    // We want to wait until the user has stopped moving the seek bar for a
    // little bit to reduce the number of times we ask the player to seek.
    //
    // To do this, we will start a timer that will fire in a little bit, but if
    // we see another seek bar change, we will cancel that timer and re-start
    // it.
    //
    // Calling |start| on an already pending timer will cancel the old request
    // and start the new one.
    this.seekTimer_.tickAfter(/* seconds= */ 0.125);

    if (this.player.getImageTracks().length &&
        !this.controls.anySettingsMenusAreOpen()) {
      const min = parseFloat(this.bar.min);
      const max = parseFloat(this.bar.max);
      const rect = this.bar.getBoundingClientRect();
      const value = Math.round(this.getValue());
      const scale = (max - min) / rect.width;
      const position = (value - min) / scale;
      this.showThumbnail_(position, value);
    } else {
      this.hideThumbnail_();
    }
  }
Update the video element's state to match the input element's state.
Called by the base class when the input element changes.

@override