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
+
+
+
+
+
+
+
+
+
diff --git a/src/js/player.js b/src/js/player.js
index e8e5b30c4d..afbaadfd1a 100644
--- a/src/js/player.js
+++ b/src/js/player.js
@@ -431,6 +431,9 @@ class Player extends Component {
// Set poster
this.poster_ = options.poster || '';
+ if (options.posterOptions) {
+ this.posterOpts_ = this.sanitisePosterOpts_(options.posterOptions);
+ }
// Set controls
this.controls_ = !!options.controls;
@@ -3714,32 +3717,45 @@ class Player extends Component {
*
* @fires Player#posterchange
*
- * @param {string} [src]
+ * @param {string | object} [opts]
+ * Poster image source URL, or object of settings
+ * @param {string} [opts.img]
* Poster image source URL
+ * @param {string} [opts.alt]
+ * Poster image alt text. Set to null by default, but add text if there is content
+ * in the poster image that should be read by a screen reader
+ * @param {Array} [opts.sources]
+ * Array of objects repreesenting element attributes
*
* @return {string}
* The current value of poster when getting
*/
- poster(src) {
- if (src === undefined) {
- return this.poster_;
+ poster(opts) {
+ // To be non-breaking, the getter returns a string. However the string will be
+ // the actual source chosen by the browser. In the case only a string is set, there
+ // is no change in behaviour.
+ if (opts === undefined) {
+ return this.posterImage.$('img').currentSrc || this.poster_;
}
- // The correct way to remove a poster is to set as an empty string
- // other falsey values will throw errors
- if (!src) {
- src = '';
- }
+ opts = this.sanitisePosterOpts_(opts);
- if (src === this.poster_) {
+ // No change
+ if (opts === this.posterOpts_) {
return;
}
- // update the internal poster variable
- this.poster_ = src;
+ // update the internal poster variables
+ this.poster_ = opts.img;
+ this.posterOpts_ = opts;
// update the tech's poster
- this.techCall_('setPoster', src);
+ // Don't set a poster if desirable to not have mis-matching posters on the tech and PosterImage
+ if (this.options_.noTechPoster || (opts && opts.sources && opts.sources.length > 0)) {
+ this.techCall_('setPoster', '');
+ } else {
+ this.techCall_('setPoster', opts.img);
+ }
this.isPosterFromTech_ = false;
@@ -3753,6 +3769,45 @@ class Player extends Component {
this.trigger('posterchange');
}
+ /**
+ * Get poster options. Unlike similar methods this is not also a setter, as
+ * options should be set with `poster()`
+ *
+ * @return {Object}
+ */
+ posterOpts() {
+ if (arguments) {
+ this.log.warn('`posterOpts()` is not a setter');
+ }
+ return this.posterOpts_;
+ }
+
+ /**
+ * Ensures poster options include a img
+ *
+ * @param {Object} opts
+ * @return {Object} opts
+ */
+ sanitisePosterOpts_(opts) {
+ if (!opts || typeof opts !== 'object') {
+ opts = {
+ img: opts
+ };
+ }
+
+ // If img is missing but have sources, use a source as the img
+ // If no img and no sources, make img an empty string so `poster(null)` works as before
+ if (!opts.img) {
+ if (opts.sources && opts.sources.length) {
+ opts.img = opts.sources[opts.sources.length - 1].srcset.split(',')[0];
+ } else {
+ opts.img = '';
+ }
+ }
+
+ return opts;
+ }
+
/**
* Some techs (e.g. YouTube) can provide a poster source in an
* asynchronous way. We want the poster component to use this
diff --git a/src/js/poster-image.js b/src/js/poster-image.js
index ad890323d0..57cba80617 100644
--- a/src/js/poster-image.js
+++ b/src/js/poster-image.js
@@ -62,6 +62,7 @@ class PosterImage extends ClickableComponent {
/**
* Get or set the `PosterImage`'s crossOrigin option.
*
+ *
* @param {string|null} [value]
* The value to set the crossOrigin to. If an argument is
* given, must be one of `'anonymous'` or `'use-credentials'`, or 'null'.
@@ -105,13 +106,14 @@ class PosterImage extends ClickableComponent {
* The `Player#posterchange` event that triggered this function.
*/
update(event) {
- const url = this.player().poster();
+ const opts = this.player().posterOpts_;
- this.setSrc(url);
+ this.setSrc(opts);
// If there's no poster source we should display:none on this component
// so it's not still clickable or right-clickable
- if (url) {
+ // TODO: is this catching all unset scenarios
+ if (opts.img) {
this.show();
} else {
this.hide();
@@ -123,9 +125,28 @@ class PosterImage extends ClickableComponent {
*
* @param {string} url
* The URL to the source for the `PosterImage`.
+ * @param {Object} [opts]
+ * Image options
+ * @param {Object} [opts.sources]
+ * An array of attributes to construct