<commit_before>/**
 * USEFUL LINKS:
 * Media events on <audio> and <video> tags:
 * https://developer.mozilla.org/en-US/docs/Web/Guide/DOM/Events/Media_events
 * Properties and Methods:
 * https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
 *
 * Understanding TimeRanges objects:
 * http://html5doctor.com/html5-audio-the-state-of-play/
 *
 * Wonderful documentation from MDN, really.
 */
angular.module('angular-audio-player', ['helperFunctions'])

.directive('audioPlayer', ['$rootScope', '$log', '$interpolate', '$timeout', 'throttle',
  function ($rootScope, $log, $interpolate, $timeout, throttle) {

    /**
     * @usage: new AudioPlayer(element, scope, [playlist], [options]);
     *
     * @param {jqLite/jQuery element} [element] [usually that would be the element the directive is attached to]
     * @param {angular Scope} [scope] [scope in which call $apply, it could even be $rootScope (untested!)]
     * @param {Array} [playlist] [an Array made of audioElements (refer to README.md)]
     */
    var AudioPlayer = function (element, scope, playlist, options) {
      if (!(this instanceof AudioPlayer)) { return new AudioPlayer(playlist, options); }

      options = options || {};
      playlist = playlist || [];

      this._element = element;
      this._audioTag = element[0];
      this._name = options.name || 'audioplayer';
      this._scope = scope; // useless for now
      this._bindListeners(scope);
      this._playlist = playlist;

      this.playing = false;
      this.currentTrack = 0;
      this.tracks = playlist.length;
      // just exposing <audio> properties.
      this.volume = this._audioTag.volume;
      this.duration = this._audioTag.duration;
      this.formatDuration = '';
      this.currentTime = this._audioTag.currentTime;
      this.formatTime = '';
      this.loadPercent = 0;
      // Alias
      this.position = this.currentTime;
      /**
       * TODO:
       * buffered - from audioTag
       * seekable - from audioTag
       *
       * Events:
       * audioplayer:next - when issued a next()
       * audioplayer:prev - when issued a prev()
       */
    };

    AudioPlayer.prototype = {
      /**
       * @usage load([audioElement], [autoplayNext]);
       * 
       * @param  {audioElement Obj} audioElement [a single audioElement, may contain multiple <source>(s)]
       * @param  {boolean} autoplayNext [flag to autostart loaded element]
       */
      load: function (audioElement, autoplayNext) {
        if (typeof audioElement === 'boolean') {
          autoplayNext = audioElement;
          audioElement = null;
        } else if (typeof audioElement === 'object') {
          this._clearAudioList();
          this._addAudioList(audioElement);
        }
        this._audioTag.load();
        if (autoplayNext) {
          var self = this;
          self._element.bind('canplaythrough', function (evt) {
            self.play();
            self._element.unbind('canplaythrough');
          });
        }
      },
      /**
       * @usage play([index])
       * @param  {integer} index [playlist index (0...n), to start playing from]
       */
      play: function (index) {
        if (this._playlist.length > index) {
          this.currentTrack = index + 1;
          return this.load(this._playlist[index], true);
        }
        // readyState = HAVE_NOTHING (0) means there's nothing into the <audio> tag
        if (!this.currentTrack && this._audioTag.readyState) { this.currentTrack++; }
        this._audioTag.play();
      },
      playPause: function (index) {
        if (index) {
          this.play(index);
        } else if (this.playing) {
          this.pause();
        } else {
          this.play();
        }<commit_msg>fix stupid mistake on playPause index (it CAN be 0, since playlist is 0...n)<commit_after>/**
 * USEFUL LINKS:
 * Media events on <audio> and <video> tags:
 * https://developer.mozilla.org/en-US/docs/Web/Guide/DOM/Events/Media_events
 * Properties and Methods:
 * https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
 *
 * Understanding TimeRanges objects:
 * http://html5doctor.com/html5-audio-the-state-of-play/
 *
 * Wonderful documentation from MDN, really.
 */
angular.module('angular-audio-player', ['helperFunctions'])

.directive('audioPlayer', ['$rootScope', '$log', '$interpolate', '$timeout', 'throttle',
  function ($rootScope, $log, $interpolate, $timeout, throttle) {

    /**
     * @usage: new AudioPlayer(element, scope, [playlist], [options]);
     *
     * @param {jqLite/jQuery element} [element] [usually that would be the element the directive is attached to]
     * @param {angular Scope} [scope] [scope in which call $apply, it could even be $rootScope (untested!)]
     * @param {Array} [playlist] [an Array made of audioElements (refer to README.md)]
     */
    var AudioPlayer = function (element, scope, playlist, options) {
      if (!(this instanceof AudioPlayer)) { return new AudioPlayer(playlist, options); }

      options = options || {};
      playlist = playlist || [];

      this._element = element;
      this._audioTag = element[0];
      this._name = options.name || 'audioplayer';
      this._scope = scope; // useless for now
      this._bindListeners(scope);
      this._playlist = playlist;

      this.playing = false;
      this.currentTrack = 0;
      this.tracks = playlist.length;
      // just exposing <audio> properties.
      this.volume = this._audioTag.volume;
      this.duration = this._audioTag.duration;
      this.formatDuration = '';
      this.currentTime = this._audioTag.currentTime;
      this.formatTime = '';
      this.loadPercent = 0;
      // Alias
      this.position = this.currentTime;
      /**
       * TODO:
       * buffered - from audioTag
       * seekable - from audioTag
       *
       * Events:
       * audioplayer:next - when issued a next()
       * audioplayer:prev - when issued a prev()
       */
    };

    AudioPlayer.prototype = {
      /**
       * @usage load([audioElement], [autoplayNext]);
       * 
       * @param  {audioElement Obj} audioElement [a single audioElement, may contain multiple <source>(s)]
       * @param  {boolean} autoplayNext [flag to autostart loaded element]
       */
      load: function (audioElement, autoplayNext) {
        if (typeof audioElement === 'boolean') {
          autoplayNext = audioElement;
          audioElement = null;
        } else if (typeof audioElement === 'object') {
          this._clearAudioList();
          this._addAudioList(audioElement);
        }
        this._audioTag.load();
        if (autoplayNext) {
          var self = this;
          self._element.bind('canplaythrough', function (evt) {
            self.play();
            self._element.unbind('canplaythrough');
          });
        }
      },
      /**
       * @usage play([index])
       * @param  {integer} index [playlist index (0...n), to start playing from]
       */
      play: function (index) {
        if (this._playlist.length > index) {
          this.currentTrack = index + 1;
          return this.load(this._playlist[index], true);
        }
        // readyState = HAVE_NOTHING (0) means there's nothing into the <audio> tag
        if (!this.currentTrack && this._audioTag.readyState) { this.currentTrack++; }
        this._audioTag.play();
      },
      playPause: function (index) {
        if (typeof index === 'number') {
          this.play(index);
        } else if (this.playing) {
          this.pause();
        } else {
          this.play();
        }
{'fraction_non_alphanumeric': 0.13544287038262942, 'fraction_numerical': 0.0023831590096650337, 'mean_word_length': 2.3813786929274845, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1525086', 'n_tokens_mistral': 2226, 'n_tokens_neox': 2169, 'n_words': 543}