diff --git a/docs/guides/angular.md b/docs/guides/angular.md index 409df3d26f..fd1dc6582c 100644 --- a/docs/guides/angular.md +++ b/docs/guides/angular.md @@ -52,7 +52,9 @@ export class VjsPlayerComponent implements OnInit, OnDestroy { } } ``` + Don't forget to include the Video.js CSS, located at `video.js/dist/video-js.css`. + ```css /* vjs-player.component.css */ @import '~video.js/dist/video-js.css'; diff --git a/docs/translations-needed.md b/docs/translations-needed.md index 556e254a43..8661eb771a 100644 --- a/docs/translations-needed.md +++ b/docs/translations-needed.md @@ -13,6 +13,7 @@ This default value is hardcoded as a default to the localize method in the SeekB ## Status of translations + | Language file | Missing translations | | ----------------------- | ----------------------------------------------------------------------------------- | | ar.json (missing 3) | progress bar timing: currentTime={1} duration={2} | @@ -941,4 +942,5 @@ This default value is hardcoded as a default to the localize method in the SeekB | | Picture-in-Picture | | zh-TW.json (missing 2) | Exit Picture-in-Picture | | | Picture-in-Picture | + diff --git a/sandbox/pip-disabled.html.example b/sandbox/pip-disabled.html.example new file mode 100644 index 0000000000..d911510725 --- /dev/null +++ b/sandbox/pip-disabled.html.example @@ -0,0 +1,72 @@ + + +
+ +You can use /sandbox/ for writing and testing your own code. Nothing in /sandbox/ will get checked into the repo, except files that end in .example (so don't edit or add those files). To get started run `npm start` and open the index.html
+npm start+
open http://localhost:9999/sandbox/index.html+
+ PiP disabled via disablepictureinpicture attribute. +
++ PiP disabled via disablePictureInPicture player option. +
+ + + + + diff --git a/src/js/control-bar/picture-in-picture-toggle.js b/src/js/control-bar/picture-in-picture-toggle.js index 2ce86b10f6..a4fbc77a57 100644 --- a/src/js/control-bar/picture-in-picture-toggle.js +++ b/src/js/control-bar/picture-in-picture-toggle.js @@ -27,13 +27,10 @@ class PictureInPictureToggle extends Button { constructor(player, options) { super(player, options); this.on(player, ['enterpictureinpicture', 'leavepictureinpicture'], this.handlePictureInPictureChange); + this.on(player, ['disablepictureinpicturechanged', 'loadedmetadata'], this.handlePictureInPictureEnabledChange); - // TODO: Activate button on player loadedmetadata event. // TODO: Deactivate button on player emptied event. - // TODO: Deactivate button if disablepictureinpicture attribute is present. - if (!document.pictureInPictureEnabled) { - this.disable(); - } + this.disable(); } /** @@ -46,6 +43,18 @@ class PictureInPictureToggle extends Button { return `vjs-picture-in-picture-control ${super.buildCSSClass()}`; } + /** + * Enables or disables button based on document.pictureInPictureEnabled property value + * or on value returned by player.disablePictureInPicture() method. + */ + handlePictureInPictureEnabledChange() { + if (!document.pictureInPictureEnabled || this.player_.disablePictureInPicture()) { + this.disable(); + } else { + this.enable(); + } + } + /** * Handles enterpictureinpicture and leavepictureinpicture on the player and change control text accordingly. * @@ -62,6 +71,7 @@ class PictureInPictureToggle extends Button { } else { this.controlText('Picture-in-Picture'); } + this.handlePictureInPictureEnabledChange(); } /** diff --git a/src/js/player.js b/src/js/player.js index 684ae663c2..8fc349b357 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -1119,6 +1119,7 @@ class Player extends Component { 'playsinline': this.options_.playsinline, 'preload': this.options_.preload, 'loop': this.options_.loop, + 'disablePictureInPicture': this.options_.disablePictureInPicture, 'muted': this.options_.muted, 'poster': this.poster(), 'language': this.language(), @@ -2981,6 +2982,22 @@ class Player extends Component { this.trigger('exitFullWindow'); } + /** + * Disable Picture-in-Picture mode. + * + * @param {boolean} value + * - true will disable Picture-in-Picture mode + * - false will enable Picture-in-Picture mode + */ + disablePictureInPicture(value) { + if (value === undefined) { + return this.techGet_('disablePictureInPicture'); + } + this.techCall_('setDisablePictureInPicture', value); + this.options_.disablePictureInPicture = value; + this.trigger('disablepictureinpicturechanged'); + } + /** * Check if the player is in Picture-in-Picture mode or tell the player that it * is or is not in Picture-in-Picture mode. diff --git a/src/js/tech/html5.js b/src/js/tech/html5.js index 2cefd8e678..74e11c65cd 100644 --- a/src/js/tech/html5.js +++ b/src/js/tech/html5.js @@ -405,6 +405,10 @@ class Html5 extends Tech { Dom.setAttribute(el, 'preload', this.options_.preload); } + if (this.options_.disablePictureInPicture !== undefined) { + el.disablePictureInPicture = this.options_.disablePictureInPicture; + } + // Update specific tag settings, in case they were overridden // `autoplay` has to be *last* so that `muted` and `playsinline` are present // when iOS/Safari or other browsers attempt to autoplay. @@ -1518,8 +1522,8 @@ Html5.resetMediaElement = function(el) { // Wrap native properties with a getter // The list is as followed // paused, currentTime, buffered, volume, poster, preload, error, seeking -// seekable, ended, playbackRate, defaultPlaybackRate, played, networkState -// readyState, videoWidth, videoHeight, crossOrigin +// seekable, ended, playbackRate, defaultPlaybackRate, disablePictureInPicture +// played, networkState, readyState, videoWidth, videoHeight, crossOrigin [ /** * Get the value of `paused` from the media element. `paused` indicates whether the media element @@ -1691,6 +1695,19 @@ Html5.resetMediaElement = function(el) { */ 'defaultPlaybackRate', + /** + * Get the value of 'disablePictureInPicture' from the video element. + * + * @method Html5#disablePictureInPicture + * @return {boolean} value + * - The value of `disablePictureInPicture` from the video element. + * - True indicates that the video can't be played in Picture-In-Picture mode + * - False indicates that the video can be played in Picture-In-Picture mode + * + * @see [Spec]{@link https://w3c.github.io/picture-in-picture/#disable-pip} + */ + 'disablePictureInPicture', + /** * Get the value of `played` from the media element. `played` returns a `TimeRange` * object representing points in the media timeline that have been played. @@ -1788,7 +1805,8 @@ Html5.resetMediaElement = function(el) { // Wrap native properties with a setter in this format: // set + toTitleCase(name) // The list is as follows: -// setVolume, setSrc, setPoster, setPreload, setPlaybackRate, setDefaultPlaybackRate, setCrossOrigin +// setVolume, setSrc, setPoster, setPreload, setPlaybackRate, setDefaultPlaybackRate, +// setDisablePictureInPicture, setCrossOrigin [ /** * Set the value of `volume` on the media element. `volume` indicates the current @@ -1880,6 +1898,18 @@ Html5.resetMediaElement = function(el) { */ 'defaultPlaybackRate', + /** + * Prevents the browser from suggesting a Picture-in-Picture context menu + * or to request Picture-in-Picture automatically in some cases. + * + * @method Html5#setDisablePictureInPicture + * @param {boolean} value + * The true value will disable Picture-in-Picture mode. + * + * @see [Spec]{@link https://w3c.github.io/picture-in-picture/#disable-pip} + */ + 'disablePictureInPicture', + /** * Set the value of `crossOrigin` from the media element. `crossOrigin` indicates * to the browser that should sent the cookies along with the requests for the diff --git a/src/js/tech/tech.js b/src/js/tech/tech.js index f1b8dc43d1..0f08f1f2ab 100644 --- a/src/js/tech/tech.js +++ b/src/js/tech/tech.js @@ -788,6 +788,22 @@ class Tech extends Component { } } + /** + * A method to check for the presence of the 'disablePictureInPicture'