diff --git a/src/js/player.js b/src/js/player.js index 684ae663c2..2ce20c8efa 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -2432,6 +2432,7 @@ class Player extends Component { return this.scrubbing_; } this.scrubbing_ = !!isScrubbing; + this.techCall_('setScrubbing', this.scrubbing_); if (isScrubbing) { this.addClass('vjs-scrubbing'); diff --git a/src/js/tech/html5.js b/src/js/tech/html5.js index 2cefd8e678..51976e0968 100644 --- a/src/js/tech/html5.js +++ b/src/js/tech/html5.js @@ -520,6 +520,10 @@ class Html5 extends Tech { }); } + setScrubbing(isScrubbing) { + this.isScrubbing_ = isScrubbing; + } + /** * Set current time for the `HTML5` tech. * @@ -528,7 +532,11 @@ class Html5 extends Tech { */ setCurrentTime(seconds) { try { - this.el_.currentTime = seconds; + if (this.isScrubbing_ && this.el_.fastSeek) { + this.el_.fastSeek(seconds); + } else { + this.el_.currentTime = seconds; + } } catch (e) { log(e, 'Video is not ready. (Video.js)'); // this.warning(VideoJS.warnings.videoNotReady); diff --git a/test/unit/player.test.js b/test/unit/player.test.js index 69fbf5cc7e..26563c6291 100644 --- a/test/unit/player.test.js +++ b/test/unit/player.test.js @@ -1241,6 +1241,23 @@ QUnit.test('should add an audio player region if an audio el is used', function( player.dispose(); }); +QUnit.test('should setScrubbing when seeking or not seeking', function(assert) { + const player = TestHelpers.makePlayer(); + let isScrubbing; + + player.tech_.setScrubbing = (_isScrubbing) => { + isScrubbing = _isScrubbing; + }; + + assert.equal(player.scrubbing(), false, 'player is not scrubbing'); + + player.scrubbing(true); + assert.ok(isScrubbing, "tech's setScrubbing was called with true"); + + player.scrubbing(false); + assert.notOk(isScrubbing, "tech's setScrubbing was called with false"); +}); + QUnit.test('should not be scrubbing while not seeking', function(assert) { const player = TestHelpers.makePlayer(); diff --git a/test/unit/tech/html5.test.js b/test/unit/tech/html5.test.js index 65749f9654..65e67ba043 100644 --- a/test/unit/tech/html5.test.js +++ b/test/unit/tech/html5.test.js @@ -5,6 +5,7 @@ let tech; import Html5 from '../../../src/js/tech/html5.js'; import * as browser from '../../../src/js/utils/browser.js'; import document from 'global/document'; +import sinon from 'sinon'; QUnit.module('HTML5', { beforeEach(assert) { @@ -50,6 +51,38 @@ QUnit.module('HTML5', { } }); +QUnit.test('if setScrubbing is true and fastSeek is available, use it', function(assert) { + Object.defineProperty(tech.el(), 'currentTime', { + get: () => {}, + set: () => {}, + + writeable: true, + enumerable: false, + configurable: true + }); + + const currentTimeSpy = sinon.spy(tech.el(), 'currentTime', ['set']); + + tech.setCurrentTime(5); + assert.ok(currentTimeSpy.set.called, 'currentTime setter was called'); + assert.ok(currentTimeSpy.set.calledWith(5), 'currentTime setter was called with 5'); + + tech.setScrubbing(true); + + // when scrubbing is set but fastSeek isn't available, currentTime should still be called + tech.el().fastSeek = null; + tech.setCurrentTime(10); + assert.ok(currentTimeSpy.set.called, 'currentTime setter was called'); + assert.ok(currentTimeSpy.set.calledWith(10), 'currentTime setter was called with 10'); + + const fastSeekSpy = tech.el().fastSeek = sinon.spy(); + + tech.setCurrentTime(15); + assert.ok(currentTimeSpy.set.calledTwice, 'currentTime setter was only called twice and not a 3rd time for fastSeek'); + assert.ok(fastSeekSpy.called, 'fastSeek called'); + assert.ok(fastSeekSpy.calledWith(15), 'fastSeek called with 15'); +}); + QUnit.test('should be able to set playsinline attribute', function(assert) { assert.expect(2); diff --git a/test/unit/tech/tech-faker.js b/test/unit/tech/tech-faker.js index 7c6891a635..7c91830216 100644 --- a/test/unit/tech/tech-faker.js +++ b/test/unit/tech/tech-faker.js @@ -97,6 +97,7 @@ class TechFaker extends Tech { seeking() { return false; } + setScrubbing() {} fakeSourceset() { this.el_.src = this.options_.sourceset; this.el_.setAttribute('src', this.options_.sourceset);