Merge branch 'MDL-67383-master-1' of git://github.com/mihailges/moodle
authorAndrew Nicols <andrew@nicols.co.uk>
Wed, 6 May 2020 01:43:34 +0000 (09:43 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Wed, 6 May 2020 03:06:10 +0000 (11:06 +0800)
27 files changed:
media/player/videojs/amd/build/Youtube-lazy.min.js
media/player/videojs/amd/build/Youtube-lazy.min.js.map
media/player/videojs/amd/build/video-lazy.min.js
media/player/videojs/amd/build/video-lazy.min.js.map
media/player/videojs/amd/build/videojs-flash-lazy.min.js
media/player/videojs/amd/build/videojs-flash-lazy.min.js.map
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/videojs-flash-lazy.js
media/player/videojs/fonts/VideoJS.svg [changed mode: 0644->0755]
media/player/videojs/fonts/VideoJS.ttf [changed mode: 0644->0755]
media/player/videojs/fonts/VideoJS.woff [changed mode: 0644->0755]
media/player/videojs/readme_moodle.txt
media/player/videojs/thirdpartylibs.xml
media/player/videojs/videojs/lang/ar.js
media/player/videojs/videojs/lang/ar.json
media/player/videojs/videojs/lang/de.js
media/player/videojs/videojs/lang/de.json
media/player/videojs/videojs/lang/en.js
media/player/videojs/videojs/lang/en.json
media/player/videojs/videojs/lang/fa.js
media/player/videojs/videojs/lang/fa.json
media/player/videojs/videojs/lang/gd.json [changed mode: 0644->0755]
media/player/videojs/videojs/lang/nb.js
media/player/videojs/videojs/lang/nb.json
media/player/videojs/videojs/lang/nn.js
media/player/videojs/videojs/lang/nn.json

index 71c16be..9fc42ac 100644 (file)
Binary files a/media/player/videojs/amd/build/Youtube-lazy.min.js and b/media/player/videojs/amd/build/Youtube-lazy.min.js differ
index 4553449..b4d5671 100644 (file)
Binary files a/media/player/videojs/amd/build/Youtube-lazy.min.js.map and b/media/player/videojs/amd/build/Youtube-lazy.min.js.map differ
index 38921dd..aec8187 100644 (file)
Binary files a/media/player/videojs/amd/build/video-lazy.min.js and b/media/player/videojs/amd/build/video-lazy.min.js differ
index 25772f1..4581b63 100644 (file)
Binary files a/media/player/videojs/amd/build/video-lazy.min.js.map and b/media/player/videojs/amd/build/video-lazy.min.js.map differ
index 79f882e..f28a0d1 100644 (file)
Binary files a/media/player/videojs/amd/build/videojs-flash-lazy.min.js and b/media/player/videojs/amd/build/videojs-flash-lazy.min.js differ
index 0802abc..c61c73c 100644 (file)
Binary files a/media/player/videojs/amd/build/videojs-flash-lazy.min.js.map and b/media/player/videojs/amd/build/videojs-flash-lazy.min.js.map differ
index 1c8dba4..de221fe 100644 (file)
@@ -1,13 +1,17 @@
 /* The MIT License (MIT)
+
 Copyright (c) 2014-2015 Benoit Tremblay <trembl.ben@gmail.com>
+
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
+
 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
+
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -363,7 +367,7 @@ THE SOFTWARE. */
         options.startSeconds = this.options_.start;
       }
       if (this.options_.end) {
-        options.endEnd = this.options_.end;
+        options.endSeconds = this.options_.end;
       }
       this.ytPlayer.loadVideoById(options);
     },
@@ -376,7 +380,7 @@ THE SOFTWARE. */
         options.startSeconds = this.options_.start;
       }
       if (this.options_.end) {
-        options.endEnd = this.options_.end;
+        options.endSeconds = this.options_.end;
       }
       this.ytPlayer.cueVideoById(options);
     },
@@ -736,6 +740,11 @@ THE SOFTWARE. */
     var loaded = false;
     var tag = document.createElement('script');
     var firstScriptTag = document.getElementsByTagName('script')[0];
+    if (!firstScriptTag) {
+      // when loaded in jest without jsdom setup it doesn't get any element.
+      // In jest it doesn't really make sense to do anything, because no one is watching youtube in jest
+      return;
+    }
     firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
     tag.onload = function () {
       if (!loaded) {
@@ -786,4 +795,4 @@ THE SOFTWARE. */
   } else {
     videojs.registerComponent('Youtube', Youtube);
   }
-}));
\ No newline at end of file
+}));
index b32a05d..9e57c6c 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * @license
- * Video.js 7.6.5 <http://videojs.com/>
+ * Video.js 7.7.6 <http://videojs.com/>
  * Copyright Brightcove, Inc. <https://www.brightcove.com/>
  * Available under Apache License Version 2.0
  * <https://github.com/videojs/video.js/blob/master/LICENSE>
   typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('global/window'), require('global/document')) :
   typeof define === 'function' && define.amd ? define(['./window', './document'], factory) :
   (global = global || self, global.videojs = factory(global.window, global.document));
-}(this, function (window$1, document) {
-  window$1 = window$1 && window$1.hasOwnProperty('default') ? window$1['default'] : window$1;
+}(this, function (window$3, document) { 'use strict';
+
+  window$3 = window$3 && window$3.hasOwnProperty('default') ? window$3['default'] : window$3;
   document = document && document.hasOwnProperty('default') ? document['default'] : document;
 
-  var version = "7.6.5";
+  var version = "7.7.6";
 
   /**
    * @file create-logger.js
       args.unshift(name + ':'); // Add a clone of the args at this point to history.
 
       if (history) {
-        history.push([].concat(args));
+        history.push([].concat(args)); // only store 1000 history entries
+
+        var splice = history.length - 1000;
+        history.splice(0, splice > 0 ? splice : 0);
       } // If there's no console then don't try to output messages, but they will
       // still be stored in history.
 
 
-      if (!window$1.console) {
+      if (!window$3.console) {
         return;
       } // Was setting these once outside of this function, but containing them
       // in the function makes it easier to test cases where console doesn't exist
       // when the module is executed.
 
 
-      var fn = window$1.console[type];
+      var fn = window$3.console[type];
 
       if (!fn && type === 'debug') {
         // Certain browsers don't have support for console.debug. For those, we
         // should default to the closest comparable log.
-        fn = window$1.console.info || window$1.console.log;
+        fn = window$3.console.info || window$3.console.log;
       } // Bail out if there's no console or if this type is not allowed by the
       // current logging level.
 
@@ -77,7 +81,7 @@
         return;
       }
 
-      fn[Array.isArray(args) ? 'apply' : 'call'](window$1.console, args);
+      fn[Array.isArray(args) ? 'apply' : 'call'](window$3.console, args);
     };
   };
 
   var log = createLogger('VIDEOJS');
   var createLogger$1 = log.createLogger;
 
+  function createCommonjsModule(fn, module) {
+       return module = { exports: {} }, fn(module, module.exports), module.exports;
+  }
+
+  var _extends_1 = createCommonjsModule(function (module) {
+    function _extends() {
+      module.exports = _extends = Object.assign || function (target) {
+        for (var i = 1; i < arguments.length; i++) {
+          var source = arguments[i];
+
+          for (var key in source) {
+            if (Object.prototype.hasOwnProperty.call(source, key)) {
+              target[key] = source[key];
+            }
+          }
+        }
+
+        return target;
+      };
+
+      return _extends.apply(this, arguments);
+    }
+
+    module.exports = _extends;
+  });
+
   /**
    * @file obj.js
    * @module obj
     }
 
     if (Object.assign) {
-      return Object.assign.apply(Object, [target].concat(sources));
+      return _extends_1.apply(void 0, [target].concat(sources));
     }
 
     sources.forEach(function (source) {
       return '';
     }
 
-    if (typeof window$1.getComputedStyle === 'function') {
-      var computedStyleValue = window$1.getComputedStyle(el);
+    if (typeof window$3.getComputedStyle === 'function') {
+      var computedStyleValue = window$3.getComputedStyle(el);
       return computedStyleValue ? computedStyleValue.getPropertyValue(prop) || computedStyleValue[prop] : '';
     }
 
    */
 
   function isNonBlankString(str) {
-    return typeof str === 'string' && /\S/.test(str);
+    // we use str.trim as it will trim any whitespace characters
+    // from the front or back of non-whitespace characters. aka
+    // Any string that contains non-whitespace characters will
+    // still contain them after `trim` but whitespace only strings
+    // will have a length of 0, failing this check.
+    return typeof str === 'string' && Boolean(str.trim());
   }
   /**
    * Throws an error if the passed string has whitespace. This is used by
 
 
   function throwIfWhitespace(str) {
-    if (/\s/.test(str)) {
+    // str.indexOf instead of regex because str.indexOf is faster performance wise.
+    if (str.indexOf(' ') >= 0) {
       throw new Error('class has illegal whitespace characters');
     }
   }
 
   function isReal() {
     // Both document and window will never be undefined thanks to `global`.
-    return document === window$1.document;
+    return document === window$3.document;
   }
   /**
    * Determines, via duck typing, whether or not a value is a DOM element.
     // We need a try/catch here because Safari will throw errors when attempting
     // to get either `parent` or `self`
     try {
-      return window$1.parent !== window$1.self;
+      return window$3.parent !== window$3.self;
     } catch (x) {
       return true;
     }
         // method for it.
       } else if (propName === 'textContent') {
         textContent(el, val);
-      } else {
+      } else if (el[propName] !== val) {
         el[propName] = val;
       }
     });
     var docEl = document.documentElement;
     var body = document.body;
     var clientLeft = docEl.clientLeft || body.clientLeft || 0;
-    var scrollLeft = window$1.pageXOffset || body.scrollLeft;
+    var scrollLeft = window$3.pageXOffset || body.scrollLeft;
     var left = box.left + scrollLeft - clientLeft;
     var clientTop = docEl.clientTop || body.clientTop || 0;
-    var scrollTop = window$1.pageYOffset || body.scrollTop;
+    var scrollTop = window$3.pageYOffset || body.scrollTop;
     var top = box.top + scrollTop - clientTop; // Android sometimes returns slightly off decimal values, so need to round
 
     return {
       videojs = vjs;
     }
 
-    window$1.setTimeout(autoSetup, wait);
+    window$3.setTimeout(autoSetup, wait);
   }
   /**
    * Used to set the internal tracking of window loaded state to true.
 
   function setWindowLoaded() {
     _windowLoaded = true;
-    window$1.removeEventListener('load', setWindowLoaded);
+    window$3.removeEventListener('load', setWindowLoaded);
   }
 
   if (isReal()) {
        *
        * @listens load
        */
-      window$1.addEventListener('load', setWindowLoaded);
+      window$3.addEventListener('load', setWindowLoaded);
     }
   }
 
     }
   };
 
-  /**
-   * @file dom-data.js
-   * @module dom-data
-   */
-
-  /**
-   * Element Data Store.
-   *
-   * Allows for binding data to an element without putting it directly on the
-   * element. Ex. Event listeners are stored here.
-   * (also from jsninja.com, slightly modified and updated for closure compiler)
-   *
-   * @type {Object}
-   * @private
-   */
-  var DomData = new WeakMap();
-
   /**
    * @file guid.js
    * @module guid
     return _guid++;
   }
 
+  /**
+   * @file dom-data.js
+   * @module dom-data
+   */
+  var FakeWeakMap;
+
+  if (!window$3.WeakMap) {
+    FakeWeakMap = /*#__PURE__*/function () {
+      function FakeWeakMap() {
+        this.vdata = 'vdata' + Math.floor(window$3.performance && window$3.performance.now() || Date.now());
+        this.data = {};
+      }
+
+      var _proto = FakeWeakMap.prototype;
+
+      _proto.set = function set(key, value) {
+        var access = key[this.vdata] || newGUID();
+
+        if (!key[this.vdata]) {
+          key[this.vdata] = access;
+        }
+
+        this.data[access] = value;
+        return this;
+      };
+
+      _proto.get = function get(key) {
+        var access = key[this.vdata]; // we have data, return it
+
+        if (access) {
+          return this.data[access];
+        } // we don't have data, return nothing.
+        // return undefined explicitly as that's the contract for this method
+
+
+        log('We have no data for this element', key);
+        return undefined;
+      };
+
+      _proto.has = function has(key) {
+        var access = key[this.vdata];
+        return access in this.data;
+      };
+
+      _proto["delete"] = function _delete(key) {
+        var access = key[this.vdata];
+
+        if (access) {
+          delete this.data[access];
+          delete key[this.vdata];
+        }
+      };
+
+      return FakeWeakMap;
+    }();
+  }
+  /**
+   * Element Data Store.
+   *
+   * Allows for binding data to an element without putting it directly on the
+   * element. Ex. Event listeners are stored here.
+   * (also from jsninja.com, slightly modified and updated for closure compiler)
+   *
+   * @type {Object}
+   * @private
+   */
+
+
+  var DomData = window$3.WeakMap ? new WeakMap() : new FakeWeakMap();
+
   /**
    * @file events.js. An Event System (John Resig - Secrets of a JS Ninja http://jsninja.com/)
    * (Original book version wasn't completely usable, so fixed some things and made Closure Compiler compatible)
 
 
   function fixEvent(event) {
+    if (event.fixed_) {
+      return event;
+    }
+
     function returnTrue() {
       return true;
     }
 
 
     if (!event || !event.isPropagationStopped) {
-      var old = event || window$1.event;
+      var old = event || window$3.event;
       event = {}; // Clone the old object so that we can modify the values event = {};
       // IE8 Doesn't like when you mess with native event properties
       // Firefox returns false for event.hasOwnProperty('type') and other props
         event.button = event.button & 1 ? 0 : event.button & 4 ? 1 : event.button & 2 ? 2 : 0;
         /* eslint-enable */
       }
-    } // Returns fixed-up instance
+    }
 
+    event.fixed_ = true; // Returns fixed-up instance
 
     return event;
   }
    * Whether passive event listeners are supported
    */
 
-  var _supportsPassive = false;
+  var _supportsPassive;
 
-  (function () {
-    try {
-      var opts = Object.defineProperty({}, 'passive', {
-        get: function get() {
-          _supportsPassive = true;
-        }
-      });
-      window$1.addEventListener('test', null, opts);
-      window$1.removeEventListener('test', null, opts);
-    } catch (e) {// disregard
+  var supportsPassive = function supportsPassive() {
+    if (typeof _supportsPassive !== 'boolean') {
+      _supportsPassive = false;
+
+      try {
+        var opts = Object.defineProperty({}, 'passive', {
+          get: function get() {
+            _supportsPassive = true;
+          }
+        });
+        window$3.addEventListener('test', null, opts);
+        window$3.removeEventListener('test', null, opts);
+      } catch (e) {// disregard
+      }
     }
-  })();
+
+    return _supportsPassive;
+  };
   /**
    * Touch events Chrome expects to be passive
    */
       if (elem.addEventListener) {
         var options = false;
 
-        if (_supportsPassive && passiveEvents.indexOf(type) > -1) {
+        if (supportsPassive() && passiveEvents.indexOf(type) > -1) {
           options = {
             passive: true
           };
    */
 
   var throttle = function throttle(fn, wait) {
-    var last = window$1.performance.now();
+    var last = window$3.performance.now();
 
     var throttled = function throttled() {
-      var now = window$1.performance.now();
+      var now = window$3.performance.now();
 
       if (now - last >= wait) {
         fn.apply(void 0, arguments);
 
   var debounce = function debounce(func, wait, immediate, context) {
     if (context === void 0) {
-      context = window$1;
+      context = window$3;
     }
 
     var timeout;
 
     var oldTimeout = map.get(type);
     map["delete"](type);
-    window$1.clearTimeout(oldTimeout);
-    var timeout = window$1.setTimeout(function () {
+    window$3.clearTimeout(oldTimeout);
+    var timeout = window$3.setTimeout(function () {
       // if we cleared out all timeouts for the current target, delete its map
       if (map.size === 0) {
         map = null;
 
     target.on('dispose', function () {
       target.off();
-      window$1.setTimeout(function () {
+      window$3.setTimeout(function () {
         target.eventBusEl_ = null;
       }, 0);
     });
    * Components can also use methods from {@link EventTarget}
    */
 
-  var Component =
-  /*#__PURE__*/
-  function () {
+  var Component = /*#__PURE__*/function () {
     /**
      * A callback that is called when a component is ready. Does not have any
      * paramters and any callback value will be ignored.
         this.player_ = player = this; // eslint-disable-line
       } else {
         this.player_ = player;
-      } // Hold the reference to the parent component via `addChild` method
+      }
 
+      this.isDisposed_ = false; // Hold the reference to the parent component via `addChild` method
 
       this.parentComponent_ = null; // Make a copy of prototype.options_ to protect against overriding defaults
 
       this.children_ = [];
       this.childIndex_ = {};
       this.childNameIndex_ = {};
-      this.setTimeoutIds_ = new Set();
-      this.setIntervalIds_ = new Set();
-      this.rafIds_ = new Set();
+      var SetSham;
+
+      if (!window$3.Set) {
+        SetSham = /*#__PURE__*/function () {
+          function SetSham() {
+            this.set_ = {};
+          }
+
+          var _proto2 = SetSham.prototype;
+
+          _proto2.has = function has(key) {
+            return key in this.set_;
+          };
+
+          _proto2["delete"] = function _delete(key) {
+            var has = this.has(key);
+            delete this.set_[key];
+            return has;
+          };
+
+          _proto2.add = function add(key) {
+            this.set_[key] = 1;
+            return this;
+          };
+
+          _proto2.forEach = function forEach(callback, thisArg) {
+            for (var key in this.set_) {
+              callback.call(thisArg, key, key, this);
+            }
+          };
+
+          return SetSham;
+        }();
+      }
+
+      this.setTimeoutIds_ = window$3.Set ? new Set() : new SetSham();
+      this.setIntervalIds_ = window$3.Set ? new Set() : new SetSham();
+      this.rafIds_ = window$3.Set ? new Set() : new SetSham();
       this.clearingTimersOnDispose_ = false; // Add any child components in options
 
       if (options.initChildren !== false) {
     var _proto = Component.prototype;
 
     _proto.dispose = function dispose() {
+      // Bail out if the component has already been disposed.
+      if (this.isDisposed_) {
+        return;
+      }
       /**
        * Triggered when a `Component` is disposed.
        *
        * @type {EventTarget~Event}
        *
        * @property {boolean} [bubbles=false]
-       *           set to false so that the close event does not
+       *           set to false so that the dispose event does not
        *           bubble up
        */
+
+
       this.trigger({
         type: 'dispose',
         bubbles: false
-      }); // Dispose all children.
+      });
+      this.isDisposed_ = true; // Dispose all children.
 
       if (this.children_) {
         for (var i = this.children_.length - 1; i >= 0; i--) {
 
       this.player_ = null;
     }
+    /**
+     * Determine whether or not this component has been disposed.
+     *
+     * @return {boolean}
+     *         If the component has been disposed, will be `true`. Otherwise, `false`.
+     */
+    ;
+
+    _proto.isDisposed = function isDisposed() {
+      return Boolean(this.isDisposed_);
+    }
     /**
      * Return the {@link Player} that the `Component` has attached to.
      *
 
 
       if (typeof component.el === 'function' && component.el()) {
-        var childNodes = this.contentEl().children;
-        var refNode = childNodes[index] || null;
+        // If inserting before a component, insert before that component's element
+        var refNode = null;
+
+        if (this.children_[index + 1] && this.children_[index + 1].el_) {
+          refNode = this.children_[index + 1].el_;
+        }
+
         this.contentEl().insertBefore(component.el(), refNode);
       } // Return so it can stored on parent object if desired.
 
             pageY: event.touches[0].pageY
           }; // Record start time so we can detect a tap vs. "touch and hold"
 
-          touchStart = window$1.performance.now(); // Reset couldBeTap tracking
+          touchStart = window$3.performance.now(); // Reset couldBeTap tracking
 
           couldBeTap = true;
         }
 
         if (couldBeTap === true) {
           // Measure how long the touch lasted
-          var touchTime = window$1.performance.now() - touchStart; // Make sure the touch was less than the threshold to be considered a tap
+          var touchTime = window$3.performance.now() - touchStart; // Make sure the touch was less than the threshold to be considered a tap
 
           if (touchTime < touchTimeThreshold) {
             // Don't let browser turn this into a click
       var timeoutId;
       fn = bind(this, fn);
       this.clearTimersOnDispose_();
-      timeoutId = window$1.setTimeout(function () {
+      timeoutId = window$3.setTimeout(function () {
         if (_this2.setTimeoutIds_.has(timeoutId)) {
           _this2.setTimeoutIds_["delete"](timeoutId);
         }
     _proto.clearTimeout = function clearTimeout(timeoutId) {
       if (this.setTimeoutIds_.has(timeoutId)) {
         this.setTimeoutIds_["delete"](timeoutId);
-        window$1.clearTimeout(timeoutId);
+        window$3.clearTimeout(timeoutId);
       }
 
       return timeoutId;
     _proto.setInterval = function setInterval(fn, interval) {
       fn = bind(this, fn);
       this.clearTimersOnDispose_();
-      var intervalId = window$1.setInterval(fn, interval);
+      var intervalId = window$3.setInterval(fn, interval);
       this.setIntervalIds_.add(intervalId);
       return intervalId;
     }
     _proto.clearInterval = function clearInterval(intervalId) {
       if (this.setIntervalIds_.has(intervalId)) {
         this.setIntervalIds_["delete"](intervalId);
-        window$1.clearInterval(intervalId);
+        window$3.clearInterval(intervalId);
       }
 
       return intervalId;
 
       var id;
       fn = bind(this, fn);
-      id = window$1.requestAnimationFrame(function () {
+      id = window$3.requestAnimationFrame(function () {
         if (_this3.rafIds_.has(id)) {
           _this3.rafIds_["delete"](id);
         }
 
       if (this.rafIds_.has(id)) {
         this.rafIds_["delete"](id);
-        window$1.cancelAnimationFrame(id);
+        window$3.cancelAnimationFrame(id);
       }
 
       return id;
    */
 
 
-  Component.prototype.supportsRaf_ = typeof window$1.requestAnimationFrame === 'function' && typeof window$1.cancelAnimationFrame === 'function';
+  Component.prototype.supportsRaf_ = typeof window$3.requestAnimationFrame === 'function' && typeof window$3.cancelAnimationFrame === 'function';
   Component.registerComponent('Component', Component);
 
-  function _inheritsLoose(subClass, superClass) {
-    subClass.prototype = Object.create(superClass.prototype);
-    subClass.prototype.constructor = subClass;
-    subClass.__proto__ = superClass;
+  function _assertThisInitialized(self) {
+    if (self === void 0) {
+      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+    }
+
+    return self;
   }
 
-  function _setPrototypeOf(o, p) {
-    _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
-      o.__proto__ = p;
-      return o;
-    };
+  var assertThisInitialized = _assertThisInitialized;
 
-    return _setPrototypeOf(o, p);
-  }
+  var _typeof_1 = createCommonjsModule(function (module) {
+    function _typeof(obj) {
+      "@babel/helpers - typeof";
 
-  function isNativeReflectConstruct() {
-    if (typeof Reflect === "undefined" || !Reflect.construct) return false;
-    if (Reflect.construct.sham) return false;
-    if (typeof Proxy === "function") return true;
+      if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
+        module.exports = _typeof = function _typeof(obj) {
+          return typeof obj;
+        };
+      } else {
+        module.exports = _typeof = function _typeof(obj) {
+          return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+        };
+      }
 
-    try {
-      Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
-      return true;
-    } catch (e) {
-      return false;
+      return _typeof(obj);
     }
-  }
 
-  function _construct(Parent, args, Class) {
-    if (isNativeReflectConstruct()) {
-      _construct = Reflect.construct;
-    } else {
-      _construct = function _construct(Parent, args, Class) {
-        var a = [null];
-        a.push.apply(a, args);
-        var Constructor = Function.bind.apply(Parent, a);
-        var instance = new Constructor();
-        if (Class) _setPrototypeOf(instance, Class.prototype);
-        return instance;
+    module.exports = _typeof;
+  });
+
+  var getPrototypeOf = createCommonjsModule(function (module) {
+    function _getPrototypeOf(o) {
+      module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
+        return o.__proto__ || Object.getPrototypeOf(o);
       };
+      return _getPrototypeOf(o);
     }
 
-    return _construct.apply(null, arguments);
-  }
-
-  function _assertThisInitialized(self) {
-    if (self === void 0) {
-      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
-    }
+    module.exports = _getPrototypeOf;
+  });
 
-    return self;
+  function _inheritsLoose(subClass, superClass) {
+    subClass.prototype = Object.create(superClass.prototype);
+    subClass.prototype.constructor = subClass;
+    subClass.__proto__ = superClass;
   }
 
+  var inheritsLoose = _inheritsLoose;
+
   /**
    * @file browser.js
    * @module browser
    */
-  var USER_AGENT = window$1.navigator && window$1.navigator.userAgent || '';
+  var USER_AGENT = window$3.navigator && window$3.navigator.userAgent || '';
   var webkitVersionMap = /AppleWebKit\/([\d.]+)/i.exec(USER_AGENT);
   var appleWebkitVersion = webkitVersionMap ? parseFloat(webkitVersionMap.pop()) : null;
-  /**
-   * Whether or not this device is an iPad.
-   *
-   * @static
-   * @const
-   * @type {Boolean}
-   */
-
-  var IS_IPAD = /iPad/i.test(USER_AGENT);
-  /**
-   * Whether or not this device is an iPhone.
-   *
-   * @static
-   * @const
-   * @type {Boolean}
-   */
-  // The Facebook app's UIWebView identifies as both an iPhone and iPad, so
-  // to identify iPhones, we need to exclude iPads.
-  // http://artsy.github.io/blog/2012/10/18/the-perils-of-ios-user-agent-sniffing/
-
-  var IS_IPHONE = /iPhone/i.test(USER_AGENT) && !IS_IPAD;
   /**
    * Whether or not this device is an iPod.
    *
    */
 
   var IS_IPOD = /iPod/i.test(USER_AGENT);
-  /**
-   * Whether or not this is an iOS device.
-   *
-   * @static
-   * @const
-   * @type {Boolean}
-   */
-
-  var IS_IOS = IS_IPHONE || IS_IPAD || IS_IPOD;
   /**
    * The detected iOS version - or `null`.
    *
    * @type {Boolean}
    */
 
-  var IS_EDGE = /Edge/i.test(USER_AGENT);
+  var IS_EDGE = /Edg/i.test(USER_AGENT);
   /**
    * Whether or not this is Google Chrome.
    *
 
   var IS_SAFARI = /Safari/i.test(USER_AGENT) && !IS_CHROME && !IS_ANDROID && !IS_EDGE;
   /**
-   * Whether or not this is any flavor of Safari - including iOS.
+   * Whether or not this is a Windows machine.
    *
    * @static
    * @const
    * @type {Boolean}
    */
 
-  var IS_ANY_SAFARI = (IS_SAFARI || IS_IOS) && !IS_CHROME;
+  var IS_WINDOWS = /Windows/i.test(USER_AGENT);
   /**
-   * Whether or not this is a Windows machine.
+   * Whether or not this device is touch-enabled.
    *
    * @static
    * @const
    * @type {Boolean}
    */
 
-  var IS_WINDOWS = /Windows/i.test(USER_AGENT);
+  var TOUCH_ENABLED = isReal() && ('ontouchstart' in window$3 || window$3.navigator.maxTouchPoints || window$3.DocumentTouch && window$3.document instanceof window$3.DocumentTouch);
   /**
-   * Whether or not this device is touch-enabled.
+   * Whether or not this device is an iPad.
+   *
+   * @static
+   * @const
+   * @type {Boolean}
+   */
+
+  var IS_IPAD = /iPad/i.test(USER_AGENT) || IS_SAFARI && TOUCH_ENABLED && !/iPhone/i.test(USER_AGENT);
+  /**
+   * Whether or not this device is an iPhone.
+   *
+   * @static
+   * @const
+   * @type {Boolean}
+   */
+  // The Facebook app's UIWebView identifies as both an iPhone and iPad, so
+  // to identify iPhones, we need to exclude iPads.
+  // http://artsy.github.io/blog/2012/10/18/the-perils-of-ios-user-agent-sniffing/
+
+  var IS_IPHONE = /iPhone/i.test(USER_AGENT) && !IS_IPAD;
+  /**
+   * Whether or not this is an iOS device.
+   *
+   * @static
+   * @const
+   * @type {Boolean}
+   */
+
+  var IS_IOS = IS_IPHONE || IS_IPAD || IS_IPOD;
+  /**
+   * Whether or not this is any flavor of Safari - including iOS.
    *
    * @static
    * @const
    * @type {Boolean}
    */
 
-  var TOUCH_ENABLED = isReal() && ('ontouchstart' in window$1 || window$1.navigator.maxTouchPoints || window$1.DocumentTouch && window$1.document instanceof window$1.DocumentTouch);
+  var IS_ANY_SAFARI = (IS_SAFARI || IS_IOS) && !IS_CHROME;
 
   var browser = /*#__PURE__*/Object.freeze({
-    IS_IPAD: IS_IPAD,
-    IS_IPHONE: IS_IPHONE,
     IS_IPOD: IS_IPOD,
-    IS_IOS: IS_IOS,
     IOS_VERSION: IOS_VERSION,
     IS_ANDROID: IS_ANDROID,
     ANDROID_VERSION: ANDROID_VERSION,
     CHROME_VERSION: CHROME_VERSION,
     IE_VERSION: IE_VERSION,
     IS_SAFARI: IS_SAFARI,
-    IS_ANY_SAFARI: IS_ANY_SAFARI,
     IS_WINDOWS: IS_WINDOWS,
-    TOUCH_ENABLED: TOUCH_ENABLED
+    TOUCH_ENABLED: TOUCH_ENABLED,
+    IS_IPAD: IS_IPAD,
+    IS_IPHONE: IS_IPHONE,
+    IS_IOS: IS_IOS,
+    IS_ANY_SAFARI: IS_ANY_SAFARI
   });
 
   /**
     trackToJson_: trackToJson_
   };
 
-  function createCommonjsModule(fn, module) {
-       return module = { exports: {} }, fn(module, module.exports), module.exports;
-  }
-
   var keycode = createCommonjsModule(function (module, exports) {
     // Source: http://jsfiddle.net/vWx8V/
     // http://stackoverflow.com/questions/5603195/full-list-of-javascript-keycodes
       '[': 219,
       '\\': 220,
       ']': 221,
-      "'": 222 // Helper aliases
+      "'": 222
+    }; // Helper aliases
 
-    };
     var aliases = exports.aliases = {
       'windows': 91,
       '⇧': 16,
       'ins': 45,
       'del': 46,
       'cmd': 91
-      /*!
-       * Programatically add the following
-       */
-      // lower case chars
-
     };
+    /*!
+     * Programatically add the following
+     */
+    // lower case chars
 
     for (i = 97; i < 123; i++) {
       codes[String.fromCharCode(i)] = i - 32;
    * @extends Component
    */
 
-  var ModalDialog =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(ModalDialog, _Component);
+  var ModalDialog = /*#__PURE__*/function (_Component) {
+    inheritsLoose(ModalDialog, _Component);
 
     /**
      * Create an instance of this class.
     _proto.focusableEls_ = function focusableEls_() {
       var allChildren = this.el_.querySelectorAll('*');
       return Array.prototype.filter.call(allChildren, function (child) {
-        return (child instanceof window$1.HTMLAnchorElement || child instanceof window$1.HTMLAreaElement) && child.hasAttribute('href') || (child instanceof window$1.HTMLInputElement || child instanceof window$1.HTMLSelectElement || child instanceof window$1.HTMLTextAreaElement || child instanceof window$1.HTMLButtonElement) && !child.hasAttribute('disabled') || child instanceof window$1.HTMLIFrameElement || child instanceof window$1.HTMLObjectElement || child instanceof window$1.HTMLEmbedElement || child.hasAttribute('tabindex') && child.getAttribute('tabindex') !== -1 || child.hasAttribute('contenteditable');
+        return (child instanceof window$3.HTMLAnchorElement || child instanceof window$3.HTMLAreaElement) && child.hasAttribute('href') || (child instanceof window$3.HTMLInputElement || child instanceof window$3.HTMLSelectElement || child instanceof window$3.HTMLTextAreaElement || child instanceof window$3.HTMLButtonElement) && !child.hasAttribute('disabled') || child instanceof window$3.HTMLIFrameElement || child instanceof window$3.HTMLObjectElement || child instanceof window$3.HTMLEmbedElement || child.hasAttribute('tabindex') && child.getAttribute('tabindex') !== -1 || child.hasAttribute('contenteditable');
       });
     };
 
    * @extends EventTarget
    */
 
-  var TrackList =
-  /*#__PURE__*/
-  function (_EventTarget) {
-    _inheritsLoose(TrackList, _EventTarget);
+  var TrackList = /*#__PURE__*/function (_EventTarget) {
+    inheritsLoose(TrackList, _EventTarget);
 
     /**
      * Create an instance of this class
        * @instance
        */
 
-      Object.defineProperty(_assertThisInitialized(_this), 'length', {
+      Object.defineProperty(assertThisInitialized(_this), 'length', {
         get: function get() {
           return this.tracks_.length;
         }
    */
 
 
-  var AudioTrackList =
-  /*#__PURE__*/
-  function (_TrackList) {
-    _inheritsLoose(AudioTrackList, _TrackList);
+  var AudioTrackList = /*#__PURE__*/function (_TrackList) {
+    inheritsLoose(AudioTrackList, _TrackList);
 
     /**
      * Create an instance of this class.
    */
 
 
-  var VideoTrackList =
-  /*#__PURE__*/
-  function (_TrackList) {
-    _inheritsLoose(VideoTrackList, _TrackList);
+  var VideoTrackList = /*#__PURE__*/function (_TrackList) {
+    inheritsLoose(VideoTrackList, _TrackList);
 
     /**
      * Create an instance of this class.
        *         The current index of the selected {@link VideoTrack`}.
        */
 
-      Object.defineProperty(_assertThisInitialized(_this), 'selectedIndex', {
+      Object.defineProperty(assertThisInitialized(_this), 'selectedIndex', {
         get: function get() {
           for (var _i = 0; _i < this.length; _i++) {
             if (this[_i].selected) {
    * @extends TrackList
    */
 
-  var TextTrackList =
-  /*#__PURE__*/
-  function (_TrackList) {
-    _inheritsLoose(TextTrackList, _TrackList);
+  var TextTrackList = /*#__PURE__*/function (_TrackList) {
+    inheritsLoose(TextTrackList, _TrackList);
 
     function TextTrackList() {
       return _TrackList.apply(this, arguments) || this;
   /**
    * The current list of {@link HtmlTrackElement}s.
    */
-  var HtmlTrackElementList =
-  /*#__PURE__*/
-  function () {
+  var HtmlTrackElementList = /*#__PURE__*/function () {
     /**
      * Create an instance of this class.
      *
    *
    * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcuelist}
    */
-  var TextTrackCueList =
-  /*#__PURE__*/
-  function () {
+  var TextTrackCueList = /*#__PURE__*/function () {
     /**
      * Create an instance of this class..
      *
    * @abstract
    */
 
-  var Track =
-  /*#__PURE__*/
-  function (_EventTarget) {
-    _inheritsLoose(Track, _EventTarget);
+  var Track = /*#__PURE__*/function (_EventTarget) {
+    inheritsLoose(Track, _EventTarget);
 
     /**
      * Create an instance of this class.
        */
 
       var _loop = function _loop(key) {
-        Object.defineProperty(_assertThisInitialized(_this), key, {
+        Object.defineProperty(assertThisInitialized(_this), key, {
           get: function get() {
             return trackProps[key];
           },
     }
 
     if (!details.protocol) {
-      details.protocol = window$1.location.protocol;
+      details.protocol = window$3.location.protocol;
     }
 
     if (addToBody) {
    * @param    {string} url
    *           The url to check.
    *
+   * @param    {Object} [winLoc]
+   *           the domain to check the url against, defaults to window.location
+   *
+   * @param    {string} [winLoc.protocol]
+   *           The window location protocol defaults to window.location.protocol
+   *
+   * @param    {string} [winLoc.host]
+   *           The window location host defaults to window.location.host
+   *
    * @return   {boolean}
    *           Whether it is a cross domain request or not.
    */
 
-  var isCrossOrigin = function isCrossOrigin(url) {
-    var winLoc = window$1.location;
+  var isCrossOrigin = function isCrossOrigin(url, winLoc) {
+    if (winLoc === void 0) {
+      winLoc = window$3.location;
+    }
+
     var urlInfo = parseUrl(url); // IE8 protocol relative urls will return ':' for protocol
 
     var srcProtocol = urlInfo.protocol === ':' ? winLoc.protocol : urlInfo.protocol; // Check if url is for another domain/origin
     fn === window.setTimeout || fn === window.alert || fn === window.confirm || fn === window.prompt);
   }
 
-  /* eslint no-invalid-this: 1 */
+  /**
+   * @license
+   * slighly modified parse-headers 2.0.2 <https://github.com/kesla/parse-headers/>
+   * Copyright (c) 2014 David Björklund
+   * Available under the MIT license
+   * <https://github.com/kesla/parse-headers/blob/master/LICENCE>
+   */
 
-  var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';
-  var slice = Array.prototype.slice;
-  var toStr = Object.prototype.toString;
-  var funcType = '[object Function]';
 
-  var implementation = function bind(that) {
-    var target = this;
+  var parseHeaders = function parseHeaders(headers) {
+    var result = {};
 
-    if (typeof target !== 'function' || toStr.call(target) !== funcType) {
-      throw new TypeError(ERROR_MESSAGE + target);
+    if (!headers) {
+      return result;
     }
 
-    var args = slice.call(arguments, 1);
-    var bound;
-
-    var binder = function binder() {
-      if (this instanceof bound) {
-        var result = target.apply(this, args.concat(slice.call(arguments)));
-
-        if (Object(result) === result) {
-          return result;
-        }
+    headers.trim().split('\n').forEach(function (row) {
+      var index = row.indexOf(':');
+      var key = row.slice(0, index).trim().toLowerCase();
+      var value = row.slice(index + 1).trim();
 
-        return this;
+      if (typeof result[key] === 'undefined') {
+        result[key] = value;
+      } else if (Array.isArray(result[key])) {
+        result[key].push(value);
       } else {
-        return target.apply(that, args.concat(slice.call(arguments)));
+        result[key] = [result[key], value];
       }
-    };
-
-    var boundLength = Math.max(0, target.length - args.length);
-    var boundArgs = [];
-
-    for (var i = 0; i < boundLength; i++) {
-      boundArgs.push('$' + i);
-    }
+    });
+    return result;
+  };
 
-    bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder);
+  var xhr = createXHR; // Allow use of default import syntax in TypeScript
 
-    if (target.prototype) {
-      var Empty = function Empty() {};
+  var default_1 = createXHR;
+  createXHR.XMLHttpRequest = window$3.XMLHttpRequest || noop;
+  createXHR.XDomainRequest = "withCredentials" in new createXHR.XMLHttpRequest() ? createXHR.XMLHttpRequest : window$3.XDomainRequest;
+  forEachArray(["get", "put", "post", "patch", "head", "delete"], function (method) {
+    createXHR[method === "delete" ? "del" : method] = function (uri, options, callback) {
+      options = initParams(uri, options, callback);
+      options.method = method.toUpperCase();
+      return _createXHR(options);
+    };
+  });
 
-      Empty.prototype = target.prototype;
-      bound.prototype = new Empty();
-      Empty.prototype = null;
+  function forEachArray(array, iterator) {
+    for (var i = 0; i < array.length; i++) {
+      iterator(array[i]);
     }
+  }
 
-    return bound;
-  };
+  function isEmpty(obj) {
+    for (var i in obj) {
+      if (obj.hasOwnProperty(i)) return false;
+    }
 
-  var functionBind = Function.prototype.bind || implementation;
+    return true;
+  }
 
-  var toStr$1 = Object.prototype.toString;
+  function initParams(uri, options, callback) {
+    var params = uri;
 
-  var isArguments = function isArguments(value) {
-    var str = toStr$1.call(value);
-    var isArgs = str === '[object Arguments]';
+    if (isFunction_1(options)) {
+      callback = options;
 
-    if (!isArgs) {
-      isArgs = str !== '[object Array]' && value !== null && typeof value === 'object' && typeof value.length === 'number' && value.length >= 0 && toStr$1.call(value.callee) === '[object Function]';
+      if (typeof uri === "string") {
+        params = {
+          uri: uri
+        };
+      }
+    } else {
+      params = _extends_1({}, options, {
+        uri: uri
+      });
     }
 
-    return isArgs;
-  };
+    params.callback = callback;
+    return params;
+  }
 
-  var keysShim;
+  function createXHR(uri, options, callback) {
+    options = initParams(uri, options, callback);
+    return _createXHR(options);
+  }
 
-  if (!Object.keys) {
-    // modified from https://github.com/es-shims/es5-shim
-    var has = Object.prototype.hasOwnProperty;
-    var toStr$2 = Object.prototype.toString;
-    var isArgs = isArguments; // eslint-disable-line global-require
+  function _createXHR(options) {
+    if (typeof options.callback === "undefined") {
+      throw new Error("callback argument missing");
+    }
 
-    var isEnumerable = Object.prototype.propertyIsEnumerable;
-    var hasDontEnumBug = !isEnumerable.call({
-      toString: null
-    }, 'toString');
-    var hasProtoEnumBug = isEnumerable.call(function () {}, 'prototype');
-    var dontEnums = ['toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'];
+    var called = false;
 
-    var equalsConstructorPrototype = function equalsConstructorPrototype(o) {
-      var ctor = o.constructor;
-      return ctor && ctor.prototype === o;
+    var callback = function cbOnce(err, response, body) {
+      if (!called) {
+        called = true;
+        options.callback(err, response, body);
+      }
     };
 
-    var excludedKeys = {
-      $applicationCache: true,
-      $console: true,
-      $external: true,
-      $frame: true,
-      $frameElement: true,
-      $frames: true,
-      $innerHeight: true,
-      $innerWidth: true,
-      $onmozfullscreenchange: true,
-      $onmozfullscreenerror: true,
-      $outerHeight: true,
-      $outerWidth: true,
-      $pageXOffset: true,
-      $pageYOffset: true,
-      $parent: true,
-      $scrollLeft: true,
-      $scrollTop: true,
-      $scrollX: true,
-      $scrollY: true,
-      $self: true,
-      $webkitIndexedDB: true,
-      $webkitStorageInfo: true,
-      $window: true
-    };
+    function readystatechange() {
+      if (xhr.readyState === 4) {
+        setTimeout(loadFunc, 0);
+      }
+    }
 
-    var hasAutomationEqualityBug = function () {
-      /* global window */
-      if (typeof window === 'undefined') {
-        return false;
+    function getBody() {
+      // Chrome with requestType=blob throws errors arround when even testing access to responseText
+      var body = undefined;
+
+      if (xhr.response) {
+        body = xhr.response;
+      } else {
+        body = xhr.responseText || getXml(xhr);
       }
 
-      for (var k in window) {
+      if (isJson) {
         try {
-          if (!excludedKeys['$' + k] && has.call(window, k) && window[k] !== null && typeof window[k] === 'object') {
-            try {
-              equalsConstructorPrototype(window[k]);
-            } catch (e) {
-              return true;
-            }
-          }
-        } catch (e) {
-          return true;
-        }
+          body = JSON.parse(body);
+        } catch (e) {}
       }
 
-      return false;
-    }();
+      return body;
+    }
 
-    var equalsConstructorPrototypeIfNotBuggy = function equalsConstructorPrototypeIfNotBuggy(o) {
-      /* global window */
-      if (typeof window === 'undefined' || !hasAutomationEqualityBug) {
-        return equalsConstructorPrototype(o);
-      }
+    function errorFunc(evt) {
+      clearTimeout(timeoutTimer);
 
-      try {
-        return equalsConstructorPrototype(o);
-      } catch (e) {
-        return false;
+      if (!(evt instanceof Error)) {
+        evt = new Error("" + (evt || "Unknown XMLHttpRequest Error"));
       }
-    };
 
-    keysShim = function keys(object) {
-      var isObject = object !== null && typeof object === 'object';
-      var isFunction = toStr$2.call(object) === '[object Function]';
-      var isArguments = isArgs(object);
-      var isString = isObject && toStr$2.call(object) === '[object String]';
-      var theKeys = [];
+      evt.statusCode = 0;
+      return callback(evt, failureResponse);
+    } // will load the data & process the response in a special response object
 
-      if (!isObject && !isFunction && !isArguments) {
-        throw new TypeError('Object.keys called on a non-object');
-      }
 
-      var skipProto = hasProtoEnumBug && isFunction;
+    function loadFunc() {
+      if (aborted) return;
+      var status;
+      clearTimeout(timeoutTimer);
 
-      if (isString && object.length > 0 && !has.call(object, 0)) {
-        for (var i = 0; i < object.length; ++i) {
-          theKeys.push(String(i));
-        }
+      if (options.useXDR && xhr.status === undefined) {
+        //IE8 CORS GET successful response doesn't have a status field, but body is fine
+        status = 200;
+      } else {
+        status = xhr.status === 1223 ? 204 : xhr.status;
       }
 
-      if (isArguments && object.length > 0) {
-        for (var j = 0; j < object.length; ++j) {
-          theKeys.push(String(j));
+      var response = failureResponse;
+      var err = null;
+
+      if (status !== 0) {
+        response = {
+          body: getBody(),
+          statusCode: status,
+          method: method,
+          headers: {},
+          url: uri,
+          rawRequest: xhr
+        };
+
+        if (xhr.getAllResponseHeaders) {
+          //remember xhr can in fact be XDR for CORS in IE
+          response.headers = parseHeaders(xhr.getAllResponseHeaders());
         }
       } else {
-        for (var name in object) {
-          if (!(skipProto && name === 'prototype') && has.call(object, name)) {
-            theKeys.push(String(name));
-          }
-        }
+        err = new Error("Internal XMLHttpRequest Error");
       }
 
-      if (hasDontEnumBug) {
-        var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object);
+      return callback(err, response, response.body);
+    }
+
+    var xhr = options.xhr || null;
 
-        for (var k = 0; k < dontEnums.length; ++k) {
-          if (!(skipConstructor && dontEnums[k] === 'constructor') && has.call(object, dontEnums[k])) {
-            theKeys.push(dontEnums[k]);
-          }
-        }
+    if (!xhr) {
+      if (options.cors || options.useXDR) {
+        xhr = new createXHR.XDomainRequest();
+      } else {
+        xhr = new createXHR.XMLHttpRequest();
       }
+    }
 
-      return theKeys;
+    var key;
+    var aborted;
+    var uri = xhr.url = options.uri || options.url;
+    var method = xhr.method = options.method || "GET";
+    var body = options.body || options.data;
+    var headers = xhr.headers = options.headers || {};
+    var sync = !!options.sync;
+    var isJson = false;
+    var timeoutTimer;
+    var failureResponse = {
+      body: undefined,
+      headers: {},
+      statusCode: 0,
+      method: method,
+      url: uri,
+      rawRequest: xhr
     };
-  }
 
-  var implementation$1 = keysShim;
-
-  var slice$1 = Array.prototype.slice;
-  var origKeys = Object.keys;
-  var keysShim$1 = origKeys ? function keys(o) {
-    return origKeys(o);
-  } : implementation$1;
-  var originalKeys = Object.keys;
-
-  keysShim$1.shim = function shimObjectKeys() {
-    if (Object.keys) {
-      var keysWorksWithArguments = function () {
-        // Safari 5.0 bug
-        var args = Object.keys(arguments);
-        return args && args.length === arguments.length;
-      }(1, 2);
+    if ("json" in options && options.json !== false) {
+      isJson = true;
+      headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json"); //Don't override existing accept header declared by user
 
-      if (!keysWorksWithArguments) {
-        Object.keys = function keys(object) {
-          // eslint-disable-line func-name-matching
-          if (isArguments(object)) {
-            return originalKeys(slice$1.call(object));
-          }
+      if (method !== "GET" && method !== "HEAD") {
+        headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json"); //Don't override existing accept header declared by user
 
-          return originalKeys(object);
-        };
+        body = JSON.stringify(options.json === true ? body : options.json);
       }
-    } else {
-      Object.keys = keysShim$1;
     }
 
-    return Object.keys || keysShim$1;
-  };
-
-  var objectKeys = keysShim$1;
-
-  var hasSymbols = typeof Symbol === 'function' && typeof Symbol('foo') === 'symbol';
-  var toStr$3 = Object.prototype.toString;
-  var concat = Array.prototype.concat;
-  var origDefineProperty = Object.defineProperty;
-
-  var isFunction$1 = function isFunction(fn) {
-    return typeof fn === 'function' && toStr$3.call(fn) === '[object Function]';
-  };
+    xhr.onreadystatechange = readystatechange;
+    xhr.onload = loadFunc;
+    xhr.onerror = errorFunc; // IE9 must have onprogress be set to a unique function.
 
-  var arePropertyDescriptorsSupported = function arePropertyDescriptorsSupported() {
-    var obj = {};
+    xhr.onprogress = function () {// IE must die
+    };
 
-    try {
-      origDefineProperty(obj, 'x', {
-        enumerable: false,
-        value: obj
-      }); // eslint-disable-next-line no-unused-vars, no-restricted-syntax
+    xhr.onabort = function () {
+      aborted = true;
+    };
 
-      for (var _ in obj) {
-        // jscs:ignore disallowUnusedVariables
-        return false;
-      }
+    xhr.ontimeout = errorFunc;
+    xhr.open(method, uri, !sync, options.username, options.password); //has to be after open
 
-      return obj.x === obj;
-    } catch (e) {
-      /* this is IE 8. */
-      return false;
-    }
-  };
+    if (!sync) {
+      xhr.withCredentials = !!options.withCredentials;
+    } // Cannot set timeout with sync request
+    // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
+    // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
 
-  var supportsDescriptors = origDefineProperty && arePropertyDescriptorsSupported();
 
-  var defineProperty = function defineProperty(object, name, value, predicate) {
-    if (name in object && (!isFunction$1(predicate) || !predicate())) {
-      return;
-    }
+    if (!sync && options.timeout > 0) {
+      timeoutTimer = setTimeout(function () {
+        if (aborted) return;
+        aborted = true; //IE9 may still call readystatechange
 
-    if (supportsDescriptors) {
-      origDefineProperty(object, name, {
-        configurable: true,
-        enumerable: false,
-        value: value,
-        writable: true
-      });
-    } else {
-      object[name] = value;
+        xhr.abort("timeout");
+        var e = new Error("XMLHttpRequest timeout");
+        e.code = "ETIMEDOUT";
+        errorFunc(e);
+      }, options.timeout);
     }
-  };
 
-  var defineProperties = function defineProperties(object, map) {
-    var predicates = arguments.length > 2 ? arguments[2] : {};
-    var props = objectKeys(map);
-
-    if (hasSymbols) {
-      props = concat.call(props, Object.getOwnPropertySymbols(map));
+    if (xhr.setRequestHeader) {
+      for (key in headers) {
+        if (headers.hasOwnProperty(key)) {
+          xhr.setRequestHeader(key, headers[key]);
+        }
+      }
+    } else if (options.headers && !isEmpty(options.headers)) {
+      throw new Error("Headers cannot be set on an XDomainRequest object");
     }
 
-    for (var i = 0; i < props.length; i += 1) {
-      defineProperty(object, props[i], map[props[i]], predicates[props[i]]);
+    if ("responseType" in options) {
+      xhr.responseType = options.responseType;
     }
-  };
 
-  defineProperties.supportsDescriptors = !!supportsDescriptors;
-  var defineProperties_1 = defineProperties;
-
-  /* globals
-       Set,
-       Map,
-       WeakSet,
-       WeakMap,
-
-       Promise,
-
-       Symbol,
-       Proxy,
+    if ("beforeSend" in options && typeof options.beforeSend === "function") {
+      options.beforeSend(xhr);
+    } // Microsoft Edge browser sends "undefined" when send is called with undefined value.
+    // XMLHttpRequest spec says to pass null as body to indicate no body
+    // See https://github.com/naugtur/xhr/issues/100.
 
-       Atomics,
-       SharedArrayBuffer,
 
-       ArrayBuffer,
-       DataView,
-       Uint8Array,
-       Float32Array,
-       Float64Array,
-       Int8Array,
-       Int16Array,
-       Int32Array,
-       Uint8ClampedArray,
-       Uint16Array,
-       Uint32Array,
-  */
+    xhr.send(body || null);
+    return xhr;
+  }
 
-  var undefined$1; // eslint-disable-line no-shadow-restricted-names
-
-  var ThrowTypeError = Object.getOwnPropertyDescriptor ? function () {
-    return Object.getOwnPropertyDescriptor(arguments, 'callee').get;
-  }() : function () {
-    throw new TypeError();
-  };
-  var hasSymbols$1 = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol';
-
-  var getProto = Object.getPrototypeOf || function (x) {
-    return x.__proto__;
-  }; // eslint-disable-line no-proto
-
-  var generatorFunction =  undefined$1;
-
-  var asyncFunction =  undefined$1;
-
-  var asyncGenFunction =  undefined$1;
-  var TypedArray = typeof Uint8Array === 'undefined' ? undefined$1 : getProto(Uint8Array);
-  var INTRINSICS = {
-    '$ %Array%': Array,
-    '$ %ArrayBuffer%': typeof ArrayBuffer === 'undefined' ? undefined$1 : ArrayBuffer,
-    '$ %ArrayBufferPrototype%': typeof ArrayBuffer === 'undefined' ? undefined$1 : ArrayBuffer.prototype,
-    '$ %ArrayIteratorPrototype%': hasSymbols$1 ? getProto([][Symbol.iterator]()) : undefined$1,
-    '$ %ArrayPrototype%': Array.prototype,
-    '$ %ArrayProto_entries%': Array.prototype.entries,
-    '$ %ArrayProto_forEach%': Array.prototype.forEach,
-    '$ %ArrayProto_keys%': Array.prototype.keys,
-    '$ %ArrayProto_values%': Array.prototype.values,
-    '$ %AsyncFromSyncIteratorPrototype%': undefined$1,
-    '$ %AsyncFunction%': asyncFunction,
-    '$ %AsyncFunctionPrototype%':  undefined$1,
-    '$ %AsyncGenerator%':  undefined$1,
-    '$ %AsyncGeneratorFunction%': asyncGenFunction,
-    '$ %AsyncGeneratorPrototype%':  undefined$1,
-    '$ %AsyncIteratorPrototype%':  undefined$1,
-    '$ %Atomics%': typeof Atomics === 'undefined' ? undefined$1 : Atomics,
-    '$ %Boolean%': Boolean,
-    '$ %BooleanPrototype%': Boolean.prototype,
-    '$ %DataView%': typeof DataView === 'undefined' ? undefined$1 : DataView,
-    '$ %DataViewPrototype%': typeof DataView === 'undefined' ? undefined$1 : DataView.prototype,
-    '$ %Date%': Date,
-    '$ %DatePrototype%': Date.prototype,
-    '$ %decodeURI%': decodeURI,
-    '$ %decodeURIComponent%': decodeURIComponent,
-    '$ %encodeURI%': encodeURI,
-    '$ %encodeURIComponent%': encodeURIComponent,
-    '$ %Error%': Error,
-    '$ %ErrorPrototype%': Error.prototype,
-    '$ %eval%': eval,
-    // eslint-disable-line no-eval
-    '$ %EvalError%': EvalError,
-    '$ %EvalErrorPrototype%': EvalError.prototype,
-    '$ %Float32Array%': typeof Float32Array === 'undefined' ? undefined$1 : Float32Array,
-    '$ %Float32ArrayPrototype%': typeof Float32Array === 'undefined' ? undefined$1 : Float32Array.prototype,
-    '$ %Float64Array%': typeof Float64Array === 'undefined' ? undefined$1 : Float64Array,
-    '$ %Float64ArrayPrototype%': typeof Float64Array === 'undefined' ? undefined$1 : Float64Array.prototype,
-    '$ %Function%': Function,
-    '$ %FunctionPrototype%': Function.prototype,
-    '$ %Generator%':  undefined$1,
-    '$ %GeneratorFunction%': generatorFunction,
-    '$ %GeneratorPrototype%':  undefined$1,
-    '$ %Int8Array%': typeof Int8Array === 'undefined' ? undefined$1 : Int8Array,
-    '$ %Int8ArrayPrototype%': typeof Int8Array === 'undefined' ? undefined$1 : Int8Array.prototype,
-    '$ %Int16Array%': typeof Int16Array === 'undefined' ? undefined$1 : Int16Array,
-    '$ %Int16ArrayPrototype%': typeof Int16Array === 'undefined' ? undefined$1 : Int8Array.prototype,
-    '$ %Int32Array%': typeof Int32Array === 'undefined' ? undefined$1 : Int32Array,
-    '$ %Int32ArrayPrototype%': typeof Int32Array === 'undefined' ? undefined$1 : Int32Array.prototype,
-    '$ %isFinite%': isFinite,
-    '$ %isNaN%': isNaN,
-    '$ %IteratorPrototype%': hasSymbols$1 ? getProto(getProto([][Symbol.iterator]())) : undefined$1,
-    '$ %JSON%': JSON,
-    '$ %JSONParse%': JSON.parse,
-    '$ %Map%': typeof Map === 'undefined' ? undefined$1 : Map,
-    '$ %MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols$1 ? undefined$1 : getProto(new Map()[Symbol.iterator]()),
-    '$ %MapPrototype%': typeof Map === 'undefined' ? undefined$1 : Map.prototype,
-    '$ %Math%': Math,
-    '$ %Number%': Number,
-    '$ %NumberPrototype%': Number.prototype,
-    '$ %Object%': Object,
-    '$ %ObjectPrototype%': Object.prototype,
-    '$ %ObjProto_toString%': Object.prototype.toString,
-    '$ %ObjProto_valueOf%': Object.prototype.valueOf,
-    '$ %parseFloat%': parseFloat,
-    '$ %parseInt%': parseInt,
-    '$ %Promise%': typeof Promise === 'undefined' ? undefined$1 : Promise,
-    '$ %PromisePrototype%': typeof Promise === 'undefined' ? undefined$1 : Promise.prototype,
-    '$ %PromiseProto_then%': typeof Promise === 'undefined' ? undefined$1 : Promise.prototype.then,
-    '$ %Promise_all%': typeof Promise === 'undefined' ? undefined$1 : Promise.all,
-    '$ %Promise_reject%': typeof Promise === 'undefined' ? undefined$1 : Promise.reject,
-    '$ %Promise_resolve%': typeof Promise === 'undefined' ? undefined$1 : Promise.resolve,
-    '$ %Proxy%': typeof Proxy === 'undefined' ? undefined$1 : Proxy,
-    '$ %RangeError%': RangeError,
-    '$ %RangeErrorPrototype%': RangeError.prototype,
-    '$ %ReferenceError%': ReferenceError,
-    '$ %ReferenceErrorPrototype%': ReferenceError.prototype,
-    '$ %Reflect%': typeof Reflect === 'undefined' ? undefined$1 : Reflect,
-    '$ %RegExp%': RegExp,
-    '$ %RegExpPrototype%': RegExp.prototype,
-    '$ %Set%': typeof Set === 'undefined' ? undefined$1 : Set,
-    '$ %SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols$1 ? undefined$1 : getProto(new Set()[Symbol.iterator]()),
-    '$ %SetPrototype%': typeof Set === 'undefined' ? undefined$1 : Set.prototype,
-    '$ %SharedArrayBuffer%': typeof SharedArrayBuffer === 'undefined' ? undefined$1 : SharedArrayBuffer,
-    '$ %SharedArrayBufferPrototype%': typeof SharedArrayBuffer === 'undefined' ? undefined$1 : SharedArrayBuffer.prototype,
-    '$ %String%': String,
-    '$ %StringIteratorPrototype%': hasSymbols$1 ? getProto(''[Symbol.iterator]()) : undefined$1,
-    '$ %StringPrototype%': String.prototype,
-    '$ %Symbol%': hasSymbols$1 ? Symbol : undefined$1,
-    '$ %SymbolPrototype%': hasSymbols$1 ? Symbol.prototype : undefined$1,
-    '$ %SyntaxError%': SyntaxError,
-    '$ %SyntaxErrorPrototype%': SyntaxError.prototype,
-    '$ %ThrowTypeError%': ThrowTypeError,
-    '$ %TypedArray%': TypedArray,
-    '$ %TypedArrayPrototype%': TypedArray ? TypedArray.prototype : undefined$1,
-    '$ %TypeError%': TypeError,
-    '$ %TypeErrorPrototype%': TypeError.prototype,
-    '$ %Uint8Array%': typeof Uint8Array === 'undefined' ? undefined$1 : Uint8Array,
-    '$ %Uint8ArrayPrototype%': typeof Uint8Array === 'undefined' ? undefined$1 : Uint8Array.prototype,
-    '$ %Uint8ClampedArray%': typeof Uint8ClampedArray === 'undefined' ? undefined$1 : Uint8ClampedArray,
-    '$ %Uint8ClampedArrayPrototype%': typeof Uint8ClampedArray === 'undefined' ? undefined$1 : Uint8ClampedArray.prototype,
-    '$ %Uint16Array%': typeof Uint16Array === 'undefined' ? undefined$1 : Uint16Array,
-    '$ %Uint16ArrayPrototype%': typeof Uint16Array === 'undefined' ? undefined$1 : Uint16Array.prototype,
-    '$ %Uint32Array%': typeof Uint32Array === 'undefined' ? undefined$1 : Uint32Array,
-    '$ %Uint32ArrayPrototype%': typeof Uint32Array === 'undefined' ? undefined$1 : Uint32Array.prototype,
-    '$ %URIError%': URIError,
-    '$ %URIErrorPrototype%': URIError.prototype,
-    '$ %WeakMap%': typeof WeakMap === 'undefined' ? undefined$1 : WeakMap,
-    '$ %WeakMapPrototype%': typeof WeakMap === 'undefined' ? undefined$1 : WeakMap.prototype,
-    '$ %WeakSet%': typeof WeakSet === 'undefined' ? undefined$1 : WeakSet,
-    '$ %WeakSetPrototype%': typeof WeakSet === 'undefined' ? undefined$1 : WeakSet.prototype
-  };
-
-  var GetIntrinsic = function GetIntrinsic(name, allowMissing) {
-    if (arguments.length > 1 && typeof allowMissing !== 'boolean') {
-      throw new TypeError('"allowMissing" argument must be a boolean');
-    }
-
-    var key = '$ ' + name;
-
-    if (!(key in INTRINSICS)) {
-      throw new SyntaxError('intrinsic ' + name + ' does not exist!');
-    } // istanbul ignore if // hopefully this is impossible to test :-)
-
-
-    if (typeof INTRINSICS[key] === 'undefined' && !allowMissing) {
-      throw new TypeError('intrinsic ' + name + ' exists, but is not available. Please file an issue!');
-    }
-
-    return INTRINSICS[key];
-  };
-
-  var src = functionBind.call(Function.call, Object.prototype.hasOwnProperty);
-
-  var $TypeError = GetIntrinsic('%TypeError%');
-  var $SyntaxError = GetIntrinsic('%SyntaxError%');
-  var predicates = {
-    // https://ecma-international.org/ecma-262/6.0/#sec-property-descriptor-specification-type
-    'Property Descriptor': function isPropertyDescriptor(ES, Desc) {
-      if (ES.Type(Desc) !== 'Object') {
-        return false;
+  function getXml(xhr) {
+    // xhr.responseXML will throw Exception "InvalidStateError" or "DOMException"
+    // See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseXML.
+    try {
+      if (xhr.responseType === "document") {
+        return xhr.responseXML;
       }
 
-      var allowed = {
-        '[[Configurable]]': true,
-        '[[Enumerable]]': true,
-        '[[Get]]': true,
-        '[[Set]]': true,
-        '[[Value]]': true,
-        '[[Writable]]': true
-      };
+      var firefoxBugTakenEffect = xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror";
 
-      for (var key in Desc) {
-        // eslint-disable-line
-        if (src(Desc, key) && !allowed[key]) {
-          return false;
-        }
+      if (xhr.responseType === "" && !firefoxBugTakenEffect) {
+        return xhr.responseXML;
       }
+    } catch (e) {}
 
-      var isData = src(Desc, '[[Value]]');
-      var IsAccessor = src(Desc, '[[Get]]') || src(Desc, '[[Set]]');
+    return null;
+  }
 
-      if (isData && IsAccessor) {
-        throw new $TypeError('Property Descriptors may not be both accessor and data descriptors');
-      }
-
-      return true;
-    }
-  };
-
-  var assertRecord = function assertRecord(ES, recordType, argumentName, value) {
-    var predicate = predicates[recordType];
-
-    if (typeof predicate !== 'function') {
-      throw new $SyntaxError('unknown record type: ' + recordType);
-    }
-
-    if (!predicate(ES, value)) {
-      throw new $TypeError(argumentName + ' must be a ' + recordType);
-    }
-
-    console.log(predicate(ES, value), value);
-  };
-
-  var _isNaN = Number.isNaN || function isNaN(a) {
-    return a !== a;
-  };
-
-  var $isNaN = Number.isNaN || function (a) {
-    return a !== a;
-  };
-
-  var _isFinite = Number.isFinite || function (x) {
-    return typeof x === 'number' && !$isNaN(x) && x !== Infinity && x !== -Infinity;
-  };
-
-  var sign = function sign(number) {
-    return number >= 0 ? 1 : -1;
-  };
-
-  var mod = function mod(number, modulo) {
-    var remain = number % modulo;
-    return Math.floor(remain >= 0 ? remain : remain + modulo);
-  };
-
-  var fnToStr = Function.prototype.toString;
-  var constructorRegex = /^\s*class\b/;
-
-  var isES6ClassFn = function isES6ClassFunction(value) {
-    try {
-      var fnStr = fnToStr.call(value);
-      return constructorRegex.test(fnStr);
-    } catch (e) {
-      return false; // not a function
-    }
-  };
-
-  var tryFunctionObject = function tryFunctionToStr(value) {
-    try {
-      if (isES6ClassFn(value)) {
-        return false;
-      }
-
-      fnToStr.call(value);
-      return true;
-    } catch (e) {
-      return false;
-    }
-  };
-
-  var toStr$4 = Object.prototype.toString;
-  var fnClass = '[object Function]';
-  var genClass = '[object GeneratorFunction]';
-  var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
-
-  var isCallable = function isCallable(value) {
-    if (!value) {
-      return false;
-    }
-
-    if (typeof value !== 'function' && typeof value !== 'object') {
-      return false;
-    }
-
-    if (typeof value === 'function' && !value.prototype) {
-      return true;
-    }
-
-    if (hasToStringTag) {
-      return tryFunctionObject(value);
-    }
-
-    if (isES6ClassFn(value)) {
-      return false;
-    }
-
-    var strClass = toStr$4.call(value);
-    return strClass === fnClass || strClass === genClass;
-  };
-
-  var isPrimitive = function isPrimitive(value) {
-    return value === null || typeof value !== 'function' && typeof value !== 'object';
-  };
-
-  var toStr$5 = Object.prototype.toString; // http://ecma-international.org/ecma-262/5.1/#sec-8.12.8
-
-  var ES5internalSlots = {
-    '[[DefaultValue]]': function DefaultValue(O) {
-      var actualHint;
-
-      if (arguments.length > 1) {
-        actualHint = arguments[1];
-      } else {
-        actualHint = toStr$5.call(O) === '[object Date]' ? String : Number;
-      }
-
-      if (actualHint === String || actualHint === Number) {
-        var methods = actualHint === String ? ['toString', 'valueOf'] : ['valueOf', 'toString'];
-        var value, i;
-
-        for (i = 0; i < methods.length; ++i) {
-          if (isCallable(O[methods[i]])) {
-            value = O[methods[i]]();
-
-            if (isPrimitive(value)) {
-              return value;
-            }
-          }
-        }
-
-        throw new TypeError('No default value');
-      }
-
-      throw new TypeError('invalid [[DefaultValue]] hint supplied');
-    }
-  }; // http://ecma-international.org/ecma-262/5.1/#sec-9.1
-
-  var es5 = function ToPrimitive(input) {
-    if (isPrimitive(input)) {
-      return input;
-    }
-
-    if (arguments.length > 1) {
-      return ES5internalSlots['[[DefaultValue]]'](input, arguments[1]);
-    }
-
-    return ES5internalSlots['[[DefaultValue]]'](input);
-  };
-
-  var $Object = GetIntrinsic('%Object%');
-  var $TypeError$1 = GetIntrinsic('%TypeError%');
-  var $String = GetIntrinsic('%String%'); // https://es5.github.io/#x9
-
-  var ES5 = {
-    ToPrimitive: es5,
-    ToBoolean: function ToBoolean(value) {
-      return !!value;
-    },
-    ToNumber: function ToNumber(value) {
-      return +value; // eslint-disable-line no-implicit-coercion
-    },
-    ToInteger: function ToInteger(value) {
-      var number = this.ToNumber(value);
-
-      if (_isNaN(number)) {
-        return 0;
-      }
-
-      if (number === 0 || !_isFinite(number)) {
-        return number;
-      }
-
-      return sign(number) * Math.floor(Math.abs(number));
-    },
-    ToInt32: function ToInt32(x) {
-      return this.ToNumber(x) >> 0;
-    },
-    ToUint32: function ToUint32(x) {
-      return this.ToNumber(x) >>> 0;
-    },
-    ToUint16: function ToUint16(value) {
-      var number = this.ToNumber(value);
-
-      if (_isNaN(number) || number === 0 || !_isFinite(number)) {
-        return 0;
-      }
-
-      var posInt = sign(number) * Math.floor(Math.abs(number));
-      return mod(posInt, 0x10000);
-    },
-    ToString: function ToString(value) {
-      return $String(value);
-    },
-    ToObject: function ToObject(value) {
-      this.CheckObjectCoercible(value);
-      return $Object(value);
-    },
-    CheckObjectCoercible: function CheckObjectCoercible(value, optMessage) {
-      /* jshint eqnull:true */
-      if (value == null) {
-        throw new $TypeError$1(optMessage || 'Cannot call method on ' + value);
-      }
-
-      return value;
-    },
-    IsCallable: isCallable,
-    SameValue: function SameValue(x, y) {
-      if (x === y) {
-        // 0 === -0, but they are not identical.
-        if (x === 0) {
-          return 1 / x === 1 / y;
-        }
-
-        return true;
-      }
-
-      return _isNaN(x) && _isNaN(y);
-    },
-    // https://www.ecma-international.org/ecma-262/5.1/#sec-8
-    Type: function Type(x) {
-      if (x === null) {
-        return 'Null';
-      }
-
-      if (typeof x === 'undefined') {
-        return 'Undefined';
-      }
-
-      if (typeof x === 'function' || typeof x === 'object') {
-        return 'Object';
-      }
-
-      if (typeof x === 'number') {
-        return 'Number';
-      }
-
-      if (typeof x === 'boolean') {
-        return 'Boolean';
-      }
-
-      if (typeof x === 'string') {
-        return 'String';
-      }
-    },
-    // https://ecma-international.org/ecma-262/6.0/#sec-property-descriptor-specification-type
-    IsPropertyDescriptor: function IsPropertyDescriptor(Desc) {
-      if (this.Type(Desc) !== 'Object') {
-        return false;
-      }
-
-      var allowed = {
-        '[[Configurable]]': true,
-        '[[Enumerable]]': true,
-        '[[Get]]': true,
-        '[[Set]]': true,
-        '[[Value]]': true,
-        '[[Writable]]': true
-      };
-
-      for (var key in Desc) {
-        // eslint-disable-line
-        if (src(Desc, key) && !allowed[key]) {
-          return false;
-        }
-      }
-
-      var isData = src(Desc, '[[Value]]');
-      var IsAccessor = src(Desc, '[[Get]]') || src(Desc, '[[Set]]');
-
-      if (isData && IsAccessor) {
-        throw new $TypeError$1('Property Descriptors may not be both accessor and data descriptors');
-      }
-
-      return true;
-    },
-    // https://ecma-international.org/ecma-262/5.1/#sec-8.10.1
-    IsAccessorDescriptor: function IsAccessorDescriptor(Desc) {
-      if (typeof Desc === 'undefined') {
-        return false;
-      }
-
-      assertRecord(this, 'Property Descriptor', 'Desc', Desc);
-
-      if (!src(Desc, '[[Get]]') && !src(Desc, '[[Set]]')) {
-        return false;
-      }
-
-      return true;
-    },
-    // https://ecma-international.org/ecma-262/5.1/#sec-8.10.2
-    IsDataDescriptor: function IsDataDescriptor(Desc) {
-      if (typeof Desc === 'undefined') {
-        return false;
-      }
-
-      assertRecord(this, 'Property Descriptor', 'Desc', Desc);
-
-      if (!src(Desc, '[[Value]]') && !src(Desc, '[[Writable]]')) {
-        return false;
-      }
-
-      return true;
-    },
-    // https://ecma-international.org/ecma-262/5.1/#sec-8.10.3
-    IsGenericDescriptor: function IsGenericDescriptor(Desc) {
-      if (typeof Desc === 'undefined') {
-        return false;
-      }
-
-      assertRecord(this, 'Property Descriptor', 'Desc', Desc);
-
-      if (!this.IsAccessorDescriptor(Desc) && !this.IsDataDescriptor(Desc)) {
-        return true;
-      }
-
-      return false;
-    },
-    // https://ecma-international.org/ecma-262/5.1/#sec-8.10.4
-    FromPropertyDescriptor: function FromPropertyDescriptor(Desc) {
-      if (typeof Desc === 'undefined') {
-        return Desc;
-      }
-
-      assertRecord(this, 'Property Descriptor', 'Desc', Desc);
-
-      if (this.IsDataDescriptor(Desc)) {
-        return {
-          value: Desc['[[Value]]'],
-          writable: !!Desc['[[Writable]]'],
-          enumerable: !!Desc['[[Enumerable]]'],
-          configurable: !!Desc['[[Configurable]]']
-        };
-      } else if (this.IsAccessorDescriptor(Desc)) {
-        return {
-          get: Desc['[[Get]]'],
-          set: Desc['[[Set]]'],
-          enumerable: !!Desc['[[Enumerable]]'],
-          configurable: !!Desc['[[Configurable]]']
-        };
-      } else {
-        throw new $TypeError$1('FromPropertyDescriptor must be called with a fully populated Property Descriptor');
-      }
-    },
-    // https://ecma-international.org/ecma-262/5.1/#sec-8.10.5
-    ToPropertyDescriptor: function ToPropertyDescriptor(Obj) {
-      if (this.Type(Obj) !== 'Object') {
-        throw new $TypeError$1('ToPropertyDescriptor requires an object');
-      }
-
-      var desc = {};
-
-      if (src(Obj, 'enumerable')) {
-        desc['[[Enumerable]]'] = this.ToBoolean(Obj.enumerable);
-      }
-
-      if (src(Obj, 'configurable')) {
-        desc['[[Configurable]]'] = this.ToBoolean(Obj.configurable);
-      }
-
-      if (src(Obj, 'value')) {
-        desc['[[Value]]'] = Obj.value;
-      }
-
-      if (src(Obj, 'writable')) {
-        desc['[[Writable]]'] = this.ToBoolean(Obj.writable);
-      }
-
-      if (src(Obj, 'get')) {
-        var getter = Obj.get;
-
-        if (typeof getter !== 'undefined' && !this.IsCallable(getter)) {
-          throw new TypeError('getter must be a function');
-        }
-
-        desc['[[Get]]'] = getter;
-      }
-
-      if (src(Obj, 'set')) {
-        var setter = Obj.set;
-
-        if (typeof setter !== 'undefined' && !this.IsCallable(setter)) {
-          throw new $TypeError$1('setter must be a function');
-        }
-
-        desc['[[Set]]'] = setter;
-      }
-
-      if ((src(desc, '[[Get]]') || src(desc, '[[Set]]')) && (src(desc, '[[Value]]') || src(desc, '[[Writable]]'))) {
-        throw new $TypeError$1('Invalid property descriptor. Cannot both specify accessors and a value or writable attribute');
-      }
-
-      return desc;
-    }
-  };
-  var es5$1 = ES5;
-
-  var replace = functionBind.call(Function.call, String.prototype.replace);
-  /* eslint-disable no-control-regex */
-
-  var leftWhitespace = /^[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]+/;
-  var rightWhitespace = /[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]+$/;
-  /* eslint-enable no-control-regex */
-
-  var implementation$2 = function trim() {
-    var S = es5$1.ToString(es5$1.CheckObjectCoercible(this));
-    return replace(replace(S, leftWhitespace, ''), rightWhitespace, '');
-  };
-
-  var zeroWidthSpace = "\u200B";
-
-  var polyfill = function getPolyfill() {
-    if (String.prototype.trim && zeroWidthSpace.trim() === zeroWidthSpace) {
-      return String.prototype.trim;
-    }
-
-    return implementation$2;
-  };
-
-  var shim = function shimStringTrim() {
-    var polyfill$1 = polyfill();
-    defineProperties_1(String.prototype, {
-      trim: polyfill$1
-    }, {
-      trim: function testTrim() {
-        return String.prototype.trim !== polyfill$1;
-      }
-    });
-    return polyfill$1;
-  };
-
-  var boundTrim = functionBind.call(Function.call, polyfill());
-  defineProperties_1(boundTrim, {
-    getPolyfill: polyfill,
-    implementation: implementation$2,
-    shim: shim
-  });
-  var string_prototype_trim = boundTrim;
-
-  var toStr$6 = Object.prototype.toString;
-  var hasOwnProperty = Object.prototype.hasOwnProperty;
-
-  var forEachArray = function forEachArray(array, iterator, receiver) {
-    for (var i = 0, len = array.length; i < len; i++) {
-      if (hasOwnProperty.call(array, i)) {
-        if (receiver == null) {
-          iterator(array[i], i, array);
-        } else {
-          iterator.call(receiver, array[i], i, array);
-        }
-      }
-    }
-  };
-
-  var forEachString = function forEachString(string, iterator, receiver) {
-    for (var i = 0, len = string.length; i < len; i++) {
-      // no such thing as a sparse string.
-      if (receiver == null) {
-        iterator(string.charAt(i), i, string);
-      } else {
-        iterator.call(receiver, string.charAt(i), i, string);
-      }
-    }
-  };
-
-  var forEachObject = function forEachObject(object, iterator, receiver) {
-    for (var k in object) {
-      if (hasOwnProperty.call(object, k)) {
-        if (receiver == null) {
-          iterator(object[k], k, object);
-        } else {
-          iterator.call(receiver, object[k], k, object);
-        }
-      }
-    }
-  };
-
-  var forEach = function forEach(list, iterator, thisArg) {
-    if (!isCallable(iterator)) {
-      throw new TypeError('iterator must be a function');
-    }
-
-    var receiver;
-
-    if (arguments.length >= 3) {
-      receiver = thisArg;
-    }
-
-    if (toStr$6.call(list) === '[object Array]') {
-      forEachArray(list, iterator, receiver);
-    } else if (typeof list === 'string') {
-      forEachString(list, iterator, receiver);
-    } else {
-      forEachObject(list, iterator, receiver);
-    }
-  };
-
-  var forEach_1 = forEach;
-
-  var isArray = function isArray(arg) {
-    return Object.prototype.toString.call(arg) === '[object Array]';
-  };
-
-  var parseHeaders = function parseHeaders(headers) {
-    if (!headers) return {};
-    var result = {};
-    forEach_1(string_prototype_trim(headers).split('\n'), function (row) {
-      var index = row.indexOf(':'),
-          key = string_prototype_trim(row.slice(0, index)).toLowerCase(),
-          value = string_prototype_trim(row.slice(index + 1));
-
-      if (typeof result[key] === 'undefined') {
-        result[key] = value;
-      } else if (isArray(result[key])) {
-        result[key].push(value);
-      } else {
-        result[key] = [result[key], value];
-      }
-    });
-    return result;
-  };
-
-  var immutable = extend;
-  var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
-
-  function extend() {
-    var target = {};
-
-    for (var i = 0; i < arguments.length; i++) {
-      var source = arguments[i];
-
-      for (var key in source) {
-        if (hasOwnProperty$1.call(source, key)) {
-          target[key] = source[key];
-        }
-      }
-    }
-
-    return target;
-  }
-
-  var xhr = createXHR;
-  createXHR.XMLHttpRequest = window$1.XMLHttpRequest || noop;
-  createXHR.XDomainRequest = "withCredentials" in new createXHR.XMLHttpRequest() ? createXHR.XMLHttpRequest : window$1.XDomainRequest;
-  forEachArray$1(["get", "put", "post", "patch", "head", "delete"], function (method) {
-    createXHR[method === "delete" ? "del" : method] = function (uri, options, callback) {
-      options = initParams(uri, options, callback);
-      options.method = method.toUpperCase();
-      return _createXHR(options);
-    };
-  });
-
-  function forEachArray$1(array, iterator) {
-    for (var i = 0; i < array.length; i++) {
-      iterator(array[i]);
-    }
-  }
-
-  function isEmpty(obj) {
-    for (var i in obj) {
-      if (obj.hasOwnProperty(i)) return false;
-    }
-
-    return true;
-  }
-
-  function initParams(uri, options, callback) {
-    var params = uri;
-
-    if (isFunction_1(options)) {
-      callback = options;
-
-      if (typeof uri === "string") {
-        params = {
-          uri: uri
-        };
-      }
-    } else {
-      params = immutable(options, {
-        uri: uri
-      });
-    }
-
-    params.callback = callback;
-    return params;
-  }
-
-  function createXHR(uri, options, callback) {
-    options = initParams(uri, options, callback);
-    return _createXHR(options);
-  }
-
-  function _createXHR(options) {
-    if (typeof options.callback === "undefined") {
-      throw new Error("callback argument missing");
-    }
-
-    var called = false;
-
-    var callback = function cbOnce(err, response, body) {
-      if (!called) {
-        called = true;
-        options.callback(err, response, body);
-      }
-    };
-
-    function readystatechange() {
-      if (xhr.readyState === 4) {
-        setTimeout(loadFunc, 0);
-      }
-    }
-
-    function getBody() {
-      // Chrome with requestType=blob throws errors arround when even testing access to responseText
-      var body = undefined;
-
-      if (xhr.response) {
-        body = xhr.response;
-      } else {
-        body = xhr.responseText || getXml(xhr);
-      }
-
-      if (isJson) {
-        try {
-          body = JSON.parse(body);
-        } catch (e) {}
-      }
-
-      return body;
-    }
-
-    function errorFunc(evt) {
-      clearTimeout(timeoutTimer);
-
-      if (!(evt instanceof Error)) {
-        evt = new Error("" + (evt || "Unknown XMLHttpRequest Error"));
-      }
-
-      evt.statusCode = 0;
-      return callback(evt, failureResponse);
-    } // will load the data & process the response in a special response object
-
-
-    function loadFunc() {
-      if (aborted) return;
-      var status;
-      clearTimeout(timeoutTimer);
-
-      if (options.useXDR && xhr.status === undefined) {
-        //IE8 CORS GET successful response doesn't have a status field, but body is fine
-        status = 200;
-      } else {
-        status = xhr.status === 1223 ? 204 : xhr.status;
-      }
-
-      var response = failureResponse;
-      var err = null;
-
-      if (status !== 0) {
-        response = {
-          body: getBody(),
-          statusCode: status,
-          method: method,
-          headers: {},
-          url: uri,
-          rawRequest: xhr
-        };
-
-        if (xhr.getAllResponseHeaders) {
-          //remember xhr can in fact be XDR for CORS in IE
-          response.headers = parseHeaders(xhr.getAllResponseHeaders());
-        }
-      } else {
-        err = new Error("Internal XMLHttpRequest Error");
-      }
-
-      return callback(err, response, response.body);
-    }
-
-    var xhr = options.xhr || null;
-
-    if (!xhr) {
-      if (options.cors || options.useXDR) {
-        xhr = new createXHR.XDomainRequest();
-      } else {
-        xhr = new createXHR.XMLHttpRequest();
-      }
-    }
-
-    var key;
-    var aborted;
-    var uri = xhr.url = options.uri || options.url;
-    var method = xhr.method = options.method || "GET";
-    var body = options.body || options.data;
-    var headers = xhr.headers = options.headers || {};
-    var sync = !!options.sync;
-    var isJson = false;
-    var timeoutTimer;
-    var failureResponse = {
-      body: undefined,
-      headers: {},
-      statusCode: 0,
-      method: method,
-      url: uri,
-      rawRequest: xhr
-    };
-
-    if ("json" in options && options.json !== false) {
-      isJson = true;
-      headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json"); //Don't override existing accept header declared by user
-
-      if (method !== "GET" && method !== "HEAD") {
-        headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json"); //Don't override existing accept header declared by user
-
-        body = JSON.stringify(options.json === true ? body : options.json);
-      }
-    }
-
-    xhr.onreadystatechange = readystatechange;
-    xhr.onload = loadFunc;
-    xhr.onerror = errorFunc; // IE9 must have onprogress be set to a unique function.
-
-    xhr.onprogress = function () {// IE must die
-    };
-
-    xhr.onabort = function () {
-      aborted = true;
-    };
-
-    xhr.ontimeout = errorFunc;
-    xhr.open(method, uri, !sync, options.username, options.password); //has to be after open
-
-    if (!sync) {
-      xhr.withCredentials = !!options.withCredentials;
-    } // Cannot set timeout with sync request
-    // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
-    // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
-
-
-    if (!sync && options.timeout > 0) {
-      timeoutTimer = setTimeout(function () {
-        if (aborted) return;
-        aborted = true; //IE9 may still call readystatechange
-
-        xhr.abort("timeout");
-        var e = new Error("XMLHttpRequest timeout");
-        e.code = "ETIMEDOUT";
-        errorFunc(e);
-      }, options.timeout);
-    }
-
-    if (xhr.setRequestHeader) {
-      for (key in headers) {
-        if (headers.hasOwnProperty(key)) {
-          xhr.setRequestHeader(key, headers[key]);
-        }
-      }
-    } else if (options.headers && !isEmpty(options.headers)) {
-      throw new Error("Headers cannot be set on an XDomainRequest object");
-    }
-
-    if ("responseType" in options) {
-      xhr.responseType = options.responseType;
-    }
-
-    if ("beforeSend" in options && typeof options.beforeSend === "function") {
-      options.beforeSend(xhr);
-    } // Microsoft Edge browser sends "undefined" when send is called with undefined value.
-    // XMLHttpRequest spec says to pass null as body to indicate no body
-    // See https://github.com/naugtur/xhr/issues/100.
-
-
-    xhr.send(body || null);
-    return xhr;
-  }
-
-  function getXml(xhr) {
-    if (xhr.responseType === "document") {
-      return xhr.responseXML;
-    }
-
-    var firefoxBugTakenEffect = xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror";
-
-    if (xhr.responseType === "" && !firefoxBugTakenEffect) {
-      return xhr.responseXML;
-    }
-
-    return null;
-  }
-
-  function noop() {}
+  function noop() {}
+  xhr["default"] = default_1;
 
   /**
    * Takes a webvtt file contents and parses it into cues
    */
 
   var parseCues = function parseCues(srcContent, track) {
-    var parser = new window$1.WebVTT.Parser(window$1, window$1.vttjs, window$1.WebVTT.StringDecoder());
+    var parser = new window$3.WebVTT.Parser(window$3, window$3.vttjs, window$3.WebVTT.StringDecoder());
     var errors = [];
 
     parser.oncue = function (cue) {
     parser.parse(srcContent);
 
     if (errors.length > 0) {
-      if (window$1.console && window$1.console.groupCollapsed) {
-        window$1.console.groupCollapsed("Text Track parsing errors for " + track.src);
+      if (window$3.console && window$3.console.groupCollapsed) {
+        window$3.console.groupCollapsed("Text Track parsing errors for " + track.src);
       }
 
       errors.forEach(function (error) {
         return log.error(error);
       });
 
-      if (window$1.console && window$1.console.groupEnd) {
-        window$1.console.groupEnd();
+      if (window$3.console && window$3.console.groupEnd) {
+        window$3.console.groupEnd();
       }
     }
 
       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 window$1.WebVTT !== 'function') {
+      if (typeof window$3.WebVTT !== 'function') {
         if (track.tech_) {
           // to prevent use before define eslint error, we define loadHandler
           // as a let here
    */
 
 
-  var TextTrack =
-  /*#__PURE__*/
-  function (_Track) {
-    _inheritsLoose(TextTrack, _Track);
+  var TextTrack = /*#__PURE__*/function (_Track) {
+    inheritsLoose(TextTrack, _Track);
 
     /**
      * Create an instance of this class.
       _this.tech_ = settings.tech;
       _this.cues_ = [];
       _this.activeCues_ = [];
+      _this.preload_ = _this.tech_.preloadTextTracks !== false;
       var cues = new TextTrackCueList(_this.cues_);
       var activeCues = new TextTrackCueList(_this.activeCues_);
       var changed = false;
-      var timeupdateHandler = bind(_assertThisInitialized(_this), function () {
+      var timeupdateHandler = bind(assertThisInitialized(_this), function () {
         // Accessing this.activeCues for the side-effects of updating itself
         // due to its nature as a getter function. Do not remove or cues will
         // stop updating!
         }, true);
       }
 
-      Object.defineProperties(_assertThisInitialized(_this), {
+      Object.defineProperties(assertThisInitialized(_this), {
         /**
          * @memberof TextTrack
          * @member {boolean} default
 
             mode = newMode;
 
+            if (!this.preload_ && mode !== 'disabled' && this.cues.length === 0) {
+              // On-demand load.
+              loadTrack(this.src, this);
+            }
+
             if (mode !== 'disabled') {
               this.tech_.ready(function () {
                 _this2.tech_.on('timeupdate', timeupdateHandler);
 
       if (settings.src) {
         _this.src = settings.src;
-        loadTrack(settings.src, _assertThisInitialized(_this));
+
+        if (!_this.preload_) {
+          // Tracks will load on-demand.
+          // Act like we're loaded for other purposes.
+          _this.loaded_ = true;
+        }
+
+        if (_this.preload_ || default_ || settings.kind !== 'subtitles' && settings.kind !== 'captions') {
+          loadTrack(_this.src, assertThisInitialized(_this));
+        }
       } else {
         _this.loaded_ = true;
       }
     _proto.addCue = function addCue(originalCue) {
       var cue = originalCue;
 
-      if (window$1.vttjs && !(originalCue instanceof window$1.vttjs.VTTCue)) {
-        cue = new window$1.vttjs.VTTCue(originalCue.startTime, originalCue.endTime, originalCue.text);
+      if (window$3.vttjs && !(originalCue instanceof window$3.vttjs.VTTCue)) {
+        cue = new window$3.vttjs.VTTCue(originalCue.startTime, originalCue.endTime, originalCue.text);
 
         for (var prop in originalCue) {
           if (!(prop in cue)) {
    * @extends Track
    */
 
-  var AudioTrack =
-  /*#__PURE__*/
-  function (_Track) {
-    _inheritsLoose(AudioTrack, _Track);
+  var AudioTrack = /*#__PURE__*/function (_Track) {
+    inheritsLoose(AudioTrack, _Track);
 
     /**
      * Create an instance of this class.
        * @fires VideoTrack#selectedchange
        */
 
-      Object.defineProperty(_assertThisInitialized(_this), 'enabled', {
+      Object.defineProperty(assertThisInitialized(_this), 'enabled', {
         get: function get() {
           return enabled;
         },
    * @extends Track
    */
 
-  var VideoTrack =
-  /*#__PURE__*/
-  function (_Track) {
-    _inheritsLoose(VideoTrack, _Track);
+  var VideoTrack = /*#__PURE__*/function (_Track) {
+    inheritsLoose(VideoTrack, _Track);
 
     /**
      * Create an instance of this class.
        * @fires VideoTrack#selectedchange
        */
 
-      Object.defineProperty(_assertThisInitialized(_this), 'selected', {
+      Object.defineProperty(assertThisInitialized(_this), 'selected', {
         get: function get() {
           return selected;
         },
    * @extends EventTarget
    */
 
-  var HTMLTrackElement =
-  /*#__PURE__*/
-  function (_EventTarget) {
-    _inheritsLoose(HTMLTrackElement, _EventTarget);
+  var HTMLTrackElement = /*#__PURE__*/function (_EventTarget) {
+    inheritsLoose(HTMLTrackElement, _EventTarget);
 
     /**
      * Create an instance of this class.
       _this.srclang = track.language;
       _this.label = track.label;
       _this["default"] = track["default"];
-      Object.defineProperties(_assertThisInitialized(_this), {
+      Object.defineProperties(assertThisInitialized(_this), {
         /**
          * @memberof HTMLTrackElement
          * @member {HTMLTrackElement~ReadyState} readyState
 
         _this.trigger({
           type: 'load',
-          target: _assertThisInitialized(_this)
+          target: assertThisInitialized(_this)
         });
       });
       return _this;
       privateName: 'remoteTextTrackEls_'
     }
   };
-  var ALL = mergeOptions(NORMAL, REMOTE);
-  REMOTE.names = Object.keys(REMOTE);
+
+  var ALL = _extends_1({}, NORMAL, REMOTE);
+
+  REMOTE.names = Object.keys(REMOTE);
   NORMAL.names = Object.keys(NORMAL);
   ALL.names = [].concat(REMOTE.names).concat(NORMAL.names);
 
   /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
   /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
   var _objCreate = Object.create || function () {
     function F() {}
 
       return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + (f | 0) / 1000;
     }
 
-    var m = input.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/);
+    var m = input.match(/^(\d+):(\d{1,2})(:\d{1,2})?\.(\d{3})/);
 
     if (!m) {
       return null;
             settings.alt(k, vals0, ["auto"]);
 
             if (vals.length === 2) {
-              settings.alt("lineAlign", vals[1], ["start", "middle", "end"]);
+              settings.alt("lineAlign", vals[1], ["start", "center", "end"]);
             }
 
             break;
             settings.percent(k, vals[0]);
 
             if (vals.length === 2) {
-              settings.alt("positionAlign", vals[1], ["start", "middle", "end"]);
+              settings.alt("positionAlign", vals[1], ["start", "center", "end"]);
             }
 
             break;
             break;
 
           case "align":
-            settings.alt(k, v, ["start", "middle", "end", "left", "right"]);
+            settings.alt(k, v, ["start", "center", "end", "left", "right"]);
             break;
         }
       }, /:/, /\s/); // Apply default values for any missing fields.
 
       cue.region = settings.get("region", null);
       cue.vertical = settings.get("vertical", "");
-      cue.line = settings.get("line", "auto");
+
+      try {
+        cue.line = settings.get("line", "auto");
+      } catch (e) {}
+
       cue.lineAlign = settings.get("lineAlign", "start");
       cue.snapToLines = settings.get("snapToLines", true);
-      cue.size = settings.get("size", 100);
-      cue.align = settings.get("align", "middle");
-      cue.position = settings.get("position", {
-        start: 0,
-        left: 0,
-        middle: 50,
-        end: 100,
-        right: 100
-      }, cue.align);
+      cue.size = settings.get("size", 100); // Safari still uses the old middle value and won't accept center
+
+      try {
+        cue.align = settings.get("align", "center");
+      } catch (e) {
+        cue.align = settings.get("align", "middle");
+      }
+
+      try {
+        cue.position = settings.get("position", "auto");
+      } catch (e) {
+        cue.position = settings.get("position", {
+          start: 0,
+          left: 0,
+          center: 50,
+          middle: 50,
+          end: 100,
+          right: 100
+        }, cue.align);
+      }
+
       cue.positionAlign = settings.get("positionAlign", {
         start: "start",
         left: "start",
-        middle: "middle",
+        center: "center",
+        middle: "center",
         end: "end",
         right: "end"
       }, cue.align);
     consumeCueSettings(input, cue);
   }
 
-  var ESCAPE = {
-    "&amp;": "&",
-    "&lt;": "<",
-    "&gt;": ">",
-    "&lrm;": "\u200E",
-    "&rlm;": "\u200F",
-    "&nbsp;": "\xA0"
-  };
+  var TEXTAREA_ELEMENT = document.createElement("textarea");
   var TAG_NAME = {
     c: "span",
     i: "i",
     rt: "rt",
     v: "span",
     lang: "span"
+  }; // 5.1 default text color
+  // 5.2 default text background color is equivalent to text color with bg_ prefix
+
+  var DEFAULT_COLOR_CLASS = {
+    white: 'rgba(255,255,255,1)',
+    lime: 'rgba(0,255,0,1)',
+    cyan: 'rgba(0,255,255,1)',
+    red: 'rgba(255,0,0,1)',
+    yellow: 'rgba(255,255,0,1)',
+    magenta: 'rgba(255,0,255,1)',
+    blue: 'rgba(0,0,255,1)',
+    black: 'rgba(0,0,0,1)'
   };
   var TAG_ANNOTATION = {
     v: "title",
       // the tag.
 
       return consume(m[1] ? m[1] : m[2]);
-    } // Unescape a string 's'.
-
-
-    function unescape1(e) {
-      return ESCAPE[e];
     }
 
     function unescape(s) {
-      while (m = s.match(/&(amp|lt|gt|lrm|rlm|nbsp);/)) {
-        s = s.replace(m[0], unescape1);
-      }
-
+      TEXTAREA_ELEMENT.innerHTML = s;
+      s = TEXTAREA_ELEMENT.textContent;
+      TEXTAREA_ELEMENT.textContent = "";
       return s;
     }
 
       }
 
       var element = window.document.createElement(tagName);
-      element.localName = tagName;
       var name = TAG_ANNOTATION[type];
 
       if (name && annotation) {
 
 
         if (m[2]) {
-          node.className = m[2].substr(1).replace('.', ' ');
+          var classes = m[2].split('.');
+          classes.forEach(function (cl) {
+            var bgColor = /^bg_/.test(cl); // slice out `bg_` if it's a background color
+
+            var colorName = bgColor ? cl.slice(3) : cl;
+
+            if (DEFAULT_COLOR_CLASS.hasOwnProperty(colorName)) {
+              var propName = bgColor ? 'background-color' : 'color';
+              var propValue = DEFAULT_COLOR_CLASS[colorName];
+              node.style[propName] = propValue;
+            }
+          });
+          node.className = classes.join(' ');
         } // Append the node to the current node, and enter the scope of the new
         // node.
 
     };
     this.applyStyles(styles, this.cueDiv); // Create an absolutely positioned div that will be used to position the cue
     // div. Note, all WebVTT cue-setting alignments are equivalent to the CSS
-    // mirrors of them except "middle" which is "center" in CSS.
+    // mirrors of them except middle instead of center on Safari.
 
     this.div = window.document.createElement("div");
     styles = {
         textPos = cue.position;
         break;
 
-      case "middle":
+      case "center":
         textPos = cue.position - cue.size / 2;
         break;
 
       var calculatedPercentage = boxPosition.lineHeight / containerBox.height * 100;
 
       switch (cue.lineAlign) {
-        case "middle":
+        case "center":
           linePos -= calculatedPercentage / 2;
           break;
 
                 continue;
               }
 
-              self.cue = new (self.vttjs.VTTCue || self.window.VTTCue)(0, 0, "");
+              self.cue = new (self.vttjs.VTTCue || self.window.VTTCue)(0, 0, ""); // Safari still uses the old middle value and won't accept center
+
+              try {
+                self.cue.align = "center";
+              } catch (e) {
+                self.cue.align = "middle";
+              }
+
               self.state = "CUE"; // 30-39 - Check if self line contains an optional identifier or timing data.
 
               if (line.indexOf("-->") === -1) {
                 self.cue.text += "\n";
               }
 
-              self.cue.text += line;
+              self.cue.text += line.replace(/\u2028/g, '\n').replace(/u2029/g, '\n');
               continue;
 
             case "BADCUE":
   };
   var alignSetting = {
     "start": 1,
-    "middle": 1,
+    "center": 1,
     "end": 1,
     "left": 1,
-    "right": 1
+    "right": 1,
+    "auto": 1,
+    "line-left": 1,
+    "line-right": 1
   };
 
   function findDirectionSetting(value) {
     var _snapToLines = true;
     var _line = "auto";
     var _lineAlign = "start";
-    var _position = 50;
-    var _positionAlign = "middle";
-    var _size = 50;
-    var _align = "middle";
+    var _position = "auto";
+    var _positionAlign = "auto";
+    var _size = 100;
+    var _align = "center";
     Object.defineProperties(this, {
       "id": {
         enumerable: true,
           var setting = findDirectionSetting(value); // Have to check for false because the setting an be an empty string.
 
           if (setting === false) {
-            throw new SyntaxError("An invalid or illegal string was specified.");
+            throw new SyntaxError("Vertical: an invalid or illegal direction string was specified.");
           }
 
           _vertical = setting;
         },
         set: function set(value) {
           if (typeof value !== "number" && value !== autoKeyword) {
-            throw new SyntaxError("An invalid number or illegal string was specified.");
+            throw new SyntaxError("Line: an invalid number or illegal string was specified.");
           }
 
           _line = value;
           var setting = findAlignSetting(value);
 
           if (!setting) {
-            throw new SyntaxError("An invalid or illegal string was specified.");
+            console.warn("lineAlign: an invalid or illegal string was specified.");
+          } else {
+            _lineAlign = setting;
+            this.hasBeenReset = true;
           }
-
-          _lineAlign = setting;
-          this.hasBeenReset = true;
         }
       },
       "position": {
           var setting = findAlignSetting(value);
 
           if (!setting) {
-            throw new SyntaxError("An invalid or illegal string was specified.");
+            console.warn("positionAlign: an invalid or illegal string was specified.");
+          } else {
+            _positionAlign = setting;
+            this.hasBeenReset = true;
           }
-
-          _positionAlign = setting;
-          this.hasBeenReset = true;
         }
       },
       "size": {
           var setting = findAlignSetting(value);
 
           if (!setting) {
-            throw new SyntaxError("An invalid or illegal string was specified.");
+            throw new SyntaxError("align: an invalid or illegal alignment string was specified.");
           }
 
           _align = setting;
           var setting = findScrollSetting(value); // Have to check for false as an empty string is a legal value.
 
           if (setting === false) {
-            throw new SyntaxError("An invalid or illegal string was specified.");
+            console.warn("Scroll: an invalid or illegal string was specified.");
+          } else {
+            _scroll = setting;
           }
-
-          _scroll = setting;
         }
       }
     });
       VTTCue: vttcue,
       VTTRegion: vttregion
     };
-    window$1.vttjs = vttjs;
-    window$1.WebVTT = vttjs.WebVTT;
+    window$3.vttjs = vttjs;
+    window$3.WebVTT = vttjs.WebVTT;
     var cueShim = vttjs.VTTCue;
     var regionShim = vttjs.VTTRegion;
-    var nativeVTTCue = window$1.VTTCue;
-    var nativeVTTRegion = window$1.VTTRegion;
+    var nativeVTTCue = window$3.VTTCue;
+    var nativeVTTRegion = window$3.VTTRegion;
 
     vttjs.shim = function () {
-      window$1.VTTCue = cueShim;
-      window$1.VTTRegion = regionShim;
+      window$3.VTTCue = cueShim;
+      window$3.VTTRegion = regionShim;
     };
 
     vttjs.restore = function () {
-      window$1.VTTCue = nativeVTTCue;
-      window$1.VTTRegion = nativeVTTRegion;
+      window$3.VTTCue = nativeVTTCue;
+      window$3.VTTRegion = nativeVTTRegion;
     };
 
-    if (!window$1.VTTCue) {
+    if (!window$3.VTTCue) {
       vttjs.shim();
     }
   });
    */
 
 
-  var Tech =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(Tech, _Component);
+  var Tech = /*#__PURE__*/function (_Component) {
+    inheritsLoose(Tech, _Component);
 
     /**
     * Create an instance of this Tech.
         _this.emulateTextTracks();
       }
 
+      _this.preloadTextTracks = options.preloadTextTracks !== false;
       _this.autoRemoteTextTracks_ = new ALL.text.ListClass();
 
       _this.initTrackListeners(); // Turn on component tap events only if not using native controls
     _proto.addWebVttScript_ = function addWebVttScript_() {
       var _this5 = this;
 
-      if (window$1.WebVTT) {
+      if (window$3.WebVTT) {
         return;
       } // Initially, Tech.el_ is a child of a dummy-div wait until the Component system
       // signals that the Tech is ready at which point Tech.el_ is part of the DOM
         }); // but have not loaded yet and we set it to true before the inject so that
         // we don't overwrite the injected window.WebVTT if it loads right away
 
-        window$1.WebVTT = true;
+        window$3.WebVTT = true;
         this.el().parentNode.appendChild(script);
       } else {
         this.ready(this.addWebVttScript_);
     ;
 
     _proto.requestPictureInPicture = function requestPictureInPicture() {
-      var PromiseClass = this.options_.Promise || window$1.Promise;
+      var PromiseClass = this.options_.Promise || window$3.Promise;
 
       if (PromiseClass) {
         return PromiseClass.reject();
 
       name = toTitleCase(name);
 
-      if (window$1 && window$1.videojs && window$1.videojs[name]) {
+      if (window$3 && window$3.videojs && window$3.videojs[name]) {
         log.warn("The " + name + " tech was added to the videojs object when it should be registered using videojs.registerTech(name, tech)");
-        return window$1.videojs[name];
+        return window$3.videojs[name];
       }
     };
 
     buffered: 1,
     currentTime: 1,
     duration: 1,
-    seekable: 1,
+    muted: 1,
     played: 1,
     paused: 1,
+    seekable: 1,
     volume: 1
   };
   /**
 
   var allowedSetters = {
     setCurrentTime: 1,
+    setMuted: 1,
     setVolume: 1
   };
   /**
    * @extends Component
    */
 
-  var MediaLoader =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(MediaLoader, _Component);
+  var MediaLoader = /*#__PURE__*/function (_Component) {
+    inheritsLoose(MediaLoader, _Component);
 
     /**
      * Create an instance of this class.
    * @extends Component
    */
 
-  var ClickableComponent =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(ClickableComponent, _Component);
+  var ClickableComponent = /*#__PURE__*/function (_Component) {
+    inheritsLoose(ClickableComponent, _Component);
 
     /**
      * Creates an instance of this class.
      *
      * @param  {Object} [options]
      *         The key/value store of player options.
+     *
+     * @param  {function} [options.clickHandler]
+     *         The function to call when the button is clicked / activated
      */
     function ClickableComponent(player, options) {
       var _this;
      */
     ;
 
-    _proto.handleClick = function handleClick(event) {}
+    _proto.handleClick = function handleClick(event) {
+      if (this.options_.clickHandler) {
+        this.options_.clickHandler.call(this, arguments);
+      }
+    }
     /**
      * Event handler that is called when a `ClickableComponent` receives a
      * `keydown` event.
    * @extends ClickableComponent
    */
 
-  var PosterImage =
-  /*#__PURE__*/
-  function (_ClickableComponent) {
-    _inheritsLoose(PosterImage, _ClickableComponent);
+  var PosterImage = /*#__PURE__*/function (_ClickableComponent) {
+    inheritsLoose(PosterImage, _ClickableComponent);
 
     /**
      * Create an instance of this class.
 
       _this.update();
 
-      player.on('posterchange', bind(_assertThisInitialized(_this), _this.update));
+      player.on('posterchange', bind(assertThisInitialized(_this), _this.update));
       return _this;
     }
     /**
         return;
       }
 
-      if (this.player_.tech(true)) {
+      var sourceIsEncrypted = this.player_.usingPlugin('eme') && this.player_.eme.sessions && this.player_.eme.sessions.length > 0;
+
+      if (this.player_.tech(true) && // We've observed a bug in IE and Edge when playing back DRM content where
+      // calling .focus() on the video element causes the video to go black,
+      // so we avoid it in that specific case
+      !((IE_VERSION || IS_EDGE) && sourceIsEncrypted)) {
         this.player_.tech(true).focus();
       }
 
    */
 
 
-  var TextTrackDisplay =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(TextTrackDisplay, _Component);
+  var TextTrackDisplay = /*#__PURE__*/function (_Component) {
+    inheritsLoose(TextTrackDisplay, _Component);
 
     /**
      * Creates an instance of this class.
       var _this;
 
       _this = _Component.call(this, player, options, ready) || this;
-      var updateDisplayHandler = bind(_assertThisInitialized(_this), _this.updateDisplay);
-      player.on('loadstart', bind(_assertThisInitialized(_this), _this.toggleDisplay));
+      var updateDisplayHandler = bind(assertThisInitialized(_this), _this.updateDisplay);
+      player.on('loadstart', bind(assertThisInitialized(_this), _this.toggleDisplay));
       player.on('texttrackchange', updateDisplayHandler);
-      player.on('loadedmetadata', bind(_assertThisInitialized(_this), _this.preselectTrack)); // This used to be called during player init, but was causing an error
+      player.on('loadedmetadata', bind(assertThisInitialized(_this), _this.preselectTrack)); // This used to be called during player init, but was causing an error
       // if a track should show by default and the display hadn't loaded yet.
       // Should probably be moved to an external track loader when we support
       // tracks that don't need a display.
 
-      player.ready(bind(_assertThisInitialized(_this), function () {
+      player.ready(bind(assertThisInitialized(_this), function () {
         if (player.tech_ && player.tech_.featuresNativeTextTracks) {
           this.hide();
           return;
 
         player.on('fullscreenchange', updateDisplayHandler);
         player.on('playerresize', updateDisplayHandler);
-        window$1.addEventListener('orientationchange', updateDisplayHandler);
+        window$3.addEventListener('orientationchange', updateDisplayHandler);
         player.on('dispose', function () {
-          return window$1.removeEventListener('orientationchange', updateDisplayHandler);
+          return window$3.removeEventListener('orientationchange', updateDisplayHandler);
         });
         var tracks = this.options_.playerOptions.tracks || [];
 
     ;
 
     _proto.clearDisplay = function clearDisplay() {
-      if (typeof window$1.WebVTT === 'function') {
-        window$1.WebVTT.processCues(window$1, [], this.el_);
+      if (typeof window$3.WebVTT === 'function') {
+        window$3.WebVTT.processCues(window$3, [], this.el_);
       }
     }
     /**
         }
 
         if (overrides.fontPercent && overrides.fontPercent !== 1) {
-          var fontSize = window$1.parseFloat(cueDiv.style.fontSize);
+          var fontSize = window$3.parseFloat(cueDiv.style.fontSize);
           cueDiv.style.fontSize = fontSize * overrides.fontPercent + 'px';
           cueDiv.style.height = 'auto';
           cueDiv.style.top = 'auto';
         tracks = [tracks];
       }
 
-      if (typeof window$1.WebVTT !== 'function' || tracks.every(function (track) {
+      if (typeof window$3.WebVTT !== 'function' || tracks.every(function (track) {
         return !track.activeCues;
       })) {
         return;
       } // removes all cues before it processes new ones
 
 
-      window$1.WebVTT.processCues(window$1, cues, this.el_); // add unique class to each language text track & add settings styling if necessary
+      window$3.WebVTT.processCues(window$3, cues, this.el_); // add unique class to each language text track & add settings styling if necessary
 
       for (var _i2 = 0; _i2 < tracks.length; ++_i2) {
         var _track2 = tracks[_i2];
    * @extends Component
    */
 
-  var LoadingSpinner =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(LoadingSpinner, _Component);
+  var LoadingSpinner = /*#__PURE__*/function (_Component) {
+    inheritsLoose(LoadingSpinner, _Component);
 
     function LoadingSpinner() {
       return _Component.apply(this, arguments) || this;
    * @extends ClickableComponent
    */
 
-  var Button =
-  /*#__PURE__*/
-  function (_ClickableComponent) {
-    _inheritsLoose(Button, _ClickableComponent);
+  var Button = /*#__PURE__*/function (_ClickableComponent) {
+    inheritsLoose(Button, _ClickableComponent);
 
     function Button() {
       return _ClickableComponent.apply(this, arguments) || this;
    * @extends Button
    */
 
-  var BigPlayButton =
-  /*#__PURE__*/
-  function (_Button) {
-    _inheritsLoose(BigPlayButton, _Button);
+  var BigPlayButton = /*#__PURE__*/function (_Button) {
+    inheritsLoose(BigPlayButton, _Button);
 
     function BigPlayButton(player, options) {
       var _this;
       var playPromise = this.player_.play(); // exit early if clicked via the mouse
 
       if (this.mouseused_ && event.clientX && event.clientY) {
+        var sourceIsEncrypted = this.player_.usingPlugin('eme') && this.player_.eme.sessions && this.player_.eme.sessions.length > 0;
         silencePromise(playPromise);
 
-        if (this.player_.tech(true)) {
+        if (this.player_.tech(true) && // We've observed a bug in IE and Edge when playing back DRM content where
+        // calling .focus() on the video element causes the video to go black,
+        // so we avoid it in that specific case
+        !((IE_VERSION || IS_EDGE) && sourceIsEncrypted)) {
           this.player_.tech(true).focus();
         }
 
    * @extends Button
    */
 
-  var CloseButton =
-  /*#__PURE__*/
-  function (_Button) {
-    _inheritsLoose(CloseButton, _Button);
+  var CloseButton = /*#__PURE__*/function (_Button) {
+    inheritsLoose(CloseButton, _Button);
 
     /**
     * Creates an instance of the this class.
    * @extends Button
    */
 
-  var PlayToggle =
-  /*#__PURE__*/
-  function (_Button) {
-    _inheritsLoose(PlayToggle, _Button);
+  var PlayToggle = /*#__PURE__*/function (_Button) {
+    inheritsLoose(PlayToggle, _Button);
 
     /**
      * Creates an instance of this class.
   }; // Internal pointer to the current implementation.
 
 
-  var implementation$3 = defaultImplementation;
+  var implementation = defaultImplementation;
   /**
    * Replaces the default formatTime implementation with a custom implementation.
    *
    */
 
   function setFormatTime(customImplementation) {
-    implementation$3 = customImplementation;
+    implementation = customImplementation;
   }
   /**
    * Resets formatTime to the default implementation.
    */
 
   function resetFormatTime() {
-    implementation$3 = defaultImplementation;
+    implementation = defaultImplementation;
   }
   /**
    * Delegates to either the default time formatting function or a custom
       guide = seconds;
     }
 
-    return implementation$3(seconds, guide);
+    return implementation(seconds, guide);
   }
 
   /**
    * @extends Component
    */
 
-  var TimeDisplay =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(TimeDisplay, _Component);
+  var TimeDisplay = /*#__PURE__*/function (_Component) {
+    inheritsLoose(TimeDisplay, _Component);
 
     /**
      * Creates an instance of this class.
       var _this;
 
       _this = _Component.call(this, player, options) || this;
-      _this.throttledUpdateContent = throttle(bind(_assertThisInitialized(_this), _this.updateContent), UPDATE_REFRESH_INTERVAL);
 
-      _this.on(player, 'timeupdate', _this.throttledUpdateContent);
+      _this.on(player, ['timeupdate', 'ended'], _this.updateContent);
+
+      _this.updateTextNode_();
 
       return _this;
     }
         // role='presentation' causes VoiceOver to NOT treat this span as a break.
         'role': 'presentation'
       });
-      this.updateTextNode_();
       el.appendChild(this.contentEl_);
       return el;
     };
       _Component.prototype.dispose.call(this);
     }
     /**
-     * Updates the "remaining time" text node with new content using the
-     * contents of the `formattedTime_` property.
+     * Updates the time display text node with a new time
+     *
+     * @param {number} [time=0] the time to update to
      *
      * @private
      */
     ;
 
-    _proto.updateTextNode_ = function updateTextNode_() {
-      if (!this.contentEl_) {
-        return;
-      }
+    _proto.updateTextNode_ = function updateTextNode_(time) {
+      var _this2 = this;
 
-      while (this.contentEl_.firstChild) {
-        this.contentEl_.removeChild(this.contentEl_.firstChild);
+      if (time === void 0) {
+        time = 0;
       }
 
-      this.textNode_ = document.createTextNode(this.formattedTime_ || this.formatTime_(0));
-      this.contentEl_.appendChild(this.textNode_);
-    }
-    /**
-     * Generates a formatted time for this component to use in display.
-     *
-     * @param  {number} time
-     *         A numeric time, in seconds.
-     *
-     * @return {string}
-     *         A formatted time
-     *
-     * @private
-     */
-    ;
-
-    _proto.formatTime_ = function formatTime_(time) {
-      return formatTime(time);
-    }
-    /**
-     * Updates the time display text node if it has what was passed in changed
-     * the formatted time.
-     *
-     * @param {number} time
-     *        The time to update to
-     *
-     * @private
-     */
-    ;
-
-    _proto.updateFormattedTime_ = function updateFormattedTime_(time) {
-      var formattedTime = this.formatTime_(time);
+      time = formatTime(time);
 
-      if (formattedTime === this.formattedTime_) {
+      if (this.formattedTime_ === time) {
         return;
       }
 
-      this.formattedTime_ = formattedTime;
-      this.requestAnimationFrame(this.updateTextNode_);
+      this.formattedTime_ = time;
+      this.requestAnimationFrame(function () {
+        if (!_this2.contentEl_) {
+          return;
+        }
+
+        var oldNode = _this2.textNode_;
+        _this2.textNode_ = document.createTextNode(_this2.formattedTime_);
+
+        if (!_this2.textNode_) {
+          return;
+        }
+
+        if (oldNode) {
+          _this2.contentEl_.replaceChild(_this2.textNode_, oldNode);
+        } else {
+          _this2.contentEl_.appendChild(_this2.textNode_);
+        }
+      });
     }
     /**
      * To be filled out in the child class, should update the displayed time
    * @extends Component
    */
 
-  var CurrentTimeDisplay =
-  /*#__PURE__*/
-  function (_TimeDisplay) {
-    _inheritsLoose(CurrentTimeDisplay, _TimeDisplay);
+  var CurrentTimeDisplay = /*#__PURE__*/function (_TimeDisplay) {
+    inheritsLoose(CurrentTimeDisplay, _TimeDisplay);
 
-    /**
-     * Creates an instance of this class.
-     *
-     * @param {Player} player
-     *        The `Player` that this class should be attached to.
-     *
-     * @param {Object} [options]
-     *        The key/value store of player options.
-     */
-    function CurrentTimeDisplay(player, options) {
-      var _this;
-
-      _this = _TimeDisplay.call(this, player, options) || this;
+    function CurrentTimeDisplay() {
+      return _TimeDisplay.apply(this, arguments) || this;
+    }
 
-      _this.on(player, 'ended', _this.handleEnded);
+    var _proto = CurrentTimeDisplay.prototype;
 
-      return _this;
-    }
     /**
      * Builds the default DOM `className`.
      *
      * @return {string}
      *         The DOM `className` for this object.
      */
-
-
-    var _proto = CurrentTimeDisplay.prototype;
-
     _proto.buildCSSClass = function buildCSSClass() {
       return 'vjs-current-time';
     }
 
     _proto.updateContent = function updateContent(event) {
       // Allows for smooth scrubbing, when player can't keep up.
-      var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
-      this.updateFormattedTime_(time);
-    }
-    /**
-     * When the player fires ended there should be no time left. Sadly
-     * this is not always the case, lets make it seem like that is the case
-     * for users.
-     *
-     * @param {EventTarget~Event} [event]
-     *        The `ended` event that caused this to run.
-     *
-     * @listens Player#ended
-     */
-    ;
+      var time;
 
-    _proto.handleEnded = function handleEnded(event) {
-      if (!this.player_.duration()) {
-        return;
+      if (this.player_.ended()) {
+        time = this.player_.duration();
+      } else {
+        time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
       }
 
-      this.updateFormattedTime_(this.player_.duration());
+      this.updateTextNode_(time);
     };
 
     return CurrentTimeDisplay;
    * @extends Component
    */
 
-  var DurationDisplay =
-  /*#__PURE__*/
-  function (_TimeDisplay) {
-    _inheritsLoose(DurationDisplay, _TimeDisplay);
+  var DurationDisplay = /*#__PURE__*/function (_TimeDisplay) {
+    inheritsLoose(DurationDisplay, _TimeDisplay);
 
     /**
      * Creates an instance of this class.
       // can likely be removed for 7.0.
 
 
-      _this.on(player, 'loadedmetadata', _this.throttledUpdateContent);
+      _this.on(player, 'loadedmetadata', _this.updateContent);
 
       return _this;
     }
 
     _proto.updateContent = function updateContent(event) {
       var duration = this.player_.duration();
-
-      if (this.duration_ !== duration) {
-        this.duration_ = duration;
-        this.updateFormattedTime_(duration);
-      }
+      this.updateTextNode_(duration);
     };
 
     return DurationDisplay;
    * @extends Component
    */
 
-  var TimeDivider =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(TimeDivider, _Component);
+  var TimeDivider = /*#__PURE__*/function (_Component) {
+    inheritsLoose(TimeDivider, _Component);
 
     function TimeDivider() {
       return _Component.apply(this, arguments) || this;
    * @extends Component
    */
 
-  var RemainingTimeDisplay =
-  /*#__PURE__*/
-  function (_TimeDisplay) {
-    _inheritsLoose(RemainingTimeDisplay, _TimeDisplay);
+  var RemainingTimeDisplay = /*#__PURE__*/function (_TimeDisplay) {
+    inheritsLoose(RemainingTimeDisplay, _TimeDisplay);
 
     /**
      * Creates an instance of this class.
 
       _this = _TimeDisplay.call(this, player, options) || this;
 
-      _this.on(player, 'durationchange', _this.throttledUpdateContent);
-
-      _this.on(player, 'ended', _this.handleEnded);
+      _this.on(player, 'durationchange', _this.updateContent);
 
       return _this;
     }
     _proto.updateContent = function updateContent(event) {
       if (typeof this.player_.duration() !== 'number') {
         return;
-      } // @deprecated We should only use remainingTimeDisplay
-      // as of video.js 7
+      }
 
+      var time; // @deprecated We should only use remainingTimeDisplay
+      // as of video.js 7
 
-      if (this.player_.remainingTimeDisplay) {
-        this.updateFormattedTime_(this.player_.remainingTimeDisplay());
+      if (this.player_.ended()) {
+        time = 0;
+      } else if (this.player_.remainingTimeDisplay) {
+        time = this.player_.remainingTimeDisplay();
       } else {
-        this.updateFormattedTime_(this.player_.remainingTime());
-      }
-    }
-    /**
-     * When the player fires ended there should be no time left. Sadly
-     * this is not always the case, lets make it seem like that is the case
-     * for users.
-     *
-     * @param {EventTarget~Event} [event]
-     *        The `ended` event that caused this to run.
-     *
-     * @listens Player#ended
-     */
-    ;
-
-    _proto.handleEnded = function handleEnded(event) {
-      if (!this.player_.duration()) {
-        return;
+        time = this.player_.remainingTime();
       }
 
-      this.updateFormattedTime_(0);
+      this.updateTextNode_(time);
     };
 
     return RemainingTimeDisplay;
    * @extends Component
    */
 
-  var LiveDisplay =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(LiveDisplay, _Component);
+  var LiveDisplay = /*#__PURE__*/function (_Component) {
+    inheritsLoose(LiveDisplay, _Component);
 
     /**
      * Creates an instance of this class.
    * @extends Component
    */
 
-  var SeekToLive =
-  /*#__PURE__*/
-  function (_Button) {
-    _inheritsLoose(SeekToLive, _Button);
+  var SeekToLive = /*#__PURE__*/function (_Button) {
+    inheritsLoose(SeekToLive, _Button);
 
     /**
      * Creates an instance of this class.
   SeekToLive.prototype.controlText_ = 'Seek to live, currently playing live';
   Component.registerComponent('SeekToLive', SeekToLive);
 
+  /**
+   * Keep a number between a min and a max value
+   *
+   * @param {number} number
+   *        The number to clamp
+   *
+   * @param {number} min
+   *        The minimum value
+   * @param {number} max
+   *        The maximum value
+   *
+   * @return {number}
+   *         the clamped number
+   */
+  var clamp = function clamp(number, min, max) {
+    number = Number(number);
+    return Math.min(max, Math.max(min, isNaN(number) ? min : number));
+  };
+
   /**
    * The base functionality for a slider. Can be vertical or horizontal.
    * For instance the volume bar or the seek bar on a video is a slider.
    * @extends Component
    */
 
-  var Slider =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(Slider, _Component);
+  var Slider = /*#__PURE__*/function (_Component) {
+    inheritsLoose(Slider, _Component);
 
     /**
     * Create an instance of this class
     ;
 
     _proto.update = function update() {
+      var _this2 = this;
+
       // In VolumeBar init we have a setTimeout for update that pops and update
       // to the end of the execution stack. The player is destroyed before then
       // update will cause an error
-      if (!this.el_) {
-        return;
-      } // If scrubbing, we could use a cached value to make the handle keep up
-      // with the user's mouse. On HTML5 browsers scrubbing is really smooth, but
-      // some flash players are slow, so we might want to utilize this later.
-      // var progress =  (this.player_.scrubbing()) ? this.player_.getCache().currentTime / this.player_.duration() : this.player_.currentTime() / this.player_.duration();
-
-
-      var progress = this.getPercent();
-      var bar = this.bar; // If there's no bar...
-
-      if (!bar) {
+      // If there's no bar...
+      if (!this.el_ || !this.bar) {
         return;
-      } // Protect against no duration and other division issues
-
+      } // clamp progress between 0 and 1
+      // and only round to four decimal places, as we round to two below
 
-      if (typeof progress !== 'number' || progress !== progress || progress < 0 || progress === Infinity) {
-        progress = 0;
-      } // Convert to a percentage for setting
 
+      var progress = this.getProgress();
 
-      var percentage = (progress * 100).toFixed(2) + '%';
-      var style = bar.el().style; // Set the new bar width or height
-
-      var sizeKey = this.vertical() ? 'height' : 'width';
-
-      if (style[sizeKey] !== percentage) {
-        style[sizeKey] = percentage;
+      if (progress === this.progress_) {
+        return progress;
       }
 
+      this.progress_ = progress;
+      this.requestAnimationFrame(function () {
+        // Set the new bar width or height
+        var sizeKey = _this2.vertical() ? 'height' : 'width'; // Convert to a percentage for css value
+
+        _this2.bar.el().style[sizeKey] = (progress * 100).toFixed(2) + '%';
+      });
       return progress;
     }
+    /**
+     * Get the percentage of the bar that should be filled
+     * but clamped and rounded.
+     *
+     * @return {number}
+     *         percentage filled that the slider is
+     */
+    ;
+
+    _proto.getProgress = function getProgress() {
+      return Number(clamp(this.getPercent(), 0, 1).toFixed(4));
+    }
     /**
      * Calculate distance for slider
      *
 
   Component.registerComponent('Slider', Slider);
 
+  var percentify = function percentify(time, end) {
+    return clamp(time / end * 100, 0, 100).toFixed(2) + '%';
+  };
   /**
    * Shows loading progress
    *
    * @extends Component
    */
 
-  var LoadProgressBar =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(LoadProgressBar, _Component);
+
+  var LoadProgressBar = /*#__PURE__*/function (_Component) {
+    inheritsLoose(LoadProgressBar, _Component);
 
     /**
      * Creates an instance of this class.
 
     var _proto = LoadProgressBar.prototype;
 
-    _proto.createEl = function createEl() {
-      return _Component.prototype.createEl.call(this, 'div', {
-        className: 'vjs-load-progress',
-        innerHTML: "<span class=\"vjs-control-text\"><span>" + this.localize('Loaded') + "</span>: <span class=\"vjs-control-text-loaded-percentage\">0%</span></span>"
+    _proto.createEl = function createEl$1() {
+      var el = _Component.prototype.createEl.call(this, 'div', {
+        className: 'vjs-load-progress'
+      });
+
+      var wrapper = createEl('span', {
+        className: 'vjs-control-text'
+      });
+      var loadedText = createEl('span', {
+        textContent: this.localize('Loaded')
       });
+      var separator = document.createTextNode(': ');
+      this.percentageEl_ = createEl('span', {
+        className: 'vjs-control-text-loaded-percentage',
+        textContent: '0%'
+      });
+      el.appendChild(wrapper);
+      wrapper.appendChild(loadedText);
+      wrapper.appendChild(separator);
+      wrapper.appendChild(this.percentageEl_);
+      return el;
     };
 
     _proto.dispose = function dispose() {
       this.partEls_ = null;
+      this.percentageEl_ = null;
 
       _Component.prototype.dispose.call(this);
     }
     ;
 
     _proto.update = function update(event) {
-      var liveTracker = this.player_.liveTracker;
-      var buffered = this.player_.buffered();
-      var duration = liveTracker && liveTracker.isLive() ? liveTracker.seekableEnd() : this.player_.duration();
-      var bufferedEnd = this.player_.bufferedEnd();
-      var children = this.partEls_;
-      var controlTextPercentage = this.$('.vjs-control-text-loaded-percentage'); // get the percent width of a time compared to the total end
+      var _this2 = this;
 
-      var percentify = function percentify(time, end, rounded) {
-        // no NaN
-        var percent = time / end || 0;
-        percent = (percent >= 1 ? 1 : percent) * 100;
+      this.requestAnimationFrame(function () {
+        var liveTracker = _this2.player_.liveTracker;
 
-        if (rounded) {
-          percent = percent.toFixed(2);
-        }
+        var buffered = _this2.player_.buffered();
 
-        return percent + '%';
-      }; // update the width of the progress bar
+        var duration = liveTracker && liveTracker.isLive() ? liveTracker.seekableEnd() : _this2.player_.duration();
 
+        var bufferedEnd = _this2.player_.bufferedEnd();
 
-      this.el_.style.width = percentify(bufferedEnd, duration); // update the control-text
+        var children = _this2.partEls_;
+        var percent = percentify(bufferedEnd, duration);
 
-      textContent(controlTextPercentage, percentify(bufferedEnd, duration, true)); // add child elements to represent the individual buffered time ranges
+        if (_this2.percent_ !== percent) {
+          // update the width of the progress bar
+          _this2.el_.style.width = percent; // update the control-text
 
-      for (var i = 0; i < buffered.length; i++) {
-        var start = buffered.start(i);
-        var end = buffered.end(i);
-        var part = children[i];
+          textContent(_this2.percentageEl_, percent);
+          _this2.percent_ = percent;
+        } // add child elements to represent the individual buffered time ranges
 
-        if (!part) {
-          part = this.el_.appendChild(createEl());
-          children[i] = part;
-        } // set the percent based on the width of the progress bar (bufferedEnd)
 
+        for (var i = 0; i < buffered.length; i++) {
+          var start = buffered.start(i);
+          var end = buffered.end(i);
+          var part = children[i];
 
-        part.style.left = percentify(start, bufferedEnd);
-        part.style.width = percentify(end - start, bufferedEnd);
-      } // remove unused buffered range elements
+          if (!part) {
+            part = _this2.el_.appendChild(createEl());
+            children[i] = part;
+          } //  only update if changed
 
 
-      for (var _i = children.length; _i > buffered.length; _i--) {
-        this.el_.removeChild(children[_i - 1]);
-      }
+          if (part.dataset.start === start && part.dataset.end === end) {
+            continue;
+          }
 
-      children.length = buffered.length;
+          part.dataset.start = start;
+          part.dataset.end = end; // set the percent based on the width of the progress bar (bufferedEnd)
+
+          part.style.left = percentify(start, bufferedEnd);
+          part.style.width = percentify(end - start, bufferedEnd);
+        } // remove unused buffered range elements
+
+
+        for (var _i = children.length; _i > buffered.length; _i--) {
+          _this2.el_.removeChild(children[_i - 1]);
+        }
+
+        children.length = buffered.length;
+      });
     };
 
     return LoadProgressBar;
    * @extends Component
    */
 
-  var TimeTooltip =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(TimeTooltip, _Component);
+  var TimeTooltip = /*#__PURE__*/function (_Component) {
+    inheritsLoose(TimeTooltip, _Component);
 
     /**
      * Creates an instance of this class.
       var _this;
 
       _this = _Component.call(this, player, options) || this;
-      _this.update = throttle(bind(_assertThisInitialized(_this), _this.update), UPDATE_REFRESH_INTERVAL);
+      _this.update = throttle(bind(assertThisInitialized(_this), _this.update), UPDATE_REFRESH_INTERVAL);
       return _this;
     }
     /**
    * @extends Component
    */
 
-  var PlayProgressBar =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(PlayProgressBar, _Component);
+  var PlayProgressBar = /*#__PURE__*/function (_Component) {
+    inheritsLoose(PlayProgressBar, _Component);
 
     /**
      * Creates an instance of this class.
       var _this;
 
       _this = _Component.call(this, player, options) || this;
-      _this.update = throttle(bind(_assertThisInitialized(_this), _this.update), UPDATE_REFRESH_INTERVAL);
+      _this.update = throttle(bind(assertThisInitialized(_this), _this.update), UPDATE_REFRESH_INTERVAL);
       return _this;
     }
     /**
    * @extends Component
    */
 
-  var MouseTimeDisplay =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(MouseTimeDisplay, _Component);
+  var MouseTimeDisplay = /*#__PURE__*/function (_Component) {
+    inheritsLoose(MouseTimeDisplay, _Component);
 
     /**
      * Creates an instance of this class.
       var _this;
 
       _this = _Component.call(this, player, options) || this;
-      _this.update = throttle(bind(_assertThisInitialized(_this), _this.update), UPDATE_REFRESH_INTERVAL);
+      _this.update = throttle(bind(assertThisInitialized(_this), _this.update), UPDATE_REFRESH_INTERVAL);
       return _this;
     }
     /**
 
   var STEP_SECONDS = 5; // The multiplier of STEP_SECONDS that PgUp/PgDown move the timeline.
 
-  var PAGE_KEY_MULTIPLIER = 12; // The interval at which the bar should update as it progresses.
-
-  var UPDATE_REFRESH_INTERVAL$1 = 30;
+  var PAGE_KEY_MULTIPLIER = 12;
   /**
    * Seek bar and container for the progress bars. Uses {@link PlayProgressBar}
    * as its `bar`.
    * @extends Slider
    */
 
-  var SeekBar =
-  /*#__PURE__*/
-  function (_Slider) {
-    _inheritsLoose(SeekBar, _Slider);
+  var SeekBar = /*#__PURE__*/function (_Slider) {
+    inheritsLoose(SeekBar, _Slider);
 
     /**
      * Creates an instance of this class.
     var _proto = SeekBar.prototype;
 
     _proto.setEventHandlers_ = function setEventHandlers_() {
-      this.update = throttle(bind(this, this.update), UPDATE_REFRESH_INTERVAL$1);
-      this.on(this.player_, 'timeupdate', this.update);
-      this.on(this.player_, 'ended', this.handleEnded);
-      this.on(this.player_, 'durationchange', this.update);
+      this.update_ = bind(this, this.update);
+      this.update = throttle(this.update_, UPDATE_REFRESH_INTERVAL);
+      this.on(this.player_, ['ended', 'durationchange', 'timeupdate'], this.update);
 
       if (this.player_.liveTracker) {
         this.on(this.player_.liveTracker, 'liveedgechange', this.update);
       } else {
         this.enableInterval_(); // we just switched back to the page and someone may be looking, so, update ASAP
 
-        this.requestAnimationFrame(this.update);
+        this.update();
       }
     };
 
     _proto.enableInterval_ = function enableInterval_() {
-      var _this2 = this;
+      if (this.updateInterval) {
+        return;
+      }
 
-      this.clearInterval(this.updateInterval);
-      this.updateInterval = this.setInterval(function () {
-        _this2.requestAnimationFrame(_this2.update);
-      }, UPDATE_REFRESH_INTERVAL$1);
+      this.updateInterval = this.setInterval(this.update, UPDATE_REFRESH_INTERVAL);
     };
 
     _proto.disableInterval_ = function disableInterval_(e) {
         return;
       }
 
+      if (!this.updateInterval) {
+        return;
+      }
+
       this.clearInterval(this.updateInterval);
+      this.updateInterval = null;
     }
     /**
      * Create the `Component`'s DOM element
      * This function updates the play progress bar and accessibility
      * attributes to whatever is passed in.
      *
-     * @param {number} currentTime
-     *        The currentTime value that should be used for accessibility
-     *
-     * @param {number} percent
-     *        The percentage as a decimal that the bar should be filled from 0-1.
-     *
-     * @private
-     */
-    ;
-
-    _proto.update_ = function update_(currentTime, percent) {
-      var liveTracker = this.player_.liveTracker;
-      var duration = this.player_.duration();
-
-      if (liveTracker && liveTracker.isLive()) {
-        duration = this.player_.liveTracker.liveCurrentTime();
-      } // machine readable value of progress bar (percentage complete)
-
-
-      this.el_.setAttribute('aria-valuenow', (percent * 100).toFixed(2)); // human readable value of progress bar (time complete)
-
-      this.el_.setAttribute('aria-valuetext', this.localize('progress bar timing: currentTime={1} duration={2}', [formatTime(currentTime, duration), formatTime(duration, duration)], '{1} of {2}')); // Update the `PlayProgressBar`.
-
-      if (this.bar) {
-        this.bar.update(getBoundingClientRect(this.el_), percent);
-      }
-    }
-    /**
-     * Update the seek bar's UI.
-     *
      * @param {EventTarget~Event} [event]
      *        The `timeupdate` or `ended` event that caused this to run.
      *
     ;
 
     _proto.update = function update(event) {
-      // if the offsetParent is null, then this element is hidden, in which case
-      // we don't need to update it.
-      if (this.el().offsetParent === null) {
-        return;
-      }
+      var _this2 = this;
 
       var percent = _Slider.prototype.update.call(this);
 
-      this.update_(this.getCurrentTime_(), percent);
+      this.requestAnimationFrame(function () {
+        var currentTime = _this2.player_.ended() ? _this2.player_.duration() : _this2.getCurrentTime_();
+        var liveTracker = _this2.player_.liveTracker;
+
+        var duration = _this2.player_.duration();
+
+        if (liveTracker && liveTracker.isLive()) {
+          duration = _this2.player_.liveTracker.liveCurrentTime();
+        }
+
+        if (_this2.percent_ !== percent) {
+          // machine readable value of progress bar (percentage complete)
+          _this2.el_.setAttribute('aria-valuenow', (percent * 100).toFixed(2));
+
+          _this2.percent_ = percent;
+        }
+
+        if (_this2.currentTime_ !== currentTime || _this2.duration_ !== duration) {
+          // human readable value of progress bar (time complete)
+          _this2.el_.setAttribute('aria-valuetext', _this2.localize('progress bar timing: currentTime={1} duration={2}', [formatTime(currentTime, duration), formatTime(duration, duration)], '{1} of {2}'));
+
+          _this2.currentTime_ = currentTime;
+          _this2.duration_ = duration;
+        } // update the progress bar time tooltip with the current time
+
+
+        if (_this2.bar) {
+          _this2.bar.update(getBoundingClientRect(_this2.el()), _this2.getProgress());
+        }
+      });
       return percent;
     }
     /**
     _proto.getCurrentTime_ = function getCurrentTime_() {
       return this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
     }
-    /**
-     * We want the seek bar to be full on ended
-     * no matter what the actual internal values are. so we force it.
-     *
-     * @param {EventTarget~Event} [event]
-     *        The `timeupdate` or `ended` event that caused this to run.
-     *
-     * @listens Player#ended
-     */
-    ;
-
-    _proto.handleEnded = function handleEnded(event) {
-      this.update_(this.player_.duration(), 1);
-    }
     /**
      * Get the percentage of media played so far.
      *
         percent = currentTime / this.player_.duration();
       }
 
-      return percent >= 1 ? 1 : percent || 0;
+      return percent;
     }
     /**
      * Handle mouse down on seek bar
 
       if (this.videoWasPlaying) {
         silencePromise(this.player_.play());
+      } else {
+        // We're done seeking and the time has changed.
+        // If the player is paused, make sure we display the correct time on the seek bar.
+        this.update_();
       }
     }
     /**
    * @extends Component
    */
 
-  var ProgressControl =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(ProgressControl, _Component);
+  var ProgressControl = /*#__PURE__*/function (_Component) {
+    inheritsLoose(ProgressControl, _Component);
 
     /**
      * Creates an instance of this class.
       var _this;
 
       _this = _Component.call(this, player, options) || this;
-      _this.handleMouseMove = throttle(bind(_assertThisInitialized(_this), _this.handleMouseMove), UPDATE_REFRESH_INTERVAL);
-      _this.throttledHandleMouseSeek = throttle(bind(_assertThisInitialized(_this), _this.handleMouseSeek), UPDATE_REFRESH_INTERVAL);
+      _this.handleMouseMove = throttle(bind(assertThisInitialized(_this), _this.handleMouseMove), UPDATE_REFRESH_INTERVAL);
+      _this.throttledHandleMouseSeek = throttle(bind(assertThisInitialized(_this), _this.handleMouseSeek), UPDATE_REFRESH_INTERVAL);
 
       _this.enable();
 
     _proto.handleMouseMove = function handleMouseMove(event) {
       var seekBar = this.getChild('seekBar');
 
-      if (seekBar) {
-        var mouseTimeDisplay = seekBar.getChild('mouseTimeDisplay');
-        var seekBarEl = seekBar.el();
-        var seekBarRect = getBoundingClientRect(seekBarEl);
-        var seekBarPoint = getPointerPosition(seekBarEl, event).x; // The default skin has a gap on either side of the `SeekBar`. This means
-        // that it's possible to trigger this behavior outside the boundaries of
-        // the `SeekBar`. This ensures we stay within it at all times.
+      if (!seekBar) {
+        return;
+      }
 
-        if (seekBarPoint > 1) {
-          seekBarPoint = 1;
-        } else if (seekBarPoint < 0) {
-          seekBarPoint = 0;
-        }
+      var playProgressBar = seekBar.getChild('playProgressBar');
+      var mouseTimeDisplay = seekBar.getChild('mouseTimeDisplay');
 
-        if (mouseTimeDisplay) {
-          mouseTimeDisplay.update(seekBarRect, seekBarPoint);
-        }
+      if (!playProgressBar && !mouseTimeDisplay) {
+        return;
+      }
+
+      var seekBarEl = seekBar.el();
+      var seekBarRect = getBoundingClientRect(seekBarEl);
+      var seekBarPoint = getPointerPosition(seekBarEl, event).x; // The default skin has a gap on either side of the `SeekBar`. This means
+      // that it's possible to trigger this behavior outside the boundaries of
+      // the `SeekBar`. This ensures we stay within it at all times.
+
+      seekBarPoint = clamp(0, 1, seekBarPoint);
+
+      if (mouseTimeDisplay) {
+        mouseTimeDisplay.update(seekBarRect, seekBarPoint);
+      }
+
+      if (playProgressBar) {
+        playProgressBar.update(seekBarRect, seekBar.getProgress());
       }
     }
     /**
    * @extends Button
    */
 
-  var PictureInPictureToggle =
-  /*#__PURE__*/
-  function (_Button) {
-    _inheritsLoose(PictureInPictureToggle, _Button);
+  var PictureInPictureToggle = /*#__PURE__*/function (_Button) {
+    inheritsLoose(PictureInPictureToggle, _Button);
 
     /**
      * Creates an instance of this class.
    * @extends Button
    */
 
-  var FullscreenToggle =
-  /*#__PURE__*/
-  function (_Button) {
-    _inheritsLoose(FullscreenToggle, _Button);
+  var FullscreenToggle = /*#__PURE__*/function (_Button) {
+    inheritsLoose(FullscreenToggle, _Button);
 
     /**
      * Creates an instance of this class.
    * @extends Component
    */
 
-  var VolumeLevel =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(VolumeLevel, _Component);
+  var VolumeLevel = /*#__PURE__*/function (_Component) {
+    inheritsLoose(VolumeLevel, _Component);
 
     function VolumeLevel() {
       return _Component.apply(this, arguments) || this;
    * @extends Slider
    */
 
-  var VolumeBar =
-  /*#__PURE__*/
-  function (_Slider) {
-    _inheritsLoose(VolumeBar, _Slider);
+  var VolumeBar = /*#__PURE__*/function (_Slider) {
+    inheritsLoose(VolumeBar, _Slider);
 
     /**
      * Creates an instance of this class.
    * @extends Component
    */
 
-  var VolumeControl =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(VolumeControl, _Component);
+  var VolumeControl = /*#__PURE__*/function (_Component) {
+    inheritsLoose(VolumeControl, _Component);
 
     /**
      * Creates an instance of this class.
 
       _this = _Component.call(this, player, options) || this; // hide this control if volume support is missing
 
-      checkVolumeSupport(_assertThisInitialized(_this), player);
-      _this.throttledHandleMouseMove = throttle(bind(_assertThisInitialized(_this), _this.handleMouseMove), UPDATE_REFRESH_INTERVAL);
+      checkVolumeSupport(assertThisInitialized(_this), player);
+      _this.throttledHandleMouseMove = throttle(bind(assertThisInitialized(_this), _this.handleMouseMove), UPDATE_REFRESH_INTERVAL);
 
       _this.on('mousedown', _this.handleMouseDown);
 
    * @extends Button
    */
 
-  var MuteToggle =
-  /*#__PURE__*/
-  function (_Button) {
-    _inheritsLoose(MuteToggle, _Button);
+  var MuteToggle = /*#__PURE__*/function (_Button) {
+    inheritsLoose(MuteToggle, _Button);
 
     /**
      * Creates an instance of this class.
 
       _this = _Button.call(this, player, options) || this; // hide this control if volume support is missing
 
-      checkMuteSupport(_assertThisInitialized(_this), player);
+      checkMuteSupport(assertThisInitialized(_this), player);
 
       _this.on(player, ['loadstart', 'volumechange'], _this.update);
 
    * @extends Component
    */
 
-  var VolumePanel =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(VolumePanel, _Component);
+  var VolumePanel = /*#__PURE__*/function (_Component) {
+    inheritsLoose(VolumePanel, _Component);
 
     /**
      * Creates an instance of this class.
    * @extends Component
    */
 
-  var Menu =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(Menu, _Component);
+  var Menu = /*#__PURE__*/function (_Component) {
+    inheritsLoose(Menu, _Component);
 
     /**
      * Create an instance of this class.
       _this.on('keydown', _this.handleKeyDown); // All the menu item instances share the same blur handler provided by the menu container.
 
 
-      _this.boundHandleBlur_ = bind(_assertThisInitialized(_this), _this.handleBlur);
-      _this.boundHandleTapClick_ = bind(_assertThisInitialized(_this), _this.handleTapClick);
+      _this.boundHandleBlur_ = bind(assertThisInitialized(_this), _this.handleBlur);
+      _this.boundHandleTapClick_ = bind(assertThisInitialized(_this), _this.handleTapClick);
       return _this;
     }
     /**
    * @extends Component
    */
 
-  var MenuButton =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(MenuButton, _Component);
+  var MenuButton = /*#__PURE__*/function (_Component) {
+    inheritsLoose(MenuButton, _Component);
 
     /**
      * Creates an instance of this class.
 
         _this.menu.show();
 
-        on(document, 'keyup', bind(_assertThisInitialized(_this), _this.handleMenuKeyUp));
+        on(document, 'keyup', bind(assertThisInitialized(_this), _this.handleMenuKeyUp));
       });
 
       _this.on('mouseleave', _this.handleMouseLeave);
    * @extends MenuButton
    */
 
-  var TrackButton =
-  /*#__PURE__*/
-  function (_MenuButton) {
-    _inheritsLoose(TrackButton, _MenuButton);
+  var TrackButton = /*#__PURE__*/function (_MenuButton) {
+    inheritsLoose(TrackButton, _MenuButton);
 
     /**
      * Creates an instance of this class.
       }
 
       if (!tracks) {
-        return _assertThisInitialized(_this);
+        return assertThisInitialized(_this);
       }
 
-      var updateHandler = bind(_assertThisInitialized(_this), _this.update);
+      var updateHandler = bind(assertThisInitialized(_this), _this.update);
       tracks.addEventListener('removetrack', updateHandler);
       tracks.addEventListener('addtrack', updateHandler);
 
    * @extends ClickableComponent
    */
 
-  var MenuItem =
-  /*#__PURE__*/
-  function (_ClickableComponent) {
-    _inheritsLoose(MenuItem, _ClickableComponent);
+  var MenuItem = /*#__PURE__*/function (_ClickableComponent) {
+    inheritsLoose(MenuItem, _ClickableComponent);
 
     /**
      * Creates an instance of the this class.
    * @extends MenuItem
    */
 
-  var TextTrackMenuItem =
-  /*#__PURE__*/
-  function (_MenuItem) {
-    _inheritsLoose(TextTrackMenuItem, _MenuItem);
+  var TextTrackMenuItem = /*#__PURE__*/function (_MenuItem) {
+    inheritsLoose(TextTrackMenuItem, _MenuItem);
 
     /**
      * Creates an instance of this class.
           args[_key] = arguments[_key];
         }
 
-        _this.handleTracksChange.apply(_assertThisInitialized(_this), args);
+        _this.handleTracksChange.apply(assertThisInitialized(_this), args);
       };
 
       var selectedLanguageChangeHandler = function selectedLanguageChangeHandler() {
           args[_key2] = arguments[_key2];
         }
 
-        _this.handleSelectedLanguageChange.apply(_assertThisInitialized(_this), args);
+        _this.handleSelectedLanguageChange.apply(assertThisInitialized(_this), args);
       };
 
       player.on(['loadstart', 'texttrackchange'], changeHandler);
         var event;
 
         _this.on(['tap', 'click'], function () {
-          if (typeof window$1.Event !== 'object') {
+          if (typeof window$3.Event !== 'object') {
             // Android 2.3 throws an Illegal Constructor error for window.Event
             try {
-              event = new window$1.Event('change');
+              event = new window$3.Event('change');
             } catch (err) {// continue regardless of error
             }
           }
    * @extends TextTrackMenuItem
    */
 
-  var OffTextTrackMenuItem =
-  /*#__PURE__*/
-  function (_TextTrackMenuItem) {
-    _inheritsLoose(OffTextTrackMenuItem, _TextTrackMenuItem);
+  var OffTextTrackMenuItem = /*#__PURE__*/function (_TextTrackMenuItem) {
+    inheritsLoose(OffTextTrackMenuItem, _TextTrackMenuItem);
 
     /**
      * Creates an instance of this class.
    * @extends MenuButton
    */
 
-  var TextTrackButton =
-  /*#__PURE__*/
-  function (_TrackButton) {
-    _inheritsLoose(TextTrackButton, _TrackButton);
+  var TextTrackButton = /*#__PURE__*/function (_TrackButton) {
+    inheritsLoose(TextTrackButton, _TrackButton);
 
     /**
      * Creates an instance of this class.
    * @extends MenuItem
    */
 
-  var ChaptersTrackMenuItem =
-  /*#__PURE__*/
-  function (_MenuItem) {
-    _inheritsLoose(ChaptersTrackMenuItem, _MenuItem);
+  var ChaptersTrackMenuItem = /*#__PURE__*/function (_MenuItem) {
+    inheritsLoose(ChaptersTrackMenuItem, _MenuItem);
 
     /**
      * Creates an instance of this class.
       _this = _MenuItem.call(this, player, options) || this;
       _this.track = track;
       _this.cue = cue;
-      track.addEventListener('cuechange', bind(_assertThisInitialized(_this), _this.update));
+      track.addEventListener('cuechange', bind(assertThisInitialized(_this), _this.update));
       return _this;
     }
     /**
    * @extends TextTrackButton
    */
 
-  var ChaptersButton =
-  /*#__PURE__*/
-  function (_TextTrackButton) {
-    _inheritsLoose(ChaptersButton, _TextTrackButton);
+  var ChaptersButton = /*#__PURE__*/function (_TextTrackButton) {
+    inheritsLoose(ChaptersButton, _TextTrackButton);
 
     /**
      * Creates an instance of this class.
    * @extends TextTrackButton
    */
 
-  var DescriptionsButton =
-  /*#__PURE__*/
-  function (_TextTrackButton) {
-    _inheritsLoose(DescriptionsButton, _TextTrackButton);
+  var DescriptionsButton = /*#__PURE__*/function (_TextTrackButton) {
+    inheritsLoose(DescriptionsButton, _TextTrackButton);
 
     /**
      * Creates an instance of this class.
 
       _this = _TextTrackButton.call(this, player, options, ready) || this;
       var tracks = player.textTracks();
-      var changeHandler = bind(_assertThisInitialized(_this), _this.handleTracksChange);
+      var changeHandler = bind(assertThisInitialized(_this), _this.handleTracksChange);
       tracks.addEventListener('change', changeHandler);
 
       _this.on('dispose', function () {
    * @extends TextTrackButton
    */
 
-  var SubtitlesButton =
-  /*#__PURE__*/
-  function (_TextTrackButton) {
-    _inheritsLoose(SubtitlesButton, _TextTrackButton);
+  var SubtitlesButton = /*#__PURE__*/function (_TextTrackButton) {
+    inheritsLoose(SubtitlesButton, _TextTrackButton);
 
     /**
      * Creates an instance of this class.
    * @extends TextTrackMenuItem
    */
 
-  var CaptionSettingsMenuItem =
-  /*#__PURE__*/
-  function (_TextTrackMenuItem) {
-    _inheritsLoose(CaptionSettingsMenuItem, _TextTrackMenuItem);
+  var CaptionSettingsMenuItem = /*#__PURE__*/function (_TextTrackMenuItem) {
+    inheritsLoose(CaptionSettingsMenuItem, _TextTrackMenuItem);
 
     /**
      * Creates an instance of this class.
    * @extends TextTrackButton
    */
 
-  var CaptionsButton =
-  /*#__PURE__*/
-  function (_TextTrackButton) {
-    _inheritsLoose(CaptionsButton, _TextTrackButton);
+  var CaptionsButton = /*#__PURE__*/function (_TextTrackButton) {
+    inheritsLoose(CaptionsButton, _TextTrackButton);
 
     /**
      * Creates an instance of this class.
    * @extends TextTrackMenuItem
    */
 
-  var SubsCapsMenuItem =
-  /*#__PURE__*/
-  function (_TextTrackMenuItem) {
-    _inheritsLoose(SubsCapsMenuItem, _TextTrackMenuItem);
+  var SubsCapsMenuItem = /*#__PURE__*/function (_TextTrackMenuItem) {
+    inheritsLoose(SubsCapsMenuItem, _TextTrackMenuItem);
 
     function SubsCapsMenuItem() {
       return _TextTrackMenuItem.apply(this, arguments) || this;
    * @extends TextTrackButton
    */
 
-  var SubsCapsButton =
-  /*#__PURE__*/
-  function (_TextTrackButton) {
-    _inheritsLoose(SubsCapsButton, _TextTrackButton);
+  var SubsCapsButton = /*#__PURE__*/function (_TextTrackButton) {
+    inheritsLoose(SubsCapsButton, _TextTrackButton);
 
     function SubsCapsButton(player, options) {
       var _this;
    * @extends MenuItem
    */
 
-  var AudioTrackMenuItem =
-  /*#__PURE__*/
-  function (_MenuItem) {
-    _inheritsLoose(AudioTrackMenuItem, _MenuItem);
+  var AudioTrackMenuItem = /*#__PURE__*/function (_MenuItem) {
+    inheritsLoose(AudioTrackMenuItem, _MenuItem);
 
     /**
      * Creates an instance of this class.
           args[_key] = arguments[_key];
         }
 
-        _this.handleTracksChange.apply(_assertThisInitialized(_this), args);
+        _this.handleTracksChange.apply(assertThisInitialized(_this), args);
       };
 
       tracks.addEventListener('change', changeHandler);
    * @extends TrackButton
    */
 
-  var AudioTrackButton =
-  /*#__PURE__*/
-  function (_TrackButton) {
-    _inheritsLoose(AudioTrackButton, _TrackButton);
+  var AudioTrackButton = /*#__PURE__*/function (_TrackButton) {
+    inheritsLoose(AudioTrackButton, _TrackButton);
 
     /**
      * Creates an instance of this class.
    * @extends MenuItem
    */
 
-  var PlaybackRateMenuItem =
-  /*#__PURE__*/
-  function (_MenuItem) {
-    _inheritsLoose(PlaybackRateMenuItem, _MenuItem);
+  var PlaybackRateMenuItem = /*#__PURE__*/function (_MenuItem) {
+    inheritsLoose(PlaybackRateMenuItem, _MenuItem);
 
     /**
      * Creates an instance of this class.
    * @extends MenuButton
    */
 
-  var PlaybackRateMenuButton =
-  /*#__PURE__*/
-  function (_MenuButton) {
-    _inheritsLoose(PlaybackRateMenuButton, _MenuButton);
+  var PlaybackRateMenuButton = /*#__PURE__*/function (_MenuButton) {
+    inheritsLoose(PlaybackRateMenuButton, _MenuButton);
 
     /**
      * Creates an instance of this class.
    * @extends Component
    */
 
-  var Spacer =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(Spacer, _Component);
+  var Spacer = /*#__PURE__*/function (_Component) {
+    inheritsLoose(Spacer, _Component);
 
     function Spacer() {
       return _Component.apply(this, arguments) || this;
    * @extends Spacer
    */
 
-  var CustomControlSpacer =
-  /*#__PURE__*/
-  function (_Spacer) {
-    _inheritsLoose(CustomControlSpacer, _Spacer);
+  var CustomControlSpacer = /*#__PURE__*/function (_Spacer) {
+    inheritsLoose(CustomControlSpacer, _Spacer);
 
     function CustomControlSpacer() {
       return _Spacer.apply(this, arguments) || this;
    * @extends Component
    */
 
-  var ControlBar =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(ControlBar, _Component);
+  var ControlBar = /*#__PURE__*/function (_Component) {
+    inheritsLoose(ControlBar, _Component);
 
     function ControlBar() {
       return _Component.apply(this, arguments) || this;
    * @extends ModalDialog
    */
 
-  var ErrorDisplay =
-  /*#__PURE__*/
-  function (_ModalDialog) {
-    _inheritsLoose(ErrorDisplay, _ModalDialog);
+  var ErrorDisplay = /*#__PURE__*/function (_ModalDialog) {
+    inheritsLoose(ErrorDisplay, _ModalDialog);
 
     /**
      * Creates an instance of this class.
    */
 
 
-  ErrorDisplay.prototype.options_ = mergeOptions(ModalDialog.prototype.options_, {
+  ErrorDisplay.prototype.options_ = _extends_1({}, ModalDialog.prototype.options_, {
     pauseOnOpen: false,
     fillAlways: true,
     temporary: false,
    */
 
 
-  var TextTrackSettings =
-  /*#__PURE__*/
-  function (_ModalDialog) {
-    _inheritsLoose(TextTrackSettings, _ModalDialog);
+  var TextTrackSettings = /*#__PURE__*/function (_ModalDialog) {
+    inheritsLoose(TextTrackSettings, _ModalDialog);
 
     /**
      * Creates an instance of this class.
 
       options.temporary = false;
       _this = _ModalDialog.call(this, player, options) || this;
-      _this.updateDisplay = bind(_assertThisInitialized(_this), _this.updateDisplay); // fill the modal and pretend we have opened it
+      _this.updateDisplay = bind(assertThisInitialized(_this), _this.updateDisplay); // fill the modal and pretend we have opened it
 
       _this.fill();
 
       var values;
 
       try {
-        values = JSON.parse(window$1.localStorage.getItem(LOCAL_STORAGE_KEY));
+        values = JSON.parse(window$3.localStorage.getItem(LOCAL_STORAGE_KEY));
       } catch (err) {
         log.warn(err);
       }
 
       try {
         if (Object.keys(values).length) {
-          window$1.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(values));
+          window$3.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(values));
         } else {
-          window$1.localStorage.removeItem(LOCAL_STORAGE_KEY);
+          window$3.localStorage.removeItem(LOCAL_STORAGE_KEY);
         }
       } catch (err) {
         log.warn(err);
    * @extends Component
    */
 
-  var ResizeManager =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(ResizeManager, _Component);
+  var ResizeManager = /*#__PURE__*/function (_Component) {
+    inheritsLoose(ResizeManager, _Component);
 
     /**
      * Create the ResizeManager.
     function ResizeManager(player, options) {
       var _this;
 
-      var RESIZE_OBSERVER_AVAILABLE = options.ResizeObserver || window$1.ResizeObserver; // if `null` was passed, we want to disable the ResizeObserver
+      var RESIZE_OBSERVER_AVAILABLE = options.ResizeObserver || window$3.ResizeObserver; // if `null` was passed, we want to disable the ResizeObserver
 
       if (options.ResizeObserver === null) {
         RESIZE_OBSERVER_AVAILABLE = false;
         reportTouchActivity: false
       }, options);
       _this = _Component.call(this, player, options_) || this;
-      _this.ResizeObserver = options.ResizeObserver || window$1.ResizeObserver;
+      _this.ResizeObserver = options.ResizeObserver || window$3.ResizeObserver;
       _this.loadListener_ = null;
       _this.resizeObserver_ = null;
       _this.debouncedHandler_ = debounce(function () {
         _this.resizeHandler();
-      }, 100, false, _assertThisInitialized(_this));
+      }, 100, false, assertThisInitialized(_this));
 
       if (RESIZE_OBSERVER_AVAILABLE) {
         _this.resizeObserver_ = new _this.ResizeObserver(_this.debouncedHandler_);
     return arr.length % 2 !== 0 ? sortedList[mid] : (sortedList[mid - 1] + sortedList[mid]) / 2;
   };
 
+  var defaults = {
+    // Number of seconds of live window (seekableEnd - seekableStart) that
+    // a video needs to have before the liveui will be shown.
+    trackingThreshold: 30
+  };
   /* track when we are at the live edge, and other helpers for live playback */
 
-  var LiveTracker =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(LiveTracker, _Component);
+  var LiveTracker = /*#__PURE__*/function (_Component) {
+    inheritsLoose(LiveTracker, _Component);
 
     function LiveTracker(player, options) {
       var _this;
 
       // LiveTracker does not need an element
-      var options_ = mergeOptions({
+      var options_ = mergeOptions(defaults, options, {
         createEl: false
-      }, options);
+      });
       _this = _Component.call(this, player, options_) || this;
 
       _this.reset_();
         this.pastSeekEnd_ = 0;
         this.lastSeekEnd_ = newSeekEnd;
         this.trigger('seekableendchange');
-      }
+      } // we should reset pastSeekEnd when the value
+      // is much higher than seeking increment.
 
-      this.pastSeekEnd_ = this.pastSeekEnd() + 0.03;
+
+      if (this.pastSeekEnd() > this.seekableIncrement_ * 1.5) {
+        this.pastSeekEnd_ = 0;
+      } else {
+        this.pastSeekEnd_ = this.pastSeekEnd() + 0.03;
+      }
 
       if (this.isBehind_() !== this.behindLiveEdge()) {
         this.behindLiveEdge_ = this.isBehind_();
     ;
 
     _proto.handleDurationchange = function handleDurationchange() {
-      if (this.player_.duration() === Infinity) {
+      if (this.player_.duration() === Infinity && this.liveWindow() >= this.options_.trackingThreshold) {
+        if (this.player_.options_.liveui) {
+          this.player_.addClass('vjs-liveui');
+        }
+
         this.startTracking();
       } else {
+        this.player_.removeClass('vjs-liveui');
         this.stopTracking();
       }
     }
         this.timeupdateSeen_ = this.player_.hasStarted();
       }
 
-      this.trackingInterval_ = this.setInterval(this.trackLive_, 30);
+      this.trackingInterval_ = this.setInterval(this.trackLive_, UPDATE_REFRESH_INTERVAL);
       this.trackLive_();
       this.on(this.player_, 'play', this.trackLive_);
       this.on(this.player_, 'pause', this.trackLive_); // this is to prevent showing that we are not live
       this.innerText = ''; // now we add all of that html in one by appending the
       // document fragment. This is how innerHTML does it.
 
-      window$1.Element.prototype.appendChild.call(this, docFrag); // then return the result that innerHTML's setter would
+      window$3.Element.prototype.appendChild.call(this, docFrag); // then return the result that innerHTML's setter would
 
       return this.innerHTML;
     }
   };
 
   var getInnerHTMLDescriptor = function getInnerHTMLDescriptor(tech) {
-    return getDescriptor([tech.el(), window$1.HTMLMediaElement.prototype, window$1.Element.prototype, innerHTMLDescriptorPolyfill], 'innerHTML');
+    return getDescriptor([tech.el(), window$3.HTMLMediaElement.prototype, window$3.Element.prototype, innerHTMLDescriptorPolyfill], 'innerHTML');
   };
   /**
    * Patches browser internal functions so that we can tell synchronously
   var srcDescriptorPolyfill = Object.defineProperty({}, 'src', {
     get: function get() {
       if (this.hasAttribute('src')) {
-        return getAbsoluteURL(window$1.Element.prototype.getAttribute.call(this, 'src'));
+        return getAbsoluteURL(window$3.Element.prototype.getAttribute.call(this, 'src'));
       }
 
       return '';
     },
     set: function set(v) {
-      window$1.Element.prototype.setAttribute.call(this, 'src', v);
+      window$3.Element.prototype.setAttribute.call(this, 'src', v);
       return v;
     }
   });
 
   var getSrcDescriptor = function getSrcDescriptor(tech) {
-    return getDescriptor([tech.el(), window$1.HTMLMediaElement.prototype, srcDescriptorPolyfill], 'src');
+    return getDescriptor([tech.el(), window$3.HTMLMediaElement.prototype, srcDescriptorPolyfill], 'src');
   };
   /**
    * setup `sourceset` handling on the `Html5` tech. This function
     };
   };
 
+  /**
+   * Object.defineProperty but "lazy", which means that the value is only set after
+   * it retrieved the first time, rather than being set right away.
+   *
+   * @param {Object} obj the object to set the property on
+   * @param {string} key the key for the property to set
+   * @param {Function} getValue the function used to get the value when it is needed.
+   * @param {boolean} setter wether a setter shoould be allowed or not
+   */
+  var defineLazyProperty = function defineLazyProperty(obj, key, getValue, setter) {
+    if (setter === void 0) {
+      setter = true;
+    }
+
+    var set = function set(value) {
+      return Object.defineProperty(obj, key, {
+        value: value,
+        enumerable: true,
+        writable: true
+      });
+    };
+
+    var options = {
+      configurable: true,
+      enumerable: true,
+      get: function get() {
+        var value = getValue();
+        set(value);
+        return value;
+      }
+    };
+
+    if (setter) {
+      options.set = set;
+    }
+
+    return Object.defineProperty(obj, key, options);
+  };
+
   /**
    * HTML5 Media Controller - Wrapper for HTML5 Media API
    *
    * @extends Tech
    */
 
-  var Html5 =
-  /*#__PURE__*/
-  function (_Tech) {
-    _inheritsLoose(Html5, _Tech);
+  var Html5 = /*#__PURE__*/function (_Tech) {
+    inheritsLoose(Html5, _Tech);
 
     /**
     * Create an instance of this Tech.
 
       var listeners = {
         change: function change(e) {
-          techTracks.trigger({
+          var event = {
             type: 'change',
             target: techTracks,
             currentTarget: techTracks,
             srcElement: techTracks
-          });
+          };
+          techTracks.trigger(event); // if we are a text track change event, we should also notify the
+          // remote text track list. This can potentially cause a false positive
+          // if we were to get a change event on a non-remote track and
+          // we triggered the event on the remote text track list which doesn't
+          // contain that track. However, best practices mean looping through the
+          // list of tracks and searching for the appropriate mode value, so,
+          // this shouldn't pose an issue
+
+          if (name === 'text') {
+            _this3[REMOTE.remoteText.getterName]().trigger(event);
+          }
         },
         addtrack: function addtrack(e) {
           techTracks.addTrack(e.track);
 
     _proto.supportsFullScreen = function supportsFullScreen() {
       if (typeof this.el_.webkitEnterFullScreen === 'function') {
-        var userAgent = window$1.navigator && window$1.navigator.userAgent || ''; // Seems to be broken in Chromium/Chrome && Safari in Leopard
+        var userAgent = window$3.navigator && window$3.navigator.userAgent || ''; // Seems to be broken in Chromium/Chrome && Safari in Leopard
 
         if (/Android/.test(userAgent) || !/Chrome|Mac OS X 10.5/.test(userAgent)) {
           return true;
         videoPlaybackQuality.totalVideoFrames = this.el().webkitDecodedFrameCount;
       }
 
-      if (window$1.performance && typeof window$1.performance.now === 'function') {
-        videoPlaybackQuality.creationTime = window$1.performance.now();
-      } else if (window$1.performance && window$1.performance.timing && typeof window$1.performance.timing.navigationStart === 'number') {
-        videoPlaybackQuality.creationTime = window$1.Date.now() - window$1.performance.timing.navigationStart;
+      if (window$3.performance && typeof window$3.performance.now === 'function') {
+        videoPlaybackQuality.creationTime = window$3.performance.now();
+      } else if (window$3.performance && window$3.performance.timing && typeof window$3.performance.timing.navigationStart === 'number') {
+        videoPlaybackQuality.creationTime = window$3.Date.now() - window$3.performance.timing.navigationStart;
       }
 
       return videoPlaybackQuality;
   }(Tech);
   /* HTML5 Support Testing ---------------------------------------------------- */
 
+  /**
+   * Element for testing browser HTML5 media capabilities
+   *
+   * @type {Element}
+   * @constant
+   * @private
+   */
 
-  if (isReal()) {
-    /**
-     * Element for testing browser HTML5 media capabilities
-     *
-     * @type {Element}
-     * @constant
-     * @private
-     */
-    Html5.TEST_VID = document.createElement('video');
+
+  defineLazyProperty(Html5, 'TEST_VID', function () {
+    if (!isReal()) {
+      return;
+    }
+
+    var video = document.createElement('video');
     var track = document.createElement('track');
     track.kind = 'captions';
     track.srclang = 'en';
     track.label = 'English';
-    Html5.TEST_VID.appendChild(track);
-  }
+    video.appendChild(track);
+    return video;
+  });
   /**
    * Check if HTML5 media is supported by this browser/device.
    *
    *         - False if HTML5 media is not supported.
    */
 
-
   Html5.isSupported = function () {
     // IE with no Media Player is a LIAR! (#984)
     try {
    * @default {@link Html5.canControlVolume}
    */
 
-  Html5.prototype.featuresVolumeControl = Html5.canControlVolume();
   /**
    * Boolean indicating whether the `Tech` supports muting volume.
    *
    * @default {@link Html5.canMuteVolume}
    */
 
-  Html5.prototype.featuresMuteControl = Html5.canMuteVolume();
   /**
    * Boolean indicating whether the `Tech` supports changing the speed at which the media
    * plays. Examples:
    * @default {@link Html5.canControlPlaybackRate}
    */
 
-  Html5.prototype.featuresPlaybackRate = Html5.canControlPlaybackRate();
   /**
    * Boolean indicating whether the `Tech` supports the `sourceset` event.
    *
    * @default
    */
 
-  Html5.prototype.featuresSourceset = Html5.canOverrideAttributes();
+  /**
+   * Boolean indicating whether the `HTML5` tech currently supports native `TextTrack`s.
+   *
+   * @type {boolean}
+   * @default {@link Html5.supportsNativeTextTracks}
+   */
+
+  /**
+   * Boolean indicating whether the `HTML5` tech currently supports native `VideoTrack`s.
+   *
+   * @type {boolean}
+   * @default {@link Html5.supportsNativeVideoTracks}
+   */
+
+  /**
+   * Boolean indicating whether the `HTML5` tech currently supports native `AudioTrack`s.
+   *
+   * @type {boolean}
+   * @default {@link Html5.supportsNativeAudioTracks}
+   */
+
+  [['featuresVolumeControl', 'canControlVolume'], ['featuresMuteControl', 'canMuteVolume'], ['featuresPlaybackRate', 'canControlPlaybackRate'], ['featuresSourceset', 'canOverrideAttributes'], ['featuresNativeTextTracks', 'supportsNativeTextTracks'], ['featuresNativeVideoTracks', 'supportsNativeVideoTracks'], ['featuresNativeAudioTracks', 'supportsNativeAudioTracks']].forEach(function (_ref) {
+    var key = _ref[0],
+        fn = _ref[1];
+    defineLazyProperty(Html5.prototype, key, function () {
+      return Html5[fn]();
+    }, true);
+  });
   /**
    * Boolean indicating whether the `HTML5` tech currently supports the media element
    * moving in the DOM. iOS breaks if you move the media element, so this is set this to
    * @default
    */
 
-  Html5.prototype.featuresTimeupdateEvents = true;
-  /**
-   * Boolean indicating whether the `HTML5` tech currently supports native `TextTrack`s.
-   *
-   * @type {boolean}
-   * @default {@link Html5.supportsNativeTextTracks}
-   */
-
-  Html5.prototype.featuresNativeTextTracks = Html5.supportsNativeTextTracks();
-  /**
-   * Boolean indicating whether the `HTML5` tech currently supports native `VideoTrack`s.
-   *
-   * @type {boolean}
-   * @default {@link Html5.supportsNativeVideoTracks}
-   */
-
-  Html5.prototype.featuresNativeVideoTracks = Html5.supportsNativeVideoTracks();
-  /**
-   * Boolean indicating whether the `HTML5` tech currently supports native `AudioTrack`s.
-   *
-   * @type {boolean}
-   * @default {@link Html5.supportsNativeAudioTracks}
-   */
-
-  Html5.prototype.featuresNativeAudioTracks = Html5.supportsNativeAudioTracks(); // HTML5 Feature detection and Device Fixes --------------------------------- //
+  Html5.prototype.featuresTimeupdateEvents = true; // HTML5 Feature detection and Device Fixes --------------------------------- //
 
-  var canPlayType = Html5.TEST_VID && Html5.TEST_VID.constructor.prototype.canPlayType;
-  var mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i;
+  var canPlayType;
 
   Html5.patchCanPlayType = function () {
     // Android 4.0 and above can play HLS to some extent but it reports being unable to do so
     // Firefox and Chrome report correctly
     if (ANDROID_VERSION >= 4.0 && !IS_FIREFOX && !IS_CHROME) {
+      canPlayType = Html5.TEST_VID && Html5.TEST_VID.constructor.prototype.canPlayType;
+
       Html5.TEST_VID.constructor.prototype.canPlayType = function (type) {
+        var mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i;
+
         if (type && mpegurlRE.test(type)) {
           return 'maybe';
         }
 
   Html5.unpatchCanPlayType = function () {
     var r = Html5.TEST_VID.constructor.prototype.canPlayType;
-    Html5.TEST_VID.constructor.prototype.canPlayType = canPlayType;
+
+    if (canPlayType) {
+      Html5.TEST_VID.constructor.prototype.canPlayType = canPlayType;
+    }
+
     return r;
   }; // by default, patch the media element
 
    * @extends Component
    */
 
-  var Player =
-  /*#__PURE__*/
-  function (_Component) {
-    _inheritsLoose(Player, _Component);
+  var Player = /*#__PURE__*/function (_Component) {
+    inheritsLoose(Player, _Component);
 
     /**
      * Create an instance of this class.
 
       _this = _Component.call(this, null, options, ready) || this; // Create bound methods for document listeners.
 
-      _this.boundDocumentFullscreenChange_ = bind(_assertThisInitialized(_this), _this.documentFullscreenChange_);
-      _this.boundFullWindowOnEscKey_ = bind(_assertThisInitialized(_this), _this.fullWindowOnEscKey); // create logger
+      _this.boundDocumentFullscreenChange_ = bind(assertThisInitialized(_this), _this.documentFullscreenChange_);
+      _this.boundFullWindowOnEscKey_ = bind(assertThisInitialized(_this), _this.fullWindowOnEscKey); // default isFullscreen_ to false
+
+      _this.isFullscreen_ = false; // create logger
 
       _this.log = createLogger$1(_this.id_); // Hold our own reference to fullscreen api so it can be mocked in tests
 
       _this.scrubbing_ = false;
       _this.el_ = _this.createEl(); // Make this an evented object and use `el_` as its event bus.
 
-      evented(_assertThisInitialized(_this), {
+      evented(assertThisInitialized(_this), {
         eventBusKey: 'el_'
-      });
+      }); // listen to document and player fullscreenchange handlers so we receive those events
+      // before a user can receive them so we can update isFullscreen appropriately.
+      // make sure that we listen to fullscreenchange events before everything else to make sure that
+      // our isFullscreen method is updated properly for internal components as well as external.
+
+      if (_this.fsApi_.requestFullscreen) {
+        on(document, _this.fsApi_.fullscreenchange, _this.boundDocumentFullscreenChange_);
+
+        _this.on(_this.fsApi_.fullscreenchange, _this.boundDocumentFullscreenChange_);
+      }
 
       if (_this.fluid_) {
         _this.on('playerreset', _this.updateStyleEl_);
       } // Make player easily findable by ID
 
 
-      Player.players[_this.id_] = _assertThisInitialized(_this); // Add a major version class to aid css in plugins
+      Player.players[_this.id_] = assertThisInitialized(_this); // Add a major version class to aid css in plugins
 
       var majorVersion = version.split('.')[0];
 
         // was initialized.
 
         Object.keys(el).forEach(function (k) {
-          tag[k] = el[k];
+          try {
+            tag[k] = el[k];
+          } catch (e) {// we got a a property like outerHTML which we can't actually copy, ignore it
+          }
         });
       } // set tabindex to -1 to remove the video element from the focus order
 
       // of the player in a way that's still overrideable by CSS, just like the
       // video element
 
-      if (window$1.VIDEOJS_NO_DYNAMIC_STYLE !== true) {
+      if (window$3.VIDEOJS_NO_DYNAMIC_STYLE !== true) {
         this.styleEl_ = createStyleElement('vjs-styles-dimensions');
         var defaultsStyleEl = $('.vjs-styles-defaults');
         var head = $('head');
         return this[privDimension] || 0;
       }
 
-      if (value === '') {
+      if (value === '' || value === 'auto') {
         // If an empty string is given, reset the dimension to be automatic
         this[privDimension] = undefined;
         this.updateStyleEl_();
     ;
 
     _proto.updateStyleEl_ = function updateStyleEl_() {
-      if (window$1.VIDEOJS_NO_DYNAMIC_STYLE === true) {
+      if (window$3.VIDEOJS_NO_DYNAMIC_STYLE === true) {
         var _width = typeof this.width_ === 'number' ? this.width_ : this.options_.width;
 
         var _height = typeof this.height_ === 'number' ? this.height_ : this.options_.height;
     ;
 
     _proto.documentFullscreenChange_ = function documentFullscreenChange_(e) {
+      var targetPlayer = e.target.player; // if another player was fullscreen
+      // do a null check for targetPlayer because older firefox's would put document as e.target
+
+      if (targetPlayer && targetPlayer !== this) {
+        return;
+      }
+
       var el = this.el();
       var isFs = document[this.fsApi_.fullscreenElement] === el;
 
         isFs = el.msMatchesSelector(':' + this.fsApi_.fullscreen);
       }
 
-      this.isFullscreen(isFs); // If cancelling fullscreen, remove event listener.
-
-      if (this.isFullscreen() === false) {
-        off(document, this.fsApi_.fullscreenchange, this.boundDocumentFullscreenChange_);
-      }
-
-      if (this.fsApi_.prefixed) {
-        /**
-         * @event Player#fullscreenchange
-         * @type {EventTarget~Event}
-         */
-        this.trigger('fullscreenchange');
-      }
+      this.isFullscreen(isFs);
     }
     /**
      * Handle Tech Fullscreen Change
       if (data) {
         this.isFullscreen(data.isFullscreen);
       }
-      /**
-       * Fired when going in and out of fullscreen.
-       *
-       * @event Player#fullscreenchange
-       * @type {EventTarget~Event}
-       */
-
-
-      this.trigger('fullscreenchange');
     }
     /**
      * @private
     _proto.play = function play() {
       var _this8 = this;
 
-      var PromiseClass = this.options_.Promise || window$1.Promise;
+      var PromiseClass = this.options_.Promise || window$3.Promise;
 
       if (PromiseClass) {
         return new PromiseClass(function (resolve) {
 
         if (seconds === Infinity) {
           this.addClass('vjs-live');
-
-          if (this.options_.liveui && this.player_.liveTracker) {
-            this.addClass('vjs-liveui');
-          }
         } else {
           this.removeClass('vjs-live');
-          this.removeClass('vjs-liveui');
         }
 
         if (!isNaN(seconds)) {
 
     _proto.isFullscreen = function isFullscreen(isFS) {
       if (isFS !== undefined) {
-        this.isFullscreen_ = !!isFS;
+        var oldValue = this.isFullscreen_;
+        this.isFullscreen_ = Boolean(isFS); // if we changed fullscreen state and we're in prefixed mode, trigger fullscreenchange
+        // this is the only place where we trigger fullscreenchange events for older browsers
+        // fullWindow mode is treated as a prefixed event and will get a fullscreenchange event as well
+
+        if (this.isFullscreen_ !== oldValue && this.fsApi_.prefixed) {
+          /**
+             * @event Player#fullscreenchange
+             * @type {EventTarget~Event}
+             */
+          this.trigger('fullscreenchange');
+        }
+
         this.toggleFullscreenClass_();
         return;
       }
 
-      return !!this.isFullscreen_;
+      return this.isFullscreen_;
     }
     /**
      * Increase the size of the video to full screen
     ;
 
     _proto.requestFullscreen = function requestFullscreen(fullscreenOptions) {
-      var fsOptions;
-      this.isFullscreen(true);
+      var _this10 = this;
 
-      if (this.fsApi_.requestFullscreen) {
-        // the browser supports going fullscreen at the element level so we can
-        // take the controls fullscreen as well as the video
-        // Trigger fullscreenchange event after change
-        // We have to specifically add this each time, and remove
-        // when canceling fullscreen. Otherwise if there's multiple
-        // players on a page, they would all be reacting to the same fullscreen
-        // events
-        on(document, this.fsApi_.fullscreenchange, this.boundDocumentFullscreenChange_); // only pass FullscreenOptions to requestFullscreen if it isn't prefixed
+      var fsOptions; // Only pass fullscreen options to requestFullscreen in spec-compliant browsers.
+      // Use defaults or player configured option unless passed directly to this method.
 
-        if (!this.fsApi_.prefixed) {
-          fsOptions = this.options_.fullscreen && this.options_.fullscreen.options || {};
+      if (!this.fsApi_.prefixed) {
+        fsOptions = this.options_.fullscreen && this.options_.fullscreen.options || {};
 
-          if (fullscreenOptions !== undefined) {
-            fsOptions = fullscreenOptions;
-          }
+        if (fullscreenOptions !== undefined) {
+          fsOptions = fullscreenOptions;
+        }
+      } // This method works as follows:
+      // 1. if a fullscreen api is available, use it
+      //   1. call requestFullscreen with potential options
+      //   2. if we got a promise from above, use it to update isFullscreen()
+      // 2. otherwise, if the tech supports fullscreen, call `enterFullScreen` on it.
+      //   This is particularly used for iPhone, older iPads, and non-safari browser on iOS.
+      // 3. otherwise, use "fullWindow" mode
+
+
+      if (this.fsApi_.requestFullscreen) {
+        var promise = this.el_[this.fsApi_.requestFullscreen](fsOptions);
+
+        if (promise) {
+          promise.then(function () {
+            return _this10.isFullscreen(true);
+          }, function () {
+            return _this10.isFullscreen(false);
+          });
         }
 
-        silencePromise(this.el_[this.fsApi_.requestFullscreen](fsOptions));
+        return promise;
       } else if (this.tech_.supportsFullScreen()) {
         // we can't take the video.js controls fullscreen but we can go fullscreen
         // with native controls
         // fullscreen isn't supported so we'll just stretch the video element to
         // fill the viewport
         this.enterFullWindow();
-        /**
-         * @event Player#fullscreenchange
-         * @type {EventTarget~Event}
-         */
-
-        this.trigger('fullscreenchange');
       }
     }
     /**
     ;
 
     _proto.exitFullscreen = function exitFullscreen() {
-      this.isFullscreen(false); // Check for browser element fullscreen support
+      var _this11 = this;
 
       if (this.fsApi_.requestFullscreen) {
-        silencePromise(document[this.fsApi_.exitFullscreen]());
+        var promise = document[this.fsApi_.exitFullscreen]();
+
+        if (promise) {
+          promise.then(function () {
+            return _this11.isFullscreen(false);
+          });
+        }
+
+        return promise;
       } else if (this.tech_.supportsFullScreen()) {
         this.techCall_('exitFullScreen');
       } else {
         this.exitFullWindow();
-        /**
-         * @event Player#fullscreenchange
-         * @type {EventTarget~Event}
-         */
-
-        this.trigger('fullscreenchange');
       }
     }
     /**
     ;
 
     _proto.enterFullWindow = function enterFullWindow() {
+      this.isFullscreen(true);
       this.isFullWindow = true; // Storing original doc overflow value to return to when fullscreen is off
 
       this.docOrigOverflow = document.documentElement.style.overflow; // Add listener for esc key to exit fullscreen
     ;
 
     _proto.exitFullWindow = function exitFullWindow() {
+      this.isFullscreen(false);
       this.isFullWindow = false;
       off(document, 'keydown', this.boundFullWindowOnEscKey_); // Unhide scroll bars.
 
     ;
 
     _proto.selectSource = function selectSource(sources) {
-      var _this10 = this;
+      var _this12 = this;
 
       // Get only the techs specified in `techOrder` that exist and are supported by the
       // current platform
         var techName = _ref2[0],
             tech = _ref2[1];
 
-        if (tech.canPlaySource(source, _this10.options_[techName.toLowerCase()])) {
+        if (tech.canPlaySource(source, _this12.options_[techName.toLowerCase()])) {
           return {
             source: source,
             tech: techName
     ;
 
     _proto.src = function src(source) {
-      var _this11 = this;
+      var _this13 = this;
 
       // getter usage
       if (typeof source === 'undefined') {
       this.updateSourceCaches_(sources[0]); // middlewareSource is the source after it has been changed by middleware
 
       setSource(this, sources[0], function (middlewareSource, mws) {
-        _this11.middleware_ = mws; // since sourceSet is async we have to update the cache again after we select a source since
+        _this13.middleware_ = mws; // since sourceSet is async we have to update the cache again after we select a source since
         // the source that is selected could be out of order from the cache update above this callback.
 
-        _this11.cache_.sources = sources;
+        _this13.cache_.sources = sources;
 
-        _this11.updateSourceCaches_(middlewareSource);
+        _this13.updateSourceCaches_(middlewareSource);
 
-        var err = _this11.src_(middlewareSource);
+        var err = _this13.src_(middlewareSource);
 
         if (err) {
           if (sources.length > 1) {
-            return _this11.src(sources.slice(1));
+            return _this13.src(sources.slice(1));
           }
 
-          _this11.changingSrc_ = false; // We need to wrap this in a timeout to give folks a chance to add error event handlers
+          _this13.changingSrc_ = false; // We need to wrap this in a timeout to give folks a chance to add error event handlers
 
-          _this11.setTimeout(function () {
+          _this13.setTimeout(function () {
             this.error({
               code: 4,
               message: this.localize(this.options_.notSupportedMessage)
           // this needs a better comment about why this is needed
 
 
-          _this11.triggerReady();
+          _this13.triggerReady();
 
           return;
         }
 
-        setTech(mws, _this11.tech_);
+        setTech(mws, _this13.tech_);
       });
     }
     /**
     ;
 
     _proto.src_ = function src_(source) {
-      var _this12 = this;
+      var _this14 = this;
 
       var sourceTech = this.selectSource([source]);
 
 
         this.loadTech_(sourceTech.tech, sourceTech.source);
         this.tech_.ready(function () {
-          _this12.changingSrc_ = false;
+          _this14.changingSrc_ = false;
         });
         return false;
       } // wait until the tech is ready to set the source
     ;
 
     _proto.reset = function reset() {
-      var _this13 = this;
+      var _this15 = this;
 
-      var PromiseClass = this.options_.Promise || window$1.Promise;
+      var PromiseClass = this.options_.Promise || window$3.Promise;
 
       if (this.paused() || !PromiseClass) {
         this.doReset_();
       } else {
         var playPromise = this.play();
         silencePromise(playPromise.then(function () {
-          return _this13.doReset_();
+          return _this15.doReset_();
         }));
       }
     };
       // user interaction
 
 
-      if (this.options_.suppressNotSupportedError && err && err.message && err.message === this.localize(this.options_.notSupportedMessage)) {
+      if (this.options_.suppressNotSupportedError && err && err.code === 4) {
         var triggerSuppressedError = function triggerSuppressedError() {
           this.error(err);
         };
         mouseInProgress = this.setInterval(handleActivity, 250);
       };
 
-      var handleMouseUp = function handleMouseUp(event) {
+      var handleMouseUpAndMouseLeave = function handleMouseUpAndMouseLeave(event) {
         handleActivity(); // Stop the interval that maintains activity if the mouse/touch is down
 
         this.clearInterval(mouseInProgress);
 
       this.on('mousedown', handleMouseDown);
       this.on('mousemove', handleMouseMove);
-      this.on('mouseup', handleMouseUp);
+      this.on('mouseup', handleMouseUpAndMouseLeave);
+      this.on('mouseleave', handleMouseUpAndMouseLeave);
       var controlBar = this.getChild('controlBar'); // Fixes bug on Android & iOS where when tapping progressBar (when control bar is displayed)
       // controlBar would no longer be hidden by default timeout.
 
       }
     }
     /**
-     * Create a remote {@link TextTrack} and an {@link HTMLTrackElement}. It will
-     * automatically removed from the video element whenever the source changes, unless
-     * manualCleanup is set to false.
+     * Create a remote {@link TextTrack} and an {@link HTMLTrackElement}.
+     * When manualCleanup is set to false, the track will be automatically removed
+     * on source changes.
      *
      * @param {Object} options
      *        Options to pass to {@link HTMLTrackElement} during creation. See
      *        {@link HTMLTrackElement} for object properties that you should use.
      *
      * @param {boolean} [manualCleanup=true] if set to false, the TextTrack will be
+     *                                       removed on a source change
      *
      * @return {HtmlTrackElement}
      *         the HTMLTrackElement that was created and added
     ;
 
     _proto.createModal = function createModal(content, options) {
-      var _this14 = this;
+      var _this16 = this;
 
       options = options || {};
       options.content = content || '';
       var modal = new ModalDialog(this, options);
       this.addChild(modal);
       modal.on('dispose', function () {
-        _this14.removeChild(modal);
+        _this16.removeChild(modal);
       });
       modal.open();
       return modal;
     ;
 
     _proto.loadMedia = function loadMedia(media, ready) {
-      var _this15 = this;
+      var _this17 = this;
 
       if (!media || typeof media !== 'object') {
         return;
 
       if (Array.isArray(textTracks)) {
         textTracks.forEach(function (tt) {
-          return _this15.addRemoteTextTrack(tt, false);
+          return _this17.addRemoteTextTrack(tt, false);
         });
       }
 
    */
 
   Player.players = {};
-  var navigator = window$1.navigator;
+  var navigator = window$3.navigator;
   /*
    * Player instance options, surfaced using options
    * options = Player.prototype.options_
 
   Component.registerComponent('Player', Player);
 
+  var setPrototypeOf = createCommonjsModule(function (module) {
+    function _setPrototypeOf(o, p) {
+      module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
+        o.__proto__ = p;
+        return o;
+      };
+
+      return _setPrototypeOf(o, p);
+    }
+
+    module.exports = _setPrototypeOf;
+  });
+
+  function _isNativeReflectConstruct() {
+    if (typeof Reflect === "undefined" || !Reflect.construct) return false;
+    if (Reflect.construct.sham) return false;
+    if (typeof Proxy === "function") return true;
+
+    try {
+      Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
+      return true;
+    } catch (e) {
+      return false;
+    }
+  }
+
+  var isNativeReflectConstruct = _isNativeReflectConstruct;
+
+  var construct = createCommonjsModule(function (module) {
+    function _construct(Parent, args, Class) {
+      if (isNativeReflectConstruct()) {
+        module.exports = _construct = Reflect.construct;
+      } else {
+        module.exports = _construct = function _construct(Parent, args, Class) {
+          var a = [null];
+          a.push.apply(a, args);
+          var Constructor = Function.bind.apply(Parent, a);
+          var instance = new Constructor();
+          if (Class) setPrototypeOf(instance, Class.prototype);
+          return instance;
+        };
+      }
+
+      return _construct.apply(null, arguments);
+    }
+
+    module.exports = _construct;
+  });
+
   /**
    * The base plugin name.
    *
         args[_key] = arguments[_key];
       }
 
-      var instance = _construct(PluginSubClass, [this].concat(args)); // The plugin is replaced by a function that returns the current instance.
+      var instance = construct(PluginSubClass, [this].concat(args)); // The plugin is replaced by a function that returns the current instance.
 
 
       this[name] = function () {
    */
 
 
-  var Plugin =
-  /*#__PURE__*/
-  function () {
+  var Plugin = /*#__PURE__*/function () {
     /**
      * Creates an instance of this class.
      *
    *           plugin class/constructor.
    */
 
-  /**
-   * @file extend.js
-   * @module extend
-   */
-
-  /**
-   * A combination of node inherits and babel's inherits (after transpile).
-   * Both work the same but node adds `super_` to the subClass
-   * and Bable adds the superClass as __proto__. Both seem useful.
-   *
-   * @param {Object} subClass
-   *        The class to inherit to
-   *
-   * @param {Object} superClass
-   *        The class to inherit from
-   *
-   * @private
-   */
-  var _inherits = 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);
+  function _inherits(subClass, superClass) {
+    if (typeof superClass !== "function" && superClass !== null) {
+      throw new TypeError("Super expression must either be null or a function");
     }
 
     subClass.prototype = Object.create(superClass && superClass.prototype, {
       constructor: {
         value: subClass,
-        enumerable: false,
         writable: true,
         configurable: true
       }
     });
+    if (superClass) setPrototypeOf(subClass, superClass);
+  }
 
-    if (superClass) {
-      // node
-      subClass.super_ = superClass;
-    }
-  };
+  var inherits = _inherits;
+
+  /**
+   * @file extend.js
+   * @module extend
+   */
   /**
    * Used to subclass an existing class by emulating ES subclassing using the
    * `extends` keyword.
    *           The new class with subClassMethods that inherited superClass.
    */
 
-
-  var extend$1 = function extend(superClass, subClassMethods) {
+  var extend = function extend(superClass, subClassMethods) {
     if (subClassMethods === void 0) {
       subClassMethods = {};
     }
       subClass = subClassMethods;
     }
 
-    _inherits(subClass, superClass); // Extend subObj's prototype with functions and other properties from props
+    inherits(subClass, superClass); // this is needed for backward-compatibility and node compatibility.
+
+
+    if (superClass) {
+      subClass.super_ = superClass;
+    } // Extend subObj's prototype with functions and other properties from props
 
 
     for (var name in methods) {
   }; // Add default styles
 
 
-  if (window$1.VIDEOJS_NO_DYNAMIC_STYLE !== true && isReal()) {
+  if (window$3.VIDEOJS_NO_DYNAMIC_STYLE !== true && isReal()) {
     var style = $('.vjs-styles-defaults');
 
     if (!style) {
    */
 
   videojs$1.TOUCH_ENABLED = TOUCH_ENABLED;
-  videojs$1.extend = extend$1;
+  videojs$1.extend = extend;
   videojs$1.mergeOptions = mergeOptions;
   videojs$1.bind = bind;
   videojs$1.registerPlugin = Plugin.registerPlugin;
    */
 
   videojs$1.url = Url;
+  videojs$1.defineLazyProperty = defineLazyProperty;
 
   var urlToolkit = createCommonjsModule(function (module, exports) {
     // see https://tools.ietf.org/html/rfc1808
    */
 
 
-  var Stream =
-  /*#__PURE__*/
-  function () {
+  var Stream = /*#__PURE__*/function () {
     function Stream() {
       this.listeners = {};
     }
    */
 
 
-  var LineStream =
-  /*#__PURE__*/
-  function (_Stream) {
+  var LineStream = /*#__PURE__*/function (_Stream) {
     _inheritsLoose$1(LineStream, _Stream);
 
     function LineStream() {
    */
 
 
-  var ParseStream =
-  /*#__PURE__*/
-  function (_Stream) {
+  var ParseStream = /*#__PURE__*/function (_Stream) {
     _inheritsLoose$1(ParseStream, _Stream);
 
     function ParseStream() {
   }(Stream);
 
   function decodeB64ToUint8Array(b64Text) {
-    var decodedString = window$1.atob(b64Text || '');
+    var decodedString = window$3.atob(b64Text || '');
     var array = new Uint8Array(decodedString.length);
 
     for (var i = 0; i < decodedString.length; i++) {
    */
 
 
-  var Parser =
-  /*#__PURE__*/
-  function (_Stream) {
+  var Parser = /*#__PURE__*/function (_Stream) {
     _inheritsLoose$1(Parser, _Stream);
 
     function Parser() {
                   currentMap.uri = entry.uri;
                 }
 
-                if (entry.byterange) {
-                  currentMap.byterange = entry.byterange;
-                }
-              },
-              'stream-inf': function streamInf() {
-                this.manifest.playlists = uris;
-                this.manifest.mediaGroups = this.manifest.mediaGroups || defaultMediaGroups;
+                if (entry.byterange) {
+                  currentMap.byterange = entry.byterange;
+                }
+              },
+              'stream-inf': function streamInf() {
+                this.manifest.playlists = uris;
+                this.manifest.mediaGroups = this.manifest.mediaGroups || defaultMediaGroups;
+
+                if (!entry.attributes) {
+                  this.trigger('warn', {
+                    message: 'ignoring empty stream-inf attributes'
+                  });
+                  return;
+                }
+
+                if (!currentUri.attributes) {
+                  currentUri.attributes = {};
+                }
+
+                _extends(currentUri.attributes, entry.attributes);
+              },
+              media: function media() {
+                this.manifest.mediaGroups = this.manifest.mediaGroups || defaultMediaGroups;
+
+                if (!(entry.attributes && entry.attributes.TYPE && entry.attributes['GROUP-ID'] && entry.attributes.NAME)) {
+                  this.trigger('warn', {
+                    message: 'ignoring incomplete or missing media group'
+                  });
+                  return;
+                } // find the media group, creating defaults as necessary
+
+
+                var mediaGroupType = this.manifest.mediaGroups[entry.attributes.TYPE];
+                mediaGroupType[entry.attributes['GROUP-ID']] = mediaGroupType[entry.attributes['GROUP-ID']] || {};
+                mediaGroup = mediaGroupType[entry.attributes['GROUP-ID']]; // collect the rendition metadata
+
+                rendition = {
+                  "default": /yes/i.test(entry.attributes.DEFAULT)
+                };
+
+                if (rendition["default"]) {
+                  rendition.autoselect = true;
+                } else {
+                  rendition.autoselect = /yes/i.test(entry.attributes.AUTOSELECT);
+                }
+
+                if (entry.attributes.LANGUAGE) {
+                  rendition.language = entry.attributes.LANGUAGE;
+                }
+
+                if (entry.attributes.URI) {
+                  rendition.uri = entry.attributes.URI;
+                }
+
+                if (entry.attributes['INSTREAM-ID']) {
+                  rendition.instreamId = entry.attributes['INSTREAM-ID'];
+                }
+
+                if (entry.attributes.CHARACTERISTICS) {
+                  rendition.characteristics = entry.attributes.CHARACTERISTICS;
+                }
+
+                if (entry.attributes.FORCED) {
+                  rendition.forced = /yes/i.test(entry.attributes.FORCED);
+                } // insert the new rendition
+
+
+                mediaGroup[entry.attributes.NAME] = rendition;
+              },
+              discontinuity: function discontinuity() {
+                currentTimeline += 1;
+                currentUri.discontinuity = true;
+                this.manifest.discontinuityStarts.push(uris.length);
+              },
+              'program-date-time': function programDateTime() {
+                if (typeof this.manifest.dateTimeString === 'undefined') {
+                  // PROGRAM-DATE-TIME is a media-segment tag, but for backwards
+                  // compatibility, we add the first occurence of the PROGRAM-DATE-TIME tag
+                  // to the manifest object
+                  // TODO: Consider removing this in future major version
+                  this.manifest.dateTimeString = entry.dateTimeString;
+                  this.manifest.dateTimeObject = entry.dateTimeObject;
+                }
+
+                currentUri.dateTimeString = entry.dateTimeString;
+                currentUri.dateTimeObject = entry.dateTimeObject;
+              },
+              targetduration: function targetduration() {
+                if (!isFinite(entry.duration) || entry.duration < 0) {
+                  this.trigger('warn', {
+                    message: 'ignoring invalid target duration: ' + entry.duration
+                  });
+                  return;
+                }
+
+                this.manifest.targetDuration = entry.duration;
+              },
+              totalduration: function totalduration() {
+                if (!isFinite(entry.duration) || entry.duration < 0) {
+                  this.trigger('warn', {
+                    message: 'ignoring invalid total duration: ' + entry.duration
+                  });
+                  return;
+                }
+
+                this.manifest.totalDuration = entry.duration;
+              },
+              start: function start() {
+                if (!entry.attributes || isNaN(entry.attributes['TIME-OFFSET'])) {
+                  this.trigger('warn', {
+                    message: 'ignoring start declaration without appropriate attribute list'
+                  });
+                  return;
+                }
+
+                this.manifest.start = {
+                  timeOffset: entry.attributes['TIME-OFFSET'],
+                  precise: entry.attributes.PRECISE
+                };
+              },
+              'cue-out': function cueOut() {
+                currentUri.cueOut = entry.data;
+              },
+              'cue-out-cont': function cueOutCont() {
+                currentUri.cueOutCont = entry.data;
+              },
+              'cue-in': function cueIn() {
+                currentUri.cueIn = entry.data;
+              }
+            })[entry.tagType] || noop).call(self);
+          },
+          uri: function uri() {
+            currentUri.uri = entry.uri;
+            uris.push(currentUri); // if no explicit duration was declared, use the target duration
+
+            if (this.manifest.targetDuration && !('duration' in currentUri)) {
+              this.trigger('warn', {
+                message: 'defaulting segment duration to the target duration'
+              });
+              currentUri.duration = this.manifest.targetDuration;
+            } // annotate with encryption information, if necessary
+
+
+            if (_key) {
+              currentUri.key = _key;
+            }
+
+            currentUri.timeline = currentTimeline; // annotate with initialization segment information, if necessary
+
+            if (currentMap) {
+              currentUri.map = currentMap;
+            } // prepare for the next URI
+
+
+            currentUri = {};
+          },
+          comment: function comment() {// comments are not important for playback
+          },
+          custom: function custom() {
+            // if this is segment-level data attach the output to the segment
+            if (entry.segment) {
+              currentUri.custom = currentUri.custom || {};
+              currentUri.custom[entry.customType] = entry.data; // if this is manifest-level data attach to the top level manifest object
+            } else {
+              this.manifest.custom = this.manifest.custom || {};
+              this.manifest.custom[entry.customType] = entry.data;
+            }
+          }
+        })[entry.type].call(self);
+      });
+
+      return _this;
+    }
+    /**
+     * Parse the input string and update the manifest object.
+     *
+     * @param {string} chunk a potentially incomplete portion of the manifest
+     */
+
+
+    var _proto = Parser.prototype;
+
+    _proto.push = function push(chunk) {
+      this.lineStream.push(chunk);
+    }
+    /**
+     * Flush any remaining input. This can be handy if the last line of an M3U8
+     * manifest did not contain a trailing newline but the file has been
+     * completely received.
+     */
+    ;
+
+    _proto.end = function end() {
+      // flush any buffered input
+      this.lineStream.push('\n');
+    }
+    /**
+     * Add an additional parser for non-standard tags
+     *
+     * @param {Object}   options              a map of options for the added parser
+     * @param {RegExp}   options.expression   a regular expression to match the custom header
+     * @param {string}   options.type         the type to register to the output
+     * @param {Function} [options.dataParser] function to parse the line into an object
+     * @param {boolean}  [options.segment]    should tag data be attached to the segment object
+     */
+    ;
+
+    _proto.addParser = function addParser(options) {
+      this.parseStream.addParser(options);
+    }
+    /**
+     * Add a custom header mapper
+     *
+     * @param {Object}   options
+     * @param {RegExp}   options.expression   a regular expression to match the custom header
+     * @param {Function} options.map          function to translate tag into a different tag
+     */
+    ;
+
+    _proto.addTagMapper = function addTagMapper(options) {
+      this.parseStream.addTagMapper(options);
+    };
+
+    return Parser;
+  }(Stream);
+
+  function _interopDefault(ex) {
+    return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex;
+  }
+
+  var URLToolkit = _interopDefault(urlToolkit);
+
+  var window$1 = _interopDefault(window$3);
+
+  var resolveUrl = function resolveUrl(baseUrl, relativeUrl) {
+    // return early if we don't need to resolve
+    if (/^[a-z]+:/i.test(relativeUrl)) {
+      return relativeUrl;
+    } // if the base URL is relative then combine with the current location
+
+
+    if (!/\/\//i.test(baseUrl)) {
+      baseUrl = URLToolkit.buildAbsoluteURL(window$1.location && window$1.location.href || '', baseUrl);
+    }
+
+    return URLToolkit.buildAbsoluteURL(baseUrl, relativeUrl);
+  };
+
+  var resolveUrl_1 = resolveUrl;
+
+  function _interopDefault$1(ex) {
+    return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex;
+  }
+
+  var window$2 = _interopDefault$1(window$3);
+
+  var atob = function atob(s) {
+    return window$2.atob ? window$2.atob(s) : Buffer.from(s, 'base64').toString('binary');
+  };
+
+  function decodeB64ToUint8Array$1(b64Text) {
+    var decodedString = atob(b64Text);
+    var array = new Uint8Array(decodedString.length);
+
+    for (var i = 0; i < decodedString.length; i++) {
+      array[i] = decodedString.charCodeAt(i);
+    }
+
+    return array;
+  }
+
+  var decodeB64ToUint8Array_1 = decodeB64ToUint8Array$1;
+
+  //[4]        NameStartChar      ::=          ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
+  //[4a]       NameChar           ::=          NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
+  //[5]        Name       ::=          NameStartChar (NameChar)*
+  var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/; //\u10000-\uEFFFF
+
+  var nameChar = new RegExp("[\\-\\.0-9" + nameStartChar.source.slice(1, -1) + "\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
+  var tagNamePattern = new RegExp('^' + nameStartChar.source + nameChar.source + '*(?:\:' + nameStartChar.source + nameChar.source + '*)?$'); //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
+  //var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
+  //S_TAG,     S_ATTR, S_EQ,   S_ATTR_NOQUOT_VALUE
+  //S_ATTR_SPACE,      S_ATTR_END,     S_TAG_SPACE, S_TAG_CLOSE
+
+  var S_TAG = 0; //tag name offerring
+
+  var S_ATTR = 1; //attr name offerring
+
+  var S_ATTR_SPACE = 2; //attr name end and space offer
+
+  var S_EQ = 3; //=space?
+
+  var S_ATTR_NOQUOT_VALUE = 4; //attr value(no quot value only)
+
+  var S_ATTR_END = 5; //attr value end and no space(quot end)
+
+  var S_TAG_SPACE = 6; //(attr value end || tag end ) && (space offer)
+
+  var S_TAG_CLOSE = 7; //closed el<el />
+
+  function XMLReader() {}
+
+  XMLReader.prototype = {
+    parse: function parse(source, defaultNSMap, entityMap) {
+      var domBuilder = this.domBuilder;
+      domBuilder.startDocument();
+
+      _copy(defaultNSMap, defaultNSMap = {});
+
+      _parse(source, defaultNSMap, entityMap, domBuilder, this.errorHandler);
+
+      domBuilder.endDocument();
+    }
+  };
+
+  function _parse(source, defaultNSMapCopy, entityMap, domBuilder, errorHandler) {
+    function fixedFromCharCode(code) {
+      // String.prototype.fromCharCode does not supports
+      // > 2 bytes unicode chars directly
+      if (code > 0xffff) {
+        code -= 0x10000;
+        var surrogate1 = 0xd800 + (code >> 10),
+            surrogate2 = 0xdc00 + (code & 0x3ff);
+        return String.fromCharCode(surrogate1, surrogate2);
+      } else {
+        return String.fromCharCode(code);
+      }
+    }
+
+    function entityReplacer(a) {
+      var k = a.slice(1, -1);
+
+      if (k in entityMap) {
+        return entityMap[k];
+      } else if (k.charAt(0) === '#') {
+        return fixedFromCharCode(parseInt(k.substr(1).replace('x', '0x')));
+      } else {
+        errorHandler.error('entity not found:' + a);
+        return a;
+      }
+    }
+
+    function appendText(end) {
+      //has some bugs
+      if (end > start) {
+        var xt = source.substring(start, end).replace(/&#?\w+;/g, entityReplacer);
+        locator && position(start);
+        domBuilder.characters(xt, 0, end - start);
+        start = end;
+      }
+    }
+
+    function position(p, m) {
+      while (p >= lineEnd && (m = linePattern.exec(source))) {
+        lineStart = m.index;
+        lineEnd = lineStart + m[0].length;
+        locator.lineNumber++; //console.log('line++:',locator,startPos,endPos)
+      }
+
+      locator.columnNumber = p - lineStart + 1;
+    }
+
+    var lineStart = 0;
+    var lineEnd = 0;
+    var linePattern = /.*(?:\r\n?|\n)|.*$/g;
+    var locator = domBuilder.locator;
+    var parseStack = [{
+      currentNSMap: defaultNSMapCopy
+    }];
+    var closeMap = {};
+    var start = 0;
+
+    while (true) {
+      try {
+        var tagStart = source.indexOf('<', start);
+
+        if (tagStart < 0) {
+          if (!source.substr(start).match(/^\s*$/)) {
+            var doc = domBuilder.doc;
+            var text = doc.createTextNode(source.substr(start));
+            doc.appendChild(text);
+            domBuilder.currentElement = text;
+          }
+
+          return;
+        }
+
+        if (tagStart > start) {
+          appendText(tagStart);
+        }
+
+        switch (source.charAt(tagStart + 1)) {
+          case '/':
+            var end = source.indexOf('>', tagStart + 3);
+            var tagName = source.substring(tagStart + 2, end);
+            var config = parseStack.pop();
+
+            if (end < 0) {
+              tagName = source.substring(tagStart + 2).replace(/[\s<].*/, ''); //console.error('#@@@@@@'+tagName)
+
+              errorHandler.error("end tag name: " + tagName + ' is not complete:' + config.tagName);
+              end = tagStart + 1 + tagName.length;
+            } else if (tagName.match(/\s</)) {
+              tagName = tagName.replace(/[\s<].*/, '');
+              errorHandler.error("end tag name: " + tagName + ' maybe not complete');
+              end = tagStart + 1 + tagName.length;
+            } //console.error(parseStack.length,parseStack)
+            //console.error(config);
+
+
+            var localNSMap = config.localNSMap;
+            var endMatch = config.tagName == tagName;
+            var endIgnoreCaseMach = endMatch || config.tagName && config.tagName.toLowerCase() == tagName.toLowerCase();
+
+            if (endIgnoreCaseMach) {
+              domBuilder.endElement(config.uri, config.localName, tagName);
+
+              if (localNSMap) {
+                for (var prefix in localNSMap) {
+                  domBuilder.endPrefixMapping(prefix);
+                }
+              }
+
+              if (!endMatch) {
+                errorHandler.fatalError("end tag name: " + tagName + ' is not match the current start tagName:' + config.tagName);
+              }
+            } else {
+              parseStack.push(config);
+            }
+
+            end++;
+            break;
+          // end elment
+
+          case '?':
+            // <?...?>
+            locator && position(tagStart);
+            end = parseInstruction(source, tagStart, domBuilder);
+            break;
+
+          case '!':
+            // <!doctype,<![CDATA,<!--
+            locator && position(tagStart);
+            end = parseDCC(source, tagStart, domBuilder, errorHandler);
+            break;
+
+          default:
+            locator && position(tagStart);
+            var el = new ElementAttributes();
+            var currentNSMap = parseStack[parseStack.length - 1].currentNSMap; //elStartEnd
+
+            var end = parseElementStartPart(source, tagStart, el, currentNSMap, entityReplacer, errorHandler);
+            var len = el.length;
+
+            if (!el.closed && fixSelfClosed(source, end, el.tagName, closeMap)) {
+              el.closed = true;
+
+              if (!entityMap.nbsp) {
+                errorHandler.warning('unclosed xml attribute');
+              }
+            }
+
+            if (locator && len) {
+              var locator2 = copyLocator(locator, {}); //try{//attribute position fixed
+
+              for (var i = 0; i < len; i++) {
+                var a = el[i];
+                position(a.offset);
+                a.locator = copyLocator(locator, {});
+              } //}catch(e){console.error('@@@@@'+e)}
+
+
+              domBuilder.locator = locator2;
+
+              if (appendElement(el, domBuilder, currentNSMap)) {
+                parseStack.push(el);
+              }
+
+              domBuilder.locator = locator;
+            } else {
+              if (appendElement(el, domBuilder, currentNSMap)) {
+                parseStack.push(el);
+              }
+            }
+
+            if (el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed) {
+              end = parseHtmlSpecialContent(source, end, el.tagName, entityReplacer, domBuilder);
+            } else {
+              end++;
+            }
+
+        }
+      } catch (e) {
+        errorHandler.error('element parse error: ' + e); //errorHandler.error('element parse error: '+e);
+
+        end = -1; //throw e;
+      }
+
+      if (end > start) {
+        start = end;
+      } else {
+        //TODO: 这里有可能sax回退,有位置错误风险
+        appendText(Math.max(tagStart, start) + 1);
+      }
+    }
+  }
+
+  function copyLocator(f, t) {
+    t.lineNumber = f.lineNumber;
+    t.columnNumber = f.columnNumber;
+    return t;
+  }
+  /**
+   * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
+   * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
+   */
+
+
+  function parseElementStartPart(source, start, el, currentNSMap, entityReplacer, errorHandler) {
+    var attrName;
+    var value;
+    var p = ++start;
+    var s = S_TAG; //status
+
+    while (true) {
+      var c = source.charAt(p);
+
+      switch (c) {
+        case '=':
+          if (s === S_ATTR) {
+            //attrName
+            attrName = source.slice(start, p);
+            s = S_EQ;
+          } else if (s === S_ATTR_SPACE) {
+            s = S_EQ;
+          } else {
+            //fatalError: equal must after attrName or space after attrName
+            throw new Error('attribute equal must after attrName');
+          }
+
+          break;
+
+        case '\'':
+        case '"':
+          if (s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE
+          ) {
+              //equal
+              if (s === S_ATTR) {
+                errorHandler.warning('attribute value must after "="');
+                attrName = source.slice(start, p);
+              }
+
+              start = p + 1;
+              p = source.indexOf(c, start);
+
+              if (p > 0) {
+                value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer);
+                el.add(attrName, value, start - 1);
+                s = S_ATTR_END;
+              } else {
+                //fatalError: no end quot match
+                throw new Error('attribute value no end \'' + c + '\' match');
+              }
+            } else if (s == S_ATTR_NOQUOT_VALUE) {
+            value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer); //console.log(attrName,value,start,p)
+
+            el.add(attrName, value, start); //console.dir(el)
+
+            errorHandler.warning('attribute "' + attrName + '" missed start quot(' + c + ')!!');
+            start = p + 1;
+            s = S_ATTR_END;
+          } else {
+            //fatalError: no equal before
+            throw new Error('attribute value must after "="');
+          }
+
+          break;
+
+        case '/':
+          switch (s) {
+            case S_TAG:
+              el.setTagName(source.slice(start, p));
+
+            case S_ATTR_END:
+            case S_TAG_SPACE:
+            case S_TAG_CLOSE:
+              s = S_TAG_CLOSE;
+              el.closed = true;
+
+            case S_ATTR_NOQUOT_VALUE:
+            case S_ATTR:
+            case S_ATTR_SPACE:
+              break;
+            //case S_EQ:
+
+            default:
+              throw new Error("attribute invalid close char('/')");
+          }
+
+          break;
+
+        case '':
+          //end document
+          //throw new Error('unexpected end of input')
+          errorHandler.error('unexpected end of input');
+
+          if (s == S_TAG) {
+            el.setTagName(source.slice(start, p));
+          }
+
+          return p;
+
+        case '>':
+          switch (s) {
+            case S_TAG:
+              el.setTagName(source.slice(start, p));
+
+            case S_ATTR_END:
+            case S_TAG_SPACE:
+            case S_TAG_CLOSE:
+              break;
+            //normal
+
+            case S_ATTR_NOQUOT_VALUE: //Compatible state
+
+            case S_ATTR:
+              value = source.slice(start, p);
+
+              if (value.slice(-1) === '/') {
+                el.closed = true;
+                value = value.slice(0, -1);
+              }
+
+            case S_ATTR_SPACE:
+              if (s === S_ATTR_SPACE) {
+                value = attrName;
+              }
+
+              if (s == S_ATTR_NOQUOT_VALUE) {
+                errorHandler.warning('attribute "' + value + '" missed quot(")!!');
+                el.add(attrName, value.replace(/&#?\w+;/g, entityReplacer), start);
+              } else {
+                if (currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)) {
+                  errorHandler.warning('attribute "' + value + '" missed value!! "' + value + '" instead!!');
+                }
+
+                el.add(value, value, start);
+              }
+
+              break;
+
+            case S_EQ:
+              throw new Error('attribute value missed!!');
+          } //                 console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
+
+
+          return p;
+
+        /*xml space '\x20' | #x9 | #xD | #xA; */
+
+        case "\x80":
+          c = ' ';
+
+        default:
+          if (c <= ' ') {
+            //space
+            switch (s) {
+              case S_TAG:
+                el.setTagName(source.slice(start, p)); //tagName
+
+                s = S_TAG_SPACE;
+                break;
+
+              case S_ATTR:
+                attrName = source.slice(start, p);
+                s = S_ATTR_SPACE;
+                break;
+
+              case S_ATTR_NOQUOT_VALUE:
+                var value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer);
+                errorHandler.warning('attribute "' + value + '" missed quot(")!!');
+                el.add(attrName, value, start);
+
+              case S_ATTR_END:
+                s = S_TAG_SPACE;
+                break;
+              //case S_TAG_SPACE:
+              //case S_EQ:
+              //case S_ATTR_SPACE:
+              //       void();break;
+              //case S_TAG_CLOSE:
+              //ignore warning
+            }
+          } else {
+            //not space
+            //S_TAG,   S_ATTR, S_EQ,   S_ATTR_NOQUOT_VALUE
+            //S_ATTR_SPACE,    S_ATTR_END,     S_TAG_SPACE, S_TAG_CLOSE
+            switch (s) {
+              //case S_TAG:void();break;
+              //case S_ATTR:void();break;
+              //case S_ATTR_NOQUOT_VALUE:void();break;
+              case S_ATTR_SPACE:
+                var tagName = el.tagName;
+
+                if (currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !attrName.match(/^(?:disabled|checked|selected)$/i)) {
+                  errorHandler.warning('attribute "' + attrName + '" missed value!! "' + attrName + '" instead2!!');
+                }
+
+                el.add(attrName, attrName, start);
+                start = p;
+                s = S_ATTR;
+                break;
+
+              case S_ATTR_END:
+                errorHandler.warning('attribute space is required"' + attrName + '"!!');
+
+              case S_TAG_SPACE:
+                s = S_ATTR;
+                start = p;
+                break;
+
+              case S_EQ:
+                s = S_ATTR_NOQUOT_VALUE;
+                start = p;
+                break;
+
+              case S_TAG_CLOSE:
+                throw new Error("elements closed character '/' and '>' must be connected to");
+            }
+          }
+
+      } //end outer switch
+      //console.log('p++',p)
+
+
+      p++;
+    }
+  }
+  /**
+   * @return true if has new namespace define
+   */
+
+
+  function appendElement(el, domBuilder, currentNSMap) {
+    var tagName = el.tagName;
+    var localNSMap = null; //var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
+
+    var i = el.length;
+
+    while (i--) {
+      var a = el[i];
+      var qName = a.qName;
+      var value = a.value;
+      var nsp = qName.indexOf(':');
+
+      if (nsp > 0) {
+        var prefix = a.prefix = qName.slice(0, nsp);
+        var localName = qName.slice(nsp + 1);
+        var nsPrefix = prefix === 'xmlns' && localName;
+      } else {
+        localName = qName;
+        prefix = null;
+        nsPrefix = qName === 'xmlns' && '';
+      } //can not set prefix,because prefix !== ''
+
+
+      a.localName = localName; //prefix == null for no ns prefix attribute
+
+      if (nsPrefix !== false) {
+        //hack!!
+        if (localNSMap == null) {
+          localNSMap = {}; //console.log(currentNSMap,0)
+
+          _copy(currentNSMap, currentNSMap = {}); //console.log(currentNSMap,1)
+
+        }
+
+        currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
+        a.uri = 'http://www.w3.org/2000/xmlns/';
+        domBuilder.startPrefixMapping(nsPrefix, value);
+      }
+    }
+
+    var i = el.length;
+
+    while (i--) {
+      a = el[i];
+      var prefix = a.prefix;
+
+      if (prefix) {
+        //no prefix attribute has no namespace
+        if (prefix === 'xml') {
+          a.uri = 'http://www.w3.org/XML/1998/namespace';
+        }
+
+        if (prefix !== 'xmlns') {
+          a.uri = currentNSMap[prefix || '']; //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
+        }
+      }
+    }
+
+    var nsp = tagName.indexOf(':');
+
+    if (nsp > 0) {
+      prefix = el.prefix = tagName.slice(0, nsp);
+      localName = el.localName = tagName.slice(nsp + 1);
+    } else {
+      prefix = null; //important!!
+
+      localName = el.localName = tagName;
+    } //no prefix element has default namespace
+
+
+    var ns = el.uri = currentNSMap[prefix || ''];
+    domBuilder.startElement(ns, localName, tagName, el); //endPrefixMapping and startPrefixMapping have not any help for dom builder
+    //localNSMap = null
+
+    if (el.closed) {
+      domBuilder.endElement(ns, localName, tagName);
+
+      if (localNSMap) {
+        for (prefix in localNSMap) {
+          domBuilder.endPrefixMapping(prefix);
+        }
+      }
+    } else {
+      el.currentNSMap = currentNSMap;
+      el.localNSMap = localNSMap; //parseStack.push(el);
+
+      return true;
+    }
+  }
+
+  function parseHtmlSpecialContent(source, elStartEnd, tagName, entityReplacer, domBuilder) {
+    if (/^(?:script|textarea)$/i.test(tagName)) {
+      var elEndStart = source.indexOf('</' + tagName + '>', elStartEnd);
+      var text = source.substring(elStartEnd + 1, elEndStart);
+
+      if (/[&<]/.test(text)) {
+        if (/^script$/i.test(tagName)) {
+          //if(!/\]\]>/.test(text)){
+          //lexHandler.startCDATA();
+          domBuilder.characters(text, 0, text.length); //lexHandler.endCDATA();
+
+          return elEndStart; //}
+        } //}else{//text area
+
+
+        text = text.replace(/&#?\w+;/g, entityReplacer);
+        domBuilder.characters(text, 0, text.length);
+        return elEndStart; //}
+      }
+    }
+
+    return elStartEnd + 1;
+  }
+
+  function fixSelfClosed(source, elStartEnd, tagName, closeMap) {
+    //if(tagName in closeMap){
+    var pos = closeMap[tagName];
+
+    if (pos == null) {
+      //console.log(tagName)
+      pos = source.lastIndexOf('</' + tagName + '>');
+
+      if (pos < elStartEnd) {
+        //忘记闭合
+        pos = source.lastIndexOf('</' + tagName);
+      }
+
+      closeMap[tagName] = pos;
+    }
+
+    return pos < elStartEnd; //}
+  }
+
+  function _copy(source, target) {
+    for (var n in source) {
+      target[n] = source[n];
+    }
+  }
+
+  function parseDCC(source, start, domBuilder, errorHandler) {
+    //sure start with '<!'
+    var next = source.charAt(start + 2);
+
+    switch (next) {
+      case '-':
+        if (source.charAt(start + 3) === '-') {
+          var end = source.indexOf('-->', start + 4); //append comment source.substring(4,end)//<!--
+
+          if (end > start) {
+            domBuilder.comment(source, start + 4, end - start - 4);
+            return end + 3;
+          } else {
+            errorHandler.error("Unclosed comment");
+            return -1;
+          }
+        } else {
+          //error
+          return -1;
+        }
+
+      default:
+        if (source.substr(start + 3, 6) == 'CDATA[') {
+          var end = source.indexOf(']]>', start + 9);
+          domBuilder.startCDATA();
+          domBuilder.characters(source, start + 9, end - start - 9);
+          domBuilder.endCDATA();
+          return end + 3;
+        } //<!DOCTYPE
+        //startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
+
+
+        var matchs = split(source, start);
+        var len = matchs.length;
+
+        if (len > 1 && /!doctype/i.test(matchs[0][0])) {
+          var name = matchs[1][0];
+          var pubid = len > 3 && /^public$/i.test(matchs[2][0]) && matchs[3][0];
+          var sysid = len > 4 && matchs[4][0];
+          var lastMatch = matchs[len - 1];
+          domBuilder.startDTD(name, pubid && pubid.replace(/^(['"])(.*?)\1$/, '$2'), sysid && sysid.replace(/^(['"])(.*?)\1$/, '$2'));
+          domBuilder.endDTD();
+          return lastMatch.index + lastMatch[0].length;
+        }
+
+    }
+
+    return -1;
+  }
+
+  function parseInstruction(source, start, domBuilder) {
+    var end = source.indexOf('?>', start);
+
+    if (end) {
+      var match = source.substring(start, end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
+
+      if (match) {
+        var len = match[0].length;
+        domBuilder.processingInstruction(match[1], match[2]);
+        return end + 2;
+      } else {
+        //error
+        return -1;
+      }
+    }
+
+    return -1;
+  }
+  /**
+   * @param source
+   */
+
+
+  function ElementAttributes(source) {}
+
+  ElementAttributes.prototype = {
+    setTagName: function setTagName(tagName) {
+      if (!tagNamePattern.test(tagName)) {
+        throw new Error('invalid tagName:' + tagName);
+      }
+
+      this.tagName = tagName;
+    },
+    add: function add(qName, value, offset) {
+      if (!tagNamePattern.test(qName)) {
+        throw new Error('invalid attribute:' + qName);
+      }
+
+      this[this.length++] = {
+        qName: qName,
+        value: value,
+        offset: offset
+      };
+    },
+    length: 0,
+    getLocalName: function getLocalName(i) {
+      return this[i].localName;
+    },
+    getLocator: function getLocator(i) {
+      return this[i].locator;
+    },
+    getQName: function getQName(i) {
+      return this[i].qName;
+    },
+    getURI: function getURI(i) {
+      return this[i].uri;
+    },
+    getValue: function getValue(i) {
+      return this[i].value;
+    } //       ,getIndex:function(uri, localName)){
+    //         if(localName){
+    //
+    //         }else{
+    //                 var qName = uri
+    //         }
+    // },
+    // getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
+    // getType:function(uri,localName){}
+    // getType:function(i){},
+
+  };
+
+  function _set_proto_(thiz, parent) {
+    thiz.__proto__ = parent;
+    return thiz;
+  }
+
+  if (!(_set_proto_({}, _set_proto_.prototype) instanceof _set_proto_)) {
+    _set_proto_ = function _set_proto_(thiz, parent) {
+      function p() {}
+      p.prototype = parent;
+      p = new p();
+
+      for (parent in thiz) {
+        p[parent] = thiz[parent];
+      }
+
+      return p;
+    };
+  }
+
+  function split(source, start) {
+    var match;
+    var buf = [];
+    var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
+    reg.lastIndex = start;
+    reg.exec(source); //skip <
+
+    while (match = reg.exec(source)) {
+      buf.push(match);
+      if (match[1]) return buf;
+    }
+  }
+
+  var XMLReader_1 = XMLReader;
+  var sax = {
+    XMLReader: XMLReader_1
+  };
+
+  /*
+   * DOM Level 2
+   * Object DOMException
+   * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
+   * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
+   */
+  function copy(src, dest) {
+    for (var p in src) {
+      dest[p] = src[p];
+    }
+  }
+  /**
+  ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
+  ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
+   */
+
+
+  function _extends$1(Class, Super) {
+    var pt = Class.prototype;
+
+    if (Object.create) {
+      var ppt = Object.create(Super.prototype);
+      pt.__proto__ = ppt;
+    }
+
+    if (!(pt instanceof Super)) {
+      var t = function t() {};
+      t.prototype = Super.prototype;
+      t = new t();
+      copy(pt, t);
+      Class.prototype = pt = t;
+    }
+
+    if (pt.constructor != Class) {
+      if (typeof Class != 'function') {
+        console.error("unknow Class:" + Class);
+      }
+
+      pt.constructor = Class;
+    }
+  }
+
+  var htmlns = 'http://www.w3.org/1999/xhtml'; // Node Types
+
+  var NodeType = {};
+  var ELEMENT_NODE = NodeType.ELEMENT_NODE = 1;
+  var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2;
+  var TEXT_NODE = NodeType.TEXT_NODE = 3;
+  var CDATA_SECTION_NODE = NodeType.CDATA_SECTION_NODE = 4;
+  var ENTITY_REFERENCE_NODE = NodeType.ENTITY_REFERENCE_NODE = 5;
+  var ENTITY_NODE = NodeType.ENTITY_NODE = 6;
+  var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
+  var COMMENT_NODE = NodeType.COMMENT_NODE = 8;
+  var DOCUMENT_NODE = NodeType.DOCUMENT_NODE = 9;
+  var DOCUMENT_TYPE_NODE = NodeType.DOCUMENT_TYPE_NODE = 10;
+  var DOCUMENT_FRAGMENT_NODE = NodeType.DOCUMENT_FRAGMENT_NODE = 11;
+  var NOTATION_NODE = NodeType.NOTATION_NODE = 12; // ExceptionCode
+
+  var ExceptionCode = {};
+  var ExceptionMessage = {};
+  var INDEX_SIZE_ERR = ExceptionCode.INDEX_SIZE_ERR = (ExceptionMessage[1] = "Index size error", 1);
+  var DOMSTRING_SIZE_ERR = ExceptionCode.DOMSTRING_SIZE_ERR = (ExceptionMessage[2] = "DOMString size error", 2);
+  var HIERARCHY_REQUEST_ERR = ExceptionCode.HIERARCHY_REQUEST_ERR = (ExceptionMessage[3] = "Hierarchy request error", 3);
+  var WRONG_DOCUMENT_ERR = ExceptionCode.WRONG_DOCUMENT_ERR = (ExceptionMessage[4] = "Wrong document", 4);
+  var INVALID_CHARACTER_ERR = ExceptionCode.INVALID_CHARACTER_ERR = (ExceptionMessage[5] = "Invalid character", 5);
+  var NO_DATA_ALLOWED_ERR = ExceptionCode.NO_DATA_ALLOWED_ERR = (ExceptionMessage[6] = "No data allowed", 6);
+  var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = (ExceptionMessage[7] = "No modification allowed", 7);
+  var NOT_FOUND_ERR = ExceptionCode.NOT_FOUND_ERR = (ExceptionMessage[8] = "Not found", 8);
+  var NOT_SUPPORTED_ERR = ExceptionCode.NOT_SUPPORTED_ERR = (ExceptionMessage[9] = "Not supported", 9);
+  var INUSE_ATTRIBUTE_ERR = ExceptionCode.INUSE_ATTRIBUTE_ERR = (ExceptionMessage[10] = "Attribute in use", 10); //level2
+
+  var INVALID_STATE_ERR = ExceptionCode.INVALID_STATE_ERR = (ExceptionMessage[11] = "Invalid state", 11);
+  var SYNTAX_ERR = ExceptionCode.SYNTAX_ERR = (ExceptionMessage[12] = "Syntax error", 12);
+  var INVALID_MODIFICATION_ERR = ExceptionCode.INVALID_MODIFICATION_ERR = (ExceptionMessage[13] = "Invalid modification", 13);
+  var NAMESPACE_ERR = ExceptionCode.NAMESPACE_ERR = (ExceptionMessage[14] = "Invalid namespace", 14);
+  var INVALID_ACCESS_ERR = ExceptionCode.INVALID_ACCESS_ERR = (ExceptionMessage[15] = "Invalid access", 15);
+
+  function DOMException(code, message) {
+    if (message instanceof Error) {
+      var error = message;
+    } else {
+      error = this;
+      Error.call(this, ExceptionMessage[code]);
+      this.message = ExceptionMessage[code];
+      if (Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
+    }
+
+    error.code = code;
+    if (message) this.message = this.message + ": " + message;
+    return error;
+  }
+  DOMException.prototype = Error.prototype;
+  copy(ExceptionCode, DOMException);
+  /**
+   * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
+   * The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.
+   * The items in the NodeList are accessible via an integral index, starting from 0.
+   */
+
+  function NodeList() {}
+  NodeList.prototype = {
+    /**
+     * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
+     * @standard level1
+     */
+    length: 0,
+
+    /**
+     * Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
+     * @standard level1
+     * @param index  unsigned long
+     *   Index into the collection.
+     * @return Node
+     *         The node at the indexth position in the NodeList, or null if that is not a valid index.
+     */
+    item: function item(index) {
+      return this[index] || null;
+    },
+    toString: function toString(isHTML, nodeFilter) {
+      for (var buf = [], i = 0; i < this.length; i++) {
+        serializeToString(this[i], buf, isHTML, nodeFilter);
+      }
+
+      return buf.join('');
+    }
+  };
+
+  function LiveNodeList(node, refresh) {
+    this._node = node;
+    this._refresh = refresh;
+
+    _updateLiveList(this);
+  }
+
+  function _updateLiveList(list) {
+    var inc = list._node._inc || list._node.ownerDocument._inc;
+
+    if (list._inc != inc) {
+      var ls = list._refresh(list._node); //console.log(ls.length)
+
+
+      __set__(list, 'length', ls.length);
+
+      copy(ls, list);
+      list._inc = inc;
+    }
+  }
+
+  LiveNodeList.prototype.item = function (i) {
+    _updateLiveList(this);
+
+    return this[i];
+  };
+
+  _extends$1(LiveNodeList, NodeList);
+  /**
+   *
+   * Objects implementing the NamedNodeMap interface are used to represent collections of nodes that can be accessed by name. Note that NamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular order. Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index, but this is simply to allow convenient enumeration of the contents of a NamedNodeMap, and does not imply that the DOM specifies an order to these Nodes.
+   * NamedNodeMap objects in the DOM are live.
+   * used for attributes or DocumentType entities
+   */
+
+
+  function NamedNodeMap() {}
+
+  function _findNodeIndex(list, node) {
+    var i = list.length;
+
+    while (i--) {
+      if (list[i] === node) {
+        return i;
+      }
+    }
+  }
+
+  function _addNamedNode(el, list, newAttr, oldAttr) {
+    if (oldAttr) {
+      list[_findNodeIndex(list, oldAttr)] = newAttr;
+    } else {
+      list[list.length++] = newAttr;
+    }
+
+    if (el) {
+      newAttr.ownerElement = el;
+      var doc = el.ownerDocument;
+
+      if (doc) {
+        oldAttr && _onRemoveAttribute(doc, el, oldAttr);
+
+        _onAddAttribute(doc, el, newAttr);
+      }
+    }
+  }
+
+  function _removeNamedNode(el, list, attr) {
+    //console.log('remove attr:'+attr)
+    var i = _findNodeIndex(list, attr);
+
+    if (i >= 0) {
+      var lastIndex = list.length - 1;
+
+      while (i < lastIndex) {
+        list[i] = list[++i];
+      }
+
+      list.length = lastIndex;
+
+      if (el) {
+        var doc = el.ownerDocument;
+
+        if (doc) {
+          _onRemoveAttribute(doc, el, attr);
+
+          attr.ownerElement = null;
+        }
+      }
+    } else {
+      throw DOMException(NOT_FOUND_ERR, new Error(el.tagName + '@' + attr));
+    }
+  }
+
+  NamedNodeMap.prototype = {
+    length: 0,
+    item: NodeList.prototype.item,
+    getNamedItem: function getNamedItem(key) {
+      //               if(key.indexOf(':')>0 || key == 'xmlns'){
+      //                       return null;
+      //               }
+      //console.log()
+      var i = this.length;
+
+      while (i--) {
+        var attr = this[i]; //console.log(attr.nodeName,key)
+
+        if (attr.nodeName == key) {
+          return attr;
+        }
+      }
+    },
+    setNamedItem: function setNamedItem(attr) {
+      var el = attr.ownerElement;
+
+      if (el && el != this._ownerElement) {
+        throw new DOMException(INUSE_ATTRIBUTE_ERR);
+      }
+
+      var oldAttr = this.getNamedItem(attr.nodeName);
+
+      _addNamedNode(this._ownerElement, this, attr, oldAttr);
+
+      return oldAttr;
+    },
+
+    /* returns Node */
+    setNamedItemNS: function setNamedItemNS(attr) {
+      // raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
+      var el = attr.ownerElement,
+          oldAttr;
+
+      if (el && el != this._ownerElement) {
+        throw new DOMException(INUSE_ATTRIBUTE_ERR);
+      }
+
+      oldAttr = this.getNamedItemNS(attr.namespaceURI, attr.localName);
+
+      _addNamedNode(this._ownerElement, this, attr, oldAttr);
+
+      return oldAttr;
+    },
+
+    /* returns Node */
+    removeNamedItem: function removeNamedItem(key) {
+      var attr = this.getNamedItem(key);
+
+      _removeNamedNode(this._ownerElement, this, attr);
+
+      return attr;
+    },
+    // raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
+    //for level2
+    removeNamedItemNS: function removeNamedItemNS(namespaceURI, localName) {
+      var attr = this.getNamedItemNS(namespaceURI, localName);
+
+      _removeNamedNode(this._ownerElement, this, attr);
+
+      return attr;
+    },
+    getNamedItemNS: function getNamedItemNS(namespaceURI, localName) {
+      var i = this.length;
+
+      while (i--) {
+        var node = this[i];
+
+        if (node.localName == localName && node.namespaceURI == namespaceURI) {
+          return node;
+        }
+      }
+
+      return null;
+    }
+  };
+  /**
+   * @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490
+   */
+
+  function DOMImplementation(
+  /* Object */
+  features) {
+    this._features = {};
+
+    if (features) {
+      for (var feature in features) {
+        this._features = features[feature];
+      }
+    }
+  }
+  DOMImplementation.prototype = {
+    hasFeature: function hasFeature(
+    /* string */
+    feature,
+    /* string */
+    version) {
+      var versions = this._features[feature.toLowerCase()];
+
+      if (versions && (!version || version in versions)) {
+        return true;
+      } else {
+        return false;
+      }
+    },
+    // Introduced in DOM Level 2:
+    createDocument: function createDocument(namespaceURI, qualifiedName, doctype) {
+      // raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR
+      var doc = new Document();
+      doc.implementation = this;
+      doc.childNodes = new NodeList();
+      doc.doctype = doctype;
+
+      if (doctype) {
+        doc.appendChild(doctype);
+      }
+
+      if (qualifiedName) {
+        var root = doc.createElementNS(namespaceURI, qualifiedName);
+        doc.appendChild(root);
+      }
+
+      return doc;
+    },
+    // Introduced in DOM Level 2:
+    createDocumentType: function createDocumentType(qualifiedName, publicId, systemId) {
+      // raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR
+      var node = new DocumentType();
+      node.name = qualifiedName;
+      node.nodeName = qualifiedName;
+      node.publicId = publicId;
+      node.systemId = systemId; // Introduced in DOM Level 2:
+      //readonly attribute DOMString        internalSubset;
+      //TODO:..
+      //  readonly attribute NamedNodeMap     entities;
+      //  readonly attribute NamedNodeMap     notations;
+
+      return node;
+    }
+  };
+  /**
+   * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
+   */
+
+  function Node() {}
+  Node.prototype = {
+    firstChild: null,
+    lastChild: null,
+    previousSibling: null,
+    nextSibling: null,
+    attributes: null,
+    parentNode: null,
+    childNodes: null,
+    ownerDocument: null,
+    nodeValue: null,
+    namespaceURI: null,
+    prefix: null,
+    localName: null,
+    // Modified in DOM Level 2:
+    insertBefore: function insertBefore(newChild, refChild) {
+      //raises
+      return _insertBefore(this, newChild, refChild);
+    },
+    replaceChild: function replaceChild(newChild, oldChild) {
+      //raises
+      this.insertBefore(newChild, oldChild);
+
+      if (oldChild) {
+        this.removeChild(oldChild);
+      }
+    },
+    removeChild: function removeChild(oldChild) {
+      return _removeChild(this, oldChild);
+    },
+    appendChild: function appendChild(newChild) {
+      return this.insertBefore(newChild, null);
+    },
+    hasChildNodes: function hasChildNodes() {
+      return this.firstChild != null;
+    },
+    cloneNode: function cloneNode(deep) {
+      return _cloneNode(this.ownerDocument || this, this, deep);
+    },
+    // Modified in DOM Level 2:
+    normalize: function normalize() {
+      var child = this.firstChild;
+
+      while (child) {
+        var next = child.nextSibling;
+
+        if (next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE) {
+          this.removeChild(next);
+          child.appendData(next.data);
+        } else {
+          child.normalize();
+          child = next;
+        }
+      }
+    },
+    // Introduced in DOM Level 2:
+    isSupported: function isSupported(feature, version) {
+      return this.ownerDocument.implementation.hasFeature(feature, version);
+    },
+    // Introduced in DOM Level 2:
+    hasAttributes: function hasAttributes() {
+      return this.attributes.length > 0;
+    },
+    lookupPrefix: function lookupPrefix(namespaceURI) {
+      var el = this;
+
+      while (el) {
+        var map = el._nsMap; //console.dir(map)
+
+        if (map) {
+          for (var n in map) {
+            if (map[n] == namespaceURI) {
+              return n;
+            }
+          }
+        }
+
+        el = el.nodeType == ATTRIBUTE_NODE ? el.ownerDocument : el.parentNode;
+      }
+
+      return null;
+    },
+    // Introduced in DOM Level 3:
+    lookupNamespaceURI: function lookupNamespaceURI(prefix) {
+      var el = this;
+
+      while (el) {
+        var map = el._nsMap; //console.dir(map)
+
+        if (map) {
+          if (prefix in map) {
+            return map[prefix];
+          }
+        }
+
+        el = el.nodeType == ATTRIBUTE_NODE ? el.ownerDocument : el.parentNode;
+      }
+
+      return null;
+    },
+    // Introduced in DOM Level 3:
+    isDefaultNamespace: function isDefaultNamespace(namespaceURI) {
+      var prefix = this.lookupPrefix(namespaceURI);
+      return prefix == null;
+    }
+  };
+
+  function _xmlEncoder(c) {
+    return c == '<' && '&lt;' || c == '>' && '&gt;' || c == '&' && '&amp;' || c == '"' && '&quot;' || '&#' + c.charCodeAt() + ';';
+  }
+
+  copy(NodeType, Node);
+  copy(NodeType, Node.prototype);
+  /**
+   * @param callback return true for continue,false for break
+   * @return boolean true: break visit;
+   */
+
+  function _visitNode(node, callback) {
+    if (callback(node)) {
+      return true;
+    }
+
+    if (node = node.firstChild) {
+      do {
+        if (_visitNode(node, callback)) {
+          return true;
+        }
+      } while (node = node.nextSibling);
+    }
+  }
+
+  function Document() {}
+
+  function _onAddAttribute(doc, el, newAttr) {
+    doc && doc._inc++;
+    var ns = newAttr.namespaceURI;
+
+    if (ns == 'http://www.w3.org/2000/xmlns/') {
+      //update namespace
+      el._nsMap[newAttr.prefix ? newAttr.localName : ''] = newAttr.value;
+    }
+  }
+
+  function _onRemoveAttribute(doc, el, newAttr, remove) {
+    doc && doc._inc++;
+    var ns = newAttr.namespaceURI;
+
+    if (ns == 'http://www.w3.org/2000/xmlns/') {
+      //update namespace
+      delete el._nsMap[newAttr.prefix ? newAttr.localName : ''];
+    }
+  }
+
+  function _onUpdateChild(doc, el, newChild) {
+    if (doc && doc._inc) {
+      doc._inc++; //update childNodes
+
+      var cs = el.childNodes;
+
+      if (newChild) {
+        cs[cs.length++] = newChild;
+      } else {
+        //console.log(1)
+        var child = el.firstChild;
+        var i = 0;
+
+        while (child) {
+          cs[i++] = child;
+          child = child.nextSibling;
+        }
+
+        cs.length = i;
+      }
+    }
+  }
+  /**
+   * attributes;
+   * children;
+   *
+   * writeable properties:
+   * nodeValue,Attr:value,CharacterData:data
+   * prefix
+   */
+
+
+  function _removeChild(parentNode, child) {
+    var previous = child.previousSibling;
+    var next = child.nextSibling;
+
+    if (previous) {
+      previous.nextSibling = next;
+    } else {
+      parentNode.firstChild = next;
+    }
+
+    if (next) {
+      next.previousSibling = previous;
+    } else {
+      parentNode.lastChild = previous;
+    }
+
+    _onUpdateChild(parentNode.ownerDocument, parentNode);
+
+    return child;
+  }
+  /**
+   * preformance key(refChild == null)
+   */
+
+
+  function _insertBefore(parentNode, newChild, nextChild) {
+    var cp = newChild.parentNode;
+
+    if (cp) {
+      cp.removeChild(newChild); //remove and update
+    }
+
+    if (newChild.nodeType === DOCUMENT_FRAGMENT_NODE) {
+      var newFirst = newChild.firstChild;
+
+      if (newFirst == null) {
+        return newChild;
+      }
+
+      var newLast = newChild.lastChild;
+    } else {
+      newFirst = newLast = newChild;
+    }
+
+    var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
+    newFirst.previousSibling = pre;
+    newLast.nextSibling = nextChild;
+
+    if (pre) {
+      pre.nextSibling = newFirst;
+    } else {
+      parentNode.firstChild = newFirst;
+    }
+
+    if (nextChild == null) {
+      parentNode.lastChild = newLast;
+    } else {
+      nextChild.previousSibling = newLast;
+    }
+
+    do {
+      newFirst.parentNode = parentNode;
+    } while (newFirst !== newLast && (newFirst = newFirst.nextSibling));
+
+    _onUpdateChild(parentNode.ownerDocument || parentNode, parentNode); //console.log(parentNode.lastChild.nextSibling == null)
+
+
+    if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
+      newChild.firstChild = newChild.lastChild = null;
+    }
+
+    return newChild;
+  }
+
+  function _appendSingleChild(parentNode, newChild) {
+    var cp = newChild.parentNode;
+
+    if (cp) {
+      var pre = parentNode.lastChild;
+      cp.removeChild(newChild); //remove and update
+
+      var pre = parentNode.lastChild;
+    }
+
+    var pre = parentNode.lastChild;
+    newChild.parentNode = parentNode;
+    newChild.previousSibling = pre;
+    newChild.nextSibling = null;
+
+    if (pre) {
+      pre.nextSibling = newChild;
+    } else {
+      parentNode.firstChild = newChild;
+    }
+
+    parentNode.lastChild = newChild;
+
+    _onUpdateChild(parentNode.ownerDocument, parentNode, newChild);
+
+    return newChild; //console.log("__aa",parentNode.lastChild.nextSibling == null)
+  }
+
+  Document.prototype = {
+    //implementation : null,
+    nodeName: '#document',
+    nodeType: DOCUMENT_NODE,
+    doctype: null,
+    documentElement: null,
+    _inc: 1,
+    insertBefore: function insertBefore(newChild, refChild) {
+      //raises
+      if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
+        var child = newChild.firstChild;
+
+        while (child) {
+          var next = child.nextSibling;
+          this.insertBefore(child, refChild);
+          child = next;
+        }
+
+        return newChild;
+      }
+
+      if (this.documentElement == null && newChild.nodeType == ELEMENT_NODE) {
+        this.documentElement = newChild;
+      }
+
+      return _insertBefore(this, newChild, refChild), newChild.ownerDocument = this, newChild;
+    },
+    removeChild: function removeChild(oldChild) {
+      if (this.documentElement == oldChild) {
+        this.documentElement = null;
+      }
+
+      return _removeChild(this, oldChild);
+    },
+    // Introduced in DOM Level 2:
+    importNode: function importNode(importedNode, deep) {
+      return _importNode(this, importedNode, deep);
+    },
+    // Introduced in DOM Level 2:
+    getElementById: function getElementById(id) {
+      var rtv = null;
+
+      _visitNode(this.documentElement, function (node) {
+        if (node.nodeType == ELEMENT_NODE) {
+          if (node.getAttribute('id') == id) {
+            rtv = node;
+            return true;
+          }
+        }
+      });
+
+      return rtv;
+    },
+    //document factory method:
+    createElement: function createElement(tagName) {
+      var node = new Element();
+      node.ownerDocument = this;
+      node.nodeName = tagName;
+      node.tagName = tagName;
+      node.childNodes = new NodeList();
+      var attrs = node.attributes = new NamedNodeMap();
+      attrs._ownerElement = node;
+      return node;
+    },
+    createDocumentFragment: function createDocumentFragment() {
+      var node = new DocumentFragment();
+      node.ownerDocument = this;
+      node.childNodes = new NodeList();
+      return node;
+    },
+    createTextNode: function createTextNode(data) {
+      var node = new Text();
+      node.ownerDocument = this;
+      node.appendData(data);
+      return node;
+    },
+    createComment: function createComment(data) {
+      var node = new Comment();
+      node.ownerDocument = this;
+      node.appendData(data);
+      return node;
+    },
+    createCDATASection: function createCDATASection(data) {
+      var node = new CDATASection();
+      node.ownerDocument = this;
+      node.appendData(data);
+      return node;
+    },
+    createProcessingInstruction: function createProcessingInstruction(target, data) {
+      var node = new ProcessingInstruction();
+      node.ownerDocument = this;
+      node.tagName = node.target = target;
+      node.nodeValue = node.data = data;
+      return node;
+    },
+    createAttribute: function createAttribute(name) {
+      var node = new Attr();
+      node.ownerDocument = this;
+      node.name = name;
+      node.nodeName = name;
+      node.localName = name;
+      node.specified = true;
+      return node;
+    },
+    createEntityReference: function createEntityReference(name) {
+      var node = new EntityReference();
+      node.ownerDocument = this;
+      node.nodeName = name;
+      return node;
+    },
+    // Introduced in DOM Level 2:
+    createElementNS: function createElementNS(namespaceURI, qualifiedName) {
+      var node = new Element();
+      var pl = qualifiedName.split(':');
+      var attrs = node.attributes = new NamedNodeMap();
+      node.childNodes = new NodeList();
+      node.ownerDocument = this;
+      node.nodeName = qualifiedName;
+      node.tagName = qualifiedName;
+      node.namespaceURI = namespaceURI;
+
+      if (pl.length == 2) {
+        node.prefix = pl[0];
+        node.localName = pl[1];
+      } else {
+        //el.prefix = null;
+        node.localName = qualifiedName;
+      }
+
+      attrs._ownerElement = node;
+      return node;
+    },
+    // Introduced in DOM Level 2:
+    createAttributeNS: function createAttributeNS(namespaceURI, qualifiedName) {
+      var node = new Attr();
+      var pl = qualifiedName.split(':');
+      node.ownerDocument = this;
+      node.nodeName = qualifiedName;
+      node.name = qualifiedName;
+      node.namespaceURI = namespaceURI;
+      node.specified = true;
+
+      if (pl.length == 2) {
+        node.prefix = pl[0];
+        node.localName = pl[1];
+      } else {
+        //el.prefix = null;
+        node.localName = qualifiedName;
+      }
+
+      return node;
+    }
+  };
+
+  _extends$1(Document, Node);
+
+  function Element() {
+    this._nsMap = {};
+  }
+  Element.prototype = {
+    nodeType: ELEMENT_NODE,
+    hasAttribute: function hasAttribute(name) {
+      return this.getAttributeNode(name) != null;
+    },
+    getAttribute: function getAttribute(name) {
+      var attr = this.getAttributeNode(name);
+      return attr && attr.value || '';
+    },
+    getAttributeNode: function getAttributeNode(name) {
+      return this.attributes.getNamedItem(name);
+    },
+    setAttribute: function setAttribute(name, value) {
+      var attr = this.ownerDocument.createAttribute(name);
+      attr.value = attr.nodeValue = "" + value;
+      this.setAttributeNode(attr);
+    },
+    removeAttribute: function removeAttribute(name) {
+      var attr = this.getAttributeNode(name);
+      attr && this.removeAttributeNode(attr);
+    },
+    //four real opeartion method
+    appendChild: function appendChild(newChild) {
+      if (newChild.nodeType === DOCUMENT_FRAGMENT_NODE) {
+        return this.insertBefore(newChild, null);
+      } else {
+        return _appendSingleChild(this, newChild);
+      }
+    },
+    setAttributeNode: function setAttributeNode(newAttr) {
+      return this.attributes.setNamedItem(newAttr);
+    },
+    setAttributeNodeNS: function setAttributeNodeNS(newAttr) {
+      return this.attributes.setNamedItemNS(newAttr);
+    },
+    removeAttributeNode: function removeAttributeNode(oldAttr) {
+      //console.log(this == oldAttr.ownerElement)
+      return this.attributes.removeNamedItem(oldAttr.nodeName);
+    },
+    //get real attribute name,and remove it by removeAttributeNode
+    removeAttributeNS: function removeAttributeNS(namespaceURI, localName) {
+      var old = this.getAttributeNodeNS(namespaceURI, localName);
+      old && this.removeAttributeNode(old);
+    },
+    hasAttributeNS: function hasAttributeNS(namespaceURI, localName) {
+      return this.getAttributeNodeNS(namespaceURI, localName) != null;
+    },
+    getAttributeNS: function getAttributeNS(namespaceURI, localName) {
+      var attr = this.getAttributeNodeNS(namespaceURI, localName);
+      return attr && attr.value || '';
+    },
+    setAttributeNS: function setAttributeNS(namespaceURI, qualifiedName, value) {
+      var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
+      attr.value = attr.nodeValue = "" + value;
+      this.setAttributeNode(attr);
+    },
+    getAttributeNodeNS: function getAttributeNodeNS(namespaceURI, localName) {
+      return this.attributes.getNamedItemNS(namespaceURI, localName);
+    },
+    getElementsByTagName: function getElementsByTagName(tagName) {
+      return new LiveNodeList(this, function (base) {
+        var ls = [];
+
+        _visitNode(base, function (node) {
+          if (node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)) {
+            ls.push(node);
+          }
+        });
+
+        return ls;
+      });
+    },
+    getElementsByTagNameNS: function getElementsByTagNameNS(namespaceURI, localName) {
+      return new LiveNodeList(this, function (base) {
+        var ls = [];
+
+        _visitNode(base, function (node) {
+          if (node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)) {
+            ls.push(node);
+          }
+        });
+
+        return ls;
+      });
+    }
+  };
+  Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
+  Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
+
+  _extends$1(Element, Node);
+
+  function Attr() {}
+  Attr.prototype.nodeType = ATTRIBUTE_NODE;
+
+  _extends$1(Attr, Node);
+
+  function CharacterData() {}
+  CharacterData.prototype = {
+    data: '',
+    substringData: function substringData(offset, count) {
+      return this.data.substring(offset, offset + count);
+    },
+    appendData: function appendData(text) {
+      text = this.data + text;
+      this.nodeValue = this.data = text;
+      this.length = text.length;
+    },
+    insertData: function insertData(offset, text) {
+      this.replaceData(offset, 0, text);
+    },
+    appendChild: function appendChild(newChild) {
+      throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR]);
+    },
+    deleteData: function deleteData(offset, count) {
+      this.replaceData(offset, count, "");
+    },
+    replaceData: function replaceData(offset, count, text) {
+      var start = this.data.substring(0, offset);
+      var end = this.data.substring(offset + count);
+      text = start + text + end;
+      this.nodeValue = this.data = text;
+      this.length = text.length;
+    }
+  };
+
+  _extends$1(CharacterData, Node);
+
+  function Text() {}
+  Text.prototype = {
+    nodeName: "#text",
+    nodeType: TEXT_NODE,
+    splitText: function splitText(offset) {
+      var text = this.data;
+      var newText = text.substring(offset);
+      text = text.substring(0, offset);
+      this.data = this.nodeValue = text;
+      this.length = text.length;
+      var newNode = this.ownerDocument.createTextNode(newText);
+
+      if (this.parentNode) {
+        this.parentNode.insertBefore(newNode, this.nextSibling);
+      }
+
+      return newNode;
+    }
+  };
+
+  _extends$1(Text, CharacterData);
+
+  function Comment() {}
+  Comment.prototype = {
+    nodeName: "#comment",
+    nodeType: COMMENT_NODE
+  };
+
+  _extends$1(Comment, CharacterData);
+
+  function CDATASection() {}
+  CDATASection.prototype = {
+    nodeName: "#cdata-section",
+    nodeType: CDATA_SECTION_NODE
+  };
+
+  _extends$1(CDATASection, CharacterData);
+
+  function DocumentType() {}
+  DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
+
+  _extends$1(DocumentType, Node);
+
+  function Notation() {}
+  Notation.prototype.nodeType = NOTATION_NODE;
+
+  _extends$1(Notation, Node);
+
+  function Entity() {}
+  Entity.prototype.nodeType = ENTITY_NODE;
+
+  _extends$1(Entity, Node);
+
+  function EntityReference() {}
+  EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
+
+  _extends$1(EntityReference, Node);
+
+  function DocumentFragment() {}
+  DocumentFragment.prototype.nodeName = "#document-fragment";
+  DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE;
+
+  _extends$1(DocumentFragment, Node);
+
+  function ProcessingInstruction() {}
+
+  ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
+
+  _extends$1(ProcessingInstruction, Node);
+
+  function XMLSerializer() {}
+
+  XMLSerializer.prototype.serializeToString = function (node, isHtml, nodeFilter) {
+    return nodeSerializeToString.call(node, isHtml, nodeFilter);
+  };
+
+  Node.prototype.toString = nodeSerializeToString;
+
+  function nodeSerializeToString(isHtml, nodeFilter) {
+    var buf = [];
+    var refNode = this.nodeType == 9 ? this.documentElement : this;
+    var prefix = refNode.prefix;
+    var uri = refNode.namespaceURI;
+
+    if (uri && prefix == null) {
+      //console.log(prefix)
+      var prefix = refNode.lookupPrefix(uri);
+
+      if (prefix == null) {
+        //isHTML = true;
+        var visibleNamespaces = [{
+          namespace: uri,
+          prefix: null
+        } //{namespace:uri,prefix:''}
+        ];
+      }
+    }
+
+    serializeToString(this, buf, isHtml, nodeFilter, visibleNamespaces); //console.log('###',this.nodeType,uri,prefix,buf.join(''))
+
+    return buf.join('');
+  }
+
+  function needNamespaceDefine(node, isHTML, visibleNamespaces) {
+    var prefix = node.prefix || '';
+    var uri = node.namespaceURI;
+
+    if (!prefix && !uri) {
+      return false;
+    }
+
+    if (prefix === "xml" && uri === "http://www.w3.org/XML/1998/namespace" || uri == 'http://www.w3.org/2000/xmlns/') {
+      return false;
+    }
+
+    var i = visibleNamespaces.length; //console.log('@@@@',node.tagName,prefix,uri,visibleNamespaces)
+
+    while (i--) {
+      var ns = visibleNamespaces[i]; // get namespace prefix
+      //console.log(node.nodeType,node.tagName,ns.prefix,prefix)
+
+      if (ns.prefix == prefix) {
+        return ns.namespace != uri;
+      }
+    } //console.log(isHTML,uri,prefix=='')
+    //if(isHTML && prefix ==null && uri == 'http://www.w3.org/1999/xhtml'){
+    // return false;
+    //}
+    //node.flag = '11111'
+    //console.error(3,true,node.flag,node.prefix,node.namespaceURI)
+
+
+    return true;
+  }
+
+  function serializeToString(node, buf, isHTML, nodeFilter, visibleNamespaces) {
+    if (nodeFilter) {
+      node = nodeFilter(node);
+
+      if (node) {
+        if (typeof node == 'string') {
+          buf.push(node);
+          return;
+        }
+      } else {
+        return;
+      } //buf.sort.apply(attrs, attributeSorter);
+
+    }
+
+    switch (node.nodeType) {
+      case ELEMENT_NODE:
+        if (!visibleNamespaces) visibleNamespaces = [];
+        var startVisibleNamespaces = visibleNamespaces.length;
+        var attrs = node.attributes;
+        var len = attrs.length;
+        var child = node.firstChild;
+        var nodeName = node.tagName;
+        isHTML = htmlns === node.namespaceURI || isHTML;
+        buf.push('<', nodeName);
+
+        for (var i = 0; i < len; i++) {
+          // add namespaces for attributes
+          var attr = attrs.item(i);
+
+          if (attr.prefix == 'xmlns') {
+            visibleNamespaces.push({
+              prefix: attr.localName,
+              namespace: attr.value
+            });
+          } else if (attr.nodeName == 'xmlns') {
+            visibleNamespaces.push({
+              prefix: '',
+              namespace: attr.value
+            });
+          }
+        }
+
+        for (var i = 0; i < len; i++) {
+          var attr = attrs.item(i);
+
+          if (needNamespaceDefine(attr, isHTML, visibleNamespaces)) {
+            var prefix = attr.prefix || '';
+            var uri = attr.namespaceURI;
+            var ns = prefix ? ' xmlns:' + prefix : " xmlns";
+            buf.push(ns, '="', uri, '"');
+            visibleNamespaces.push({
+              prefix: prefix,
+              namespace: uri
+            });
+          }
+
+          serializeToString(attr, buf, isHTML, nodeFilter, visibleNamespaces);
+        } // add namespace for current node
+
+
+        if (needNamespaceDefine(node, isHTML, visibleNamespaces)) {
+          var prefix = node.prefix || '';
+          var uri = node.namespaceURI;
+          var ns = prefix ? ' xmlns:' + prefix : " xmlns";
+          buf.push(ns, '="', uri, '"');
+          visibleNamespaces.push({
+            prefix: prefix,
+            namespace: uri
+          });
+        }
+
+        if (child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)) {
+          buf.push('>'); //if is cdata child node
+
+          if (isHTML && /^script$/i.test(nodeName)) {
+            while (child) {
+              if (child.data) {
+                buf.push(child.data);
+              } else {
+                serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces);
+              }
+
+              child = child.nextSibling;
+            }
+          } else {
+            while (child) {
+              serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces);
+              child = child.nextSibling;
+            }
+          }
+
+          buf.push('</', nodeName, '>');
+        } else {
+          buf.push('/>');
+        } // remove added visible namespaces
+        //visibleNamespaces.length = startVisibleNamespaces;
+
+
+        return;
+
+      case DOCUMENT_NODE:
+      case DOCUMENT_FRAGMENT_NODE:
+        var child = node.firstChild;
+
+        while (child) {
+          serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces);
+          child = child.nextSibling;
+        }
+
+        return;
+
+      case ATTRIBUTE_NODE:
+        return buf.push(' ', node.name, '="', node.value.replace(/[<&"]/g, _xmlEncoder), '"');
+
+      case TEXT_NODE:
+        return buf.push(node.data.replace(/[<&]/g, _xmlEncoder));
+
+      case CDATA_SECTION_NODE:
+        return buf.push('<![CDATA[', node.data, ']]>');
+
+      case COMMENT_NODE:
+        return buf.push("<!--", node.data, "-->");
+
+      case DOCUMENT_TYPE_NODE:
+        var pubid = node.publicId;
+        var sysid = node.systemId;
+        buf.push('<!DOCTYPE ', node.name);
+
+        if (pubid) {
+          buf.push(' PUBLIC "', pubid);
+
+          if (sysid && sysid != '.') {
+            buf.push('" "', sysid);
+          }
+
+          buf.push('">');
+        } else if (sysid && sysid != '.') {
+          buf.push(' SYSTEM "', sysid, '">');
+        } else {
+          var sub = node.internalSubset;
+
+          if (sub) {
+            buf.push(" [", sub, "]");
+          }
+
+          buf.push(">");
+        }
+
+        return;
+
+      case PROCESSING_INSTRUCTION_NODE:
+        return buf.push("<?", node.target, " ", node.data, "?>");
+
+      case ENTITY_REFERENCE_NODE:
+        return buf.push('&', node.nodeName, ';');
+      //case ENTITY_NODE:
+      //case NOTATION_NODE:
+
+      default:
+        buf.push('??', node.nodeName);
+    }
+  }
+
+  function _importNode(doc, node, deep) {
+    var node2;
+
+    switch (node.nodeType) {
+      case ELEMENT_NODE:
+        node2 = node.cloneNode(false);
+        node2.ownerDocument = doc;
+      //var attrs = node2.attributes;
+      //var len = attrs.length;
+      //for(var i=0;i<len;i++){
+      //node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));
+      //}
+
+      case DOCUMENT_FRAGMENT_NODE:
+        break;
+
+      case ATTRIBUTE_NODE:
+        deep = true;
+        break;
+      //case ENTITY_REFERENCE_NODE:
+      //case PROCESSING_INSTRUCTION_NODE:
+      ////case TEXT_NODE:
+      //case CDATA_SECTION_NODE:
+      //case COMMENT_NODE:
+      //       deep = false;
+      //       break;
+      //case DOCUMENT_NODE:
+      //case DOCUMENT_TYPE_NODE:
+      //cannot be imported.
+      //case ENTITY_NODE:
+      //case NOTATION_NODE:
+      //can not hit in level3
+      //default:throw e;
+    }
+
+    if (!node2) {
+      node2 = node.cloneNode(false); //false
+    }
+
+    node2.ownerDocument = doc;
+    node2.parentNode = null;
+
+    if (deep) {
+      var child = node.firstChild;
+
+      while (child) {
+        node2.appendChild(_importNode(doc, child, deep));
+        child = child.nextSibling;
+      }
+    }
 
-                if (!entry.attributes) {
-                  this.trigger('warn', {
-                    message: 'ignoring empty stream-inf attributes'
-                  });
-                  return;
-                }
+    return node2;
+  } //
+  //var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
+  //                                   attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
 
-                if (!currentUri.attributes) {
-                  currentUri.attributes = {};
-                }
 
-                _extends(currentUri.attributes, entry.attributes);
-              },
-              media: function media() {
-                this.manifest.mediaGroups = this.manifest.mediaGroups || defaultMediaGroups;
+  function _cloneNode(doc, node, deep) {
+    var node2 = new node.constructor();
 
-                if (!(entry.attributes && entry.attributes.TYPE && entry.attributes['GROUP-ID'] && entry.attributes.NAME)) {
-                  this.trigger('warn', {
-                    message: 'ignoring incomplete or missing media group'
-                  });
-                  return;
-                } // find the media group, creating defaults as necessary
+    for (var n in node) {
+      var v = node[n];
 
+      if (typeof v != 'object') {
+        if (v != node2[n]) {
+          node2[n] = v;
+        }
+      }
+    }
 
-                var mediaGroupType = this.manifest.mediaGroups[entry.attributes.TYPE];
-                mediaGroupType[entry.attributes['GROUP-ID']] = mediaGroupType[entry.attributes['GROUP-ID']] || {};
-                mediaGroup = mediaGroupType[entry.attributes['GROUP-ID']]; // collect the rendition metadata
+    if (node.childNodes) {
+      node2.childNodes = new NodeList();
+    }
 
-                rendition = {
-                  "default": /yes/i.test(entry.attributes.DEFAULT)
-                };
+    node2.ownerDocument = doc;
 
-                if (rendition["default"]) {
-                  rendition.autoselect = true;
-                } else {
-                  rendition.autoselect = /yes/i.test(entry.attributes.AUTOSELECT);
-                }
+    switch (node2.nodeType) {
+      case ELEMENT_NODE:
+        var attrs = node.attributes;
+        var attrs2 = node2.attributes = new NamedNodeMap();
+        var len = attrs.length;
+        attrs2._ownerElement = node2;
 
-                if (entry.attributes.LANGUAGE) {
-                  rendition.language = entry.attributes.LANGUAGE;
-                }
+        for (var i = 0; i < len; i++) {
+          node2.setAttributeNode(_cloneNode(doc, attrs.item(i), true));
+        }
 
-                if (entry.attributes.URI) {
-                  rendition.uri = entry.attributes.URI;
-                }
+        break;
 
-                if (entry.attributes['INSTREAM-ID']) {
-                  rendition.instreamId = entry.attributes['INSTREAM-ID'];
-                }
 
-                if (entry.attributes.CHARACTERISTICS) {
-                  rendition.characteristics = entry.attributes.CHARACTERISTICS;
-                }
+      case ATTRIBUTE_NODE:
+        deep = true;
+    }
 
-                if (entry.attributes.FORCED) {
-                  rendition.forced = /yes/i.test(entry.attributes.FORCED);
-                } // insert the new rendition
+    if (deep) {
+      var child = node.firstChild;
 
+      while (child) {
+        node2.appendChild(_cloneNode(doc, child, deep));
+        child = child.nextSibling;
+      }
+    }
 
-                mediaGroup[entry.attributes.NAME] = rendition;
-              },
-              discontinuity: function discontinuity() {
-                currentTimeline += 1;
-                currentUri.discontinuity = true;
-                this.manifest.discontinuityStarts.push(uris.length);
-              },
-              'program-date-time': function programDateTime() {
-                if (typeof this.manifest.dateTimeString === 'undefined') {
-                  // PROGRAM-DATE-TIME is a media-segment tag, but for backwards
-                  // compatibility, we add the first occurence of the PROGRAM-DATE-TIME tag
-                  // to the manifest object
-                  // TODO: Consider removing this in future major version
-                  this.manifest.dateTimeString = entry.dateTimeString;
-                  this.manifest.dateTimeObject = entry.dateTimeObject;
-                }
+    return node2;
+  }
 
-                currentUri.dateTimeString = entry.dateTimeString;
-                currentUri.dateTimeObject = entry.dateTimeObject;
-              },
-              targetduration: function targetduration() {
-                if (!isFinite(entry.duration) || entry.duration < 0) {
-                  this.trigger('warn', {
-                    message: 'ignoring invalid target duration: ' + entry.duration
-                  });
-                  return;
-                }
+  function __set__(object, key, value) {
+    object[key] = value;
+  } //do dynamic
 
-                this.manifest.targetDuration = entry.duration;
-              },
-              totalduration: function totalduration() {
-                if (!isFinite(entry.duration) || entry.duration < 0) {
-                  this.trigger('warn', {