Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow 'playsinline' player option #4325

Merged
merged 9 commits into from
May 10, 2017
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.
*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a @see here as well?

* @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