Skip to content

Commit

Permalink
feat: add 'playsinline' player option (#4325)
Browse files Browse the repository at this point in the history
Video.js players can accept a number of standard <video> element options (autoplay, muted, loop, etc), but not currently playsinline, which is now part of the [HTML spec](https://html.spec.whatwg.org/multipage/embedded-content.html#attr-video-playsinline). We should add it to the list of <video> attributes that can be provided to the player as options.
  • Loading branch information
alex-barstow authored and gkatsev committed May 10, 2017
1 parent 6cf7327 commit 946f84b
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 2 deletions.
26 changes: 26 additions & 0 deletions src/js/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,7 @@ class Player extends Component {
'textTracks': this.textTracks_,
'audioTracks': this.audioTracks_,
'autoplay': this.options_.autoplay,
'playsinline': this.options_.playsinline,
'preload': this.options_.preload,
'loop': this.options_.loop,
'muted': this.options_.muted,
Expand Down Expand Up @@ -2385,6 +2386,31 @@ class Player extends Component {
return this.techGet_('autoplay', value);
}

/**
* Set or unset the playsinline attribute.
* Playsinline tells the browser that non-fullscreen playback is preferred.
*
* @param {boolean} [value]
* - true means that we should try to play inline by default
* - false means that we should use the browser's default playback mode,
* which in most cases is inline. iOS Safari is a notable exception
* and plays fullscreen by default.
*
* @return {string|Player}
* - the current value of playsinline
* - the player when setting
*
* @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline}
*/
playsinline(value) {
if (value !== undefined) {
this.techCall_('setPlaysinline', value);
this.options_.playsinline = value;
return this;
}
return this.techGet_('playsinline');
}

/**
* Get or set the loop attribute on the video element.
*
Expand Down
39 changes: 38 additions & 1 deletion src/js/tech/html5.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ class Html5 extends Tech {
}

// Update specific tag settings, in case they were overridden
const settingsAttrs = ['autoplay', 'preload', 'loop', 'muted'];
const settingsAttrs = ['autoplay', 'preload', 'loop', 'muted', 'playsinline'];

for (let i = settingsAttrs.length - 1; i >= 0; i--) {
const attr = settingsAttrs[i];
Expand Down Expand Up @@ -795,6 +795,43 @@ class Html5 extends Tech {
}
}

/**
* Get the value of `playsinline` from the media element. `playsinline` indicates
* to the browser that non-fullscreen playback is preferred when fullscreen
* playback is the native default, such as in iOS Safari.
*
* @method Html5#playsinline
* @return {boolean}
* - The value of `playsinline` from the media element.
* - True indicates that the media should play inline.
* - False indicates that the media should not play inline.
*
* @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline}
*/
playsinline() {
return this.el_.hasAttribute('playsinline');
}

/**
* Set the value of `playsinline` from the media element. `playsinline` indicates
* to the browser that non-fullscreen playback is preferred when fullscreen
* playback is the native default, such as in iOS Safari.
*
* @method Html5#setPlaysinline
* @param {boolean} playsinline
* - True indicates that the media should play inline.
* - False indicates that the media should not play inline.
*
* @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline}
*/
setPlaysinline(value) {
if (value) {
this.el_.setAttribute('playsinline', 'playsinline');
} else {
this.el_.removeAttribute('playsinline');
}
}

/**
* Gets available media playback quality metrics as specified by the W3C's Media
* Playback Quality API.
Expand Down
14 changes: 14 additions & 0 deletions src/js/tech/tech.js
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,20 @@ class Tech extends Component {
*/
setPoster() {}

/**
* A method to check for the presence of the 'playsinine' <video> attribute.
*
* @abstract
*/
playsinline() {}

/**
* A method to set or unset the 'playsinine' <video> attribute.
*
* @abstract
*/
setPlaysinline() {}

/*
* Check if the tech can support the given mime-type.
*
Expand Down
27 changes: 27 additions & 0 deletions test/unit/player.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,33 @@ QUnit.test('should restore attributes from the original video tag when creating
assert.equal(el.getAttribute('webkit-playsinline'), '', 'webkit-playsinline attribute was set properly');
});

QUnit.test('player.playsinline() should be able to get/set playsinline attribute', function(assert) {
assert.expect(5);

const video = document.createElement('video');
const player = TestHelpers.makePlayer({techOrder: ['html5']}, video);

// test setter
assert.ok(!player.tech_.el().hasAttribute('playsinline'), 'playsinline has not yet been added');

player.playsinline(true);

assert.ok(player.tech_.el().hasAttribute('playsinline'), 'playsinline attribute added');

player.playsinline(false);

assert.ok(!player.tech_.el().hasAttribute('playsinline'), 'playsinline attribute removed');

// test getter
player.tech_.el().setAttribute('playsinline', 'playsinline');

assert.ok(player.playsinline(), 'correctly detects playsinline attribute');

player.tech_.el().removeAttribute('playsinline');

assert.ok(!player.playsinline(), 'correctly detects absence of playsinline attribute');
});

QUnit.test('if tag exists and movingMediaElementInDOM, re-use the tag', function(assert) {
// simulate attributes stored from the original tag
const tag = Dom.createEl('video');
Expand Down
3 changes: 2 additions & 1 deletion test/unit/setup.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ QUnit.test('should set options from data-setup even if autoSetup is not called b
const el = TestHelpers.makeTag();

el.setAttribute('data-setup',
'{"controls": true, "autoplay": false, "preload": "auto"}');
'{"controls": true, "autoplay": false, "preload": "auto", "playsinline": true}');

const player = TestHelpers.makePlayer({}, el);

assert.ok(player.options_.controls === true);
assert.ok(player.options_.autoplay === false);
assert.ok(player.options_.preload === 'auto');
assert.ok(player.options_.playsinline === true);
player.dispose();
});
13 changes: 13 additions & 0 deletions test/unit/tech/html5.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,19 @@ QUnit.module('HTML5', {
}
});

QUnit.test('should be able to set playsinline attribute', function(assert) {
assert.expect(2);

tech.createEl();
tech.setPlaysinline(true);

assert.ok(tech.el().hasAttribute('playsinline'), 'playsinline attribute was added');

tech.setPlaysinline(false);

assert.ok(!tech.el().hasAttribute('playsinline'), 'playsinline attribute was removed');
});

QUnit.test('should detect whether the volume can be changed', function(assert) {

if (!{}.__defineSetter__) {
Expand Down

0 comments on commit 946f84b

Please sign in to comment.