Version 1
[yaffs-website] / node_modules / video.js / es5 / tracks / text-track.js
diff --git a/node_modules/video.js/es5/tracks/text-track.js b/node_modules/video.js/es5/tracks/text-track.js
new file mode 100644 (file)
index 0000000..f9e8af0
--- /dev/null
@@ -0,0 +1,449 @@
+'use strict';
+
+exports.__esModule = true;
+
+var _textTrackCueList = require('./text-track-cue-list');
+
+var _textTrackCueList2 = _interopRequireDefault(_textTrackCueList);
+
+var _fn = require('../utils/fn.js');
+
+var Fn = _interopRequireWildcard(_fn);
+
+var _trackEnums = require('./track-enums');
+
+var _log = require('../utils/log.js');
+
+var _log2 = _interopRequireDefault(_log);
+
+var _window = require('global/window');
+
+var _window2 = _interopRequireDefault(_window);
+
+var _track = require('./track.js');
+
+var _track2 = _interopRequireDefault(_track);
+
+var _url = require('../utils/url.js');
+
+var _xhr = require('xhr');
+
+var _xhr2 = _interopRequireDefault(_xhr);
+
+var _mergeOptions = require('../utils/merge-options');
+
+var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
+
+var _browser = require('../utils/browser.js');
+
+var browser = _interopRequireWildcard(_browser);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @file text-track.js
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */
+
+
+/**
+ * Takes a webvtt file contents and parses it into cues
+ *
+ * @param {string} srcContent
+ *        webVTT file contents
+ *
+ * @param {TextTrack} track
+ *        TextTrack to add cues to. Cues come from the srcContent.
+ *
+ * @private
+ */
+var parseCues = function parseCues(srcContent, track) {
+  var parser = new _window2['default'].WebVTT.Parser(_window2['default'], _window2['default'].vttjs, _window2['default'].WebVTT.StringDecoder());
+  var errors = [];
+
+  parser.oncue = function (cue) {
+    track.addCue(cue);
+  };
+
+  parser.onparsingerror = function (error) {
+    errors.push(error);
+  };
+
+  parser.onflush = function () {
+    track.trigger({
+      type: 'loadeddata',
+      target: track
+    });
+  };
+
+  parser.parse(srcContent);
+  if (errors.length > 0) {
+    if (_window2['default'].console && _window2['default'].console.groupCollapsed) {
+      _window2['default'].console.groupCollapsed('Text Track parsing errors for ' + track.src);
+    }
+    errors.forEach(function (error) {
+      return _log2['default'].error(error);
+    });
+    if (_window2['default'].console && _window2['default'].console.groupEnd) {
+      _window2['default'].console.groupEnd();
+    }
+  }
+
+  parser.flush();
+};
+
+/**
+ * Load a `TextTrack` from a specifed url.
+ *
+ * @param {string} src
+ *        Url to load track from.
+ *
+ * @param {TextTrack} track
+ *        Track to add cues to. Comes from the content at the end of `url`.
+ *
+ * @private
+ */
+var loadTrack = function loadTrack(src, track) {
+  var opts = {
+    uri: src
+  };
+  var crossOrigin = (0, _url.isCrossOrigin)(src);
+
+  if (crossOrigin) {
+    opts.cors = crossOrigin;
+  }
+
+  (0, _xhr2['default'])(opts, Fn.bind(this, function (err, response, responseBody) {
+    if (err) {
+      return _log2['default'].error(err, response);
+    }
+
+    track.loaded_ = true;
+
+    // Make sure that vttjs has loaded, otherwise, wait till it finished loading
+    // NOTE: this is only used for the alt/video.novtt.js build
+    if (typeof _window2['default'].WebVTT !== 'function') {
+      if (track.tech_) {
+        var loadHandler = function loadHandler() {
+          return parseCues(responseBody, track);
+        };
+
+        track.tech_.on('vttjsloaded', loadHandler);
+        track.tech_.on('vttjserror', function () {
+          _log2['default'].error('vttjs failed to load, stopping trying to process ' + track.src);
+          track.tech_.off('vttjsloaded', loadHandler);
+        });
+      }
+    } else {
+      parseCues(responseBody, track);
+    }
+  }));
+};
+
+/**
+ * A representation of a single `TextTrack`.
+ *
+ * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrack}
+ * @extends Track
+ */
+
+var TextTrack = function (_Track) {
+  _inherits(TextTrack, _Track);
+
+  /**
+   * Create an instance of this class.
+   *
+   * @param {Object} options={}
+   *        Object of option names and values
+   *
+   * @param {Tech} options.tech
+   *        A reference to the tech that owns this TextTrack.
+   *
+   * @param {TextTrack~Kind} [options.kind='subtitles']
+   *        A valid text track kind.
+   *
+   * @param {TextTrack~Mode} [options.mode='disabled']
+   *        A valid text track mode.
+   *
+   * @param {string} [options.id='vjs_track_' + Guid.newGUID()]
+   *        A unique id for this TextTrack.
+   *
+   * @param {string} [options.label='']
+   *        The menu label for this track.
+   *
+   * @param {string} [options.language='']
+   *        A valid two character language code.
+   *
+   * @param {string} [options.srclang='']
+   *        A valid two character language code. An alternative, but deprioritized
+   *        vesion of `options.language`
+   *
+   * @param {string} [options.src]
+   *        A url to TextTrack cues.
+   *
+   * @param {boolean} [options.default]
+   *        If this track should default to on or off.
+   */
+  function TextTrack() {
+    var _this, _ret;
+
+    var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+    _classCallCheck(this, TextTrack);
+
+    if (!options.tech) {
+      throw new Error('A tech was not provided.');
+    }
+
+    var settings = (0, _mergeOptions2['default'])(options, {
+      kind: _trackEnums.TextTrackKind[options.kind] || 'subtitles',
+      language: options.language || options.srclang || ''
+    });
+    var mode = _trackEnums.TextTrackMode[settings.mode] || 'disabled';
+    var default_ = settings['default'];
+
+    if (settings.kind === 'metadata' || settings.kind === 'chapters') {
+      mode = 'hidden';
+    }
+    // on IE8 this will be a document element
+    // for every other browser this will be a normal object
+    var tt = (_this = _possibleConstructorReturn(this, _Track.call(this, settings)), _this);
+
+    tt.tech_ = settings.tech;
+
+    if (browser.IS_IE8) {
+      for (var prop in TextTrack.prototype) {
+        if (prop !== 'constructor') {
+          tt[prop] = TextTrack.prototype[prop];
+        }
+      }
+    }
+
+    tt.cues_ = [];
+    tt.activeCues_ = [];
+
+    var cues = new _textTrackCueList2['default'](tt.cues_);
+    var activeCues = new _textTrackCueList2['default'](tt.activeCues_);
+    var changed = false;
+    var timeupdateHandler = Fn.bind(tt, function () {
+
+      // Accessing this.activeCues for the side-effects of updating itself
+      // due to it's nature as a getter function. Do not remove or cues will
+      // stop updating!
+      /* eslint-disable no-unused-expressions */
+      this.activeCues;
+      /* eslint-enable no-unused-expressions */
+      if (changed) {
+        this.trigger('cuechange');
+        changed = false;
+      }
+    });
+
+    if (mode !== 'disabled') {
+      tt.tech_.ready(function () {
+        tt.tech_.on('timeupdate', timeupdateHandler);
+      }, true);
+    }
+
+    /**
+     * @member {boolean} default
+     *         If this track was set to be on or off by default. Cannot be changed after
+     *         creation.
+     *
+     * @readonly
+     */
+    Object.defineProperty(tt, 'default', {
+      get: function get() {
+        return default_;
+      },
+      set: function set() {}
+    });
+
+    /**
+     * @member {string} mode
+     *         Set the mode of this TextTrack to a valid {@link TextTrack~Mode}. Will
+     *         not be set if setting to an invalid mode.
+     *
+     * @fires TextTrack#modechange
+     */
+    Object.defineProperty(tt, 'mode', {
+      get: function get() {
+        return mode;
+      },
+      set: function set(newMode) {
+        var _this2 = this;
+
+        if (!_trackEnums.TextTrackMode[newMode]) {
+          return;
+        }
+        mode = newMode;
+        if (mode === 'showing') {
+          this.tech_.ready(function () {
+            _this2.tech_.on('timeupdate', timeupdateHandler);
+          }, true);
+        }
+        /**
+         * An event that fires when mode changes on this track. This allows
+         * the TextTrackList that holds this track to act accordingly.
+         *
+         * > Note: This is not part of the spec!
+         *
+         * @event TextTrack#modechange
+         * @type {EventTarget~Event}
+         */
+        this.trigger('modechange');
+      }
+    });
+
+    /**
+     * @member {TextTrackCueList} cues
+     *         The text track cue list for this TextTrack.
+     */
+    Object.defineProperty(tt, 'cues', {
+      get: function get() {
+        if (!this.loaded_) {
+          return null;
+        }
+
+        return cues;
+      },
+      set: function set() {}
+    });
+
+    /**
+     * @member {TextTrackCueList} activeCues
+     *         The list text track cues that are currently active for this TextTrack.
+     */
+    Object.defineProperty(tt, 'activeCues', {
+      get: function get() {
+        if (!this.loaded_) {
+          return null;
+        }
+
+        // nothing to do
+        if (this.cues.length === 0) {
+          return activeCues;
+        }
+
+        var ct = this.tech_.currentTime();
+        var active = [];
+
+        for (var i = 0, l = this.cues.length; i < l; i++) {
+          var cue = this.cues[i];
+
+          if (cue.startTime <= ct && cue.endTime >= ct) {
+            active.push(cue);
+          } else if (cue.startTime === cue.endTime && cue.startTime <= ct && cue.startTime + 0.5 >= ct) {
+            active.push(cue);
+          }
+        }
+
+        changed = false;
+
+        if (active.length !== this.activeCues_.length) {
+          changed = true;
+        } else {
+          for (var _i = 0; _i < active.length; _i++) {
+            if (this.activeCues_.indexOf(active[_i]) === -1) {
+              changed = true;
+            }
+          }
+        }
+
+        this.activeCues_ = active;
+        activeCues.setCues_(this.activeCues_);
+
+        return activeCues;
+      },
+      set: function set() {}
+    });
+
+    if (settings.src) {
+      tt.src = settings.src;
+      loadTrack(settings.src, tt);
+    } else {
+      tt.loaded_ = true;
+    }
+
+    return _ret = tt, _possibleConstructorReturn(_this, _ret);
+  }
+
+  /**
+   * Add a cue to the internal list of cues.
+   *
+   * @param {TextTrack~Cue} cue
+   *        The cue to add to our internal list
+   */
+
+
+  TextTrack.prototype.addCue = function addCue(originalCue) {
+    var cue = originalCue;
+
+    if (_window2['default'].vttjs && !(originalCue instanceof _window2['default'].vttjs.VTTCue)) {
+      cue = new _window2['default'].vttjs.VTTCue(originalCue.startTime, originalCue.endTime, originalCue.text);
+
+      for (var prop in originalCue) {
+        if (!(prop in cue)) {
+          cue[prop] = originalCue[prop];
+        }
+      }
+
+      // make sure that `id` is copied over
+      cue.id = originalCue.id;
+      cue.originalCue_ = originalCue;
+    }
+
+    var tracks = this.tech_.textTracks();
+
+    if (tracks) {
+      for (var i = 0; i < tracks.length; i++) {
+        if (tracks[i] !== this) {
+          tracks[i].removeCue(cue);
+        }
+      }
+    }
+
+    this.cues_.push(cue);
+    this.cues.setCues_(this.cues_);
+  };
+
+  /**
+   * Remove a cue from our internal list
+   *
+   * @param {TextTrack~Cue} removeCue
+   *        The cue to remove from our internal list
+   */
+
+
+  TextTrack.prototype.removeCue = function removeCue(_removeCue) {
+    var i = this.cues_.length;
+
+    while (i--) {
+      var cue = this.cues_[i];
+
+      if (cue === _removeCue || cue.originalCue_ && cue.originalCue_ === _removeCue) {
+        this.cues_.splice(i, 1);
+        this.cues.setCues_(this.cues_);
+        break;
+      }
+    }
+  };
+
+  return TextTrack;
+}(_track2['default']);
+
+/**
+ * cuechange - One or more cues in the track have become active or stopped being active.
+ */
+
+
+TextTrack.prototype.allowedEvents_ = {
+  cuechange: 'cuechange'
+};
+
+exports['default'] = TextTrack;