diff --git a/package-lock.json b/package-lock.json index 0388d9df61..6a5fe4f3f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6539,9 +6539,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", diff --git a/src/modules/esl-media/README.md b/src/modules/esl-media/README.md index 70a2484f51..0e22b84349 100644 --- a/src/modules/esl-media/README.md +++ b/src/modules/esl-media/README.md @@ -86,6 +86,7 @@ using a single tag as well as work with external providers using simple native-l - `start-time` - attribute that allows a user to start viewing a video from a specific time offset. The value is simple time in seconds. By default, it is undefined which means to start from the beginning. *(note: that feature doesn't work for Abstract Iframe provider, also doesn't work for HTMLAudio and HTMLVideo providers in case when Web-server when hosted resource doesn't support ['Accept-Ranges' HTTP response marker](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Ranges))* + - `focusable` (boolean) - marker that allows the video to be focused by keyboard navigation. By default, the video is focusable if `controls` are enabled. #### Deprecated attributes (going to be removed in the next major release): - `load-cls-accepted` (optional) - class to add when the media is loaded and accepted by the load condition. Use `load-condition-class` instead. diff --git a/src/modules/esl-media/core/esl-media-provider.ts b/src/modules/esl-media/core/esl-media-provider.ts index c9f44d6f12..cfc4756e62 100644 --- a/src/modules/esl-media/core/esl-media-provider.ts +++ b/src/modules/esl-media/core/esl-media-provider.ts @@ -23,6 +23,7 @@ export interface MediaProviderConfig { preload?: 'none' | 'metadata' | 'auto' | ''; playsinline?: boolean; startTime?: number; + focusable?: boolean; } export type ProviderType = (new(component: ESLMedia, config: MediaProviderConfig) => BaseProvider) & typeof BaseProvider; @@ -40,8 +41,8 @@ export abstract class BaseProvider { return null; } static parseConfig(component: ESLMedia): MediaProviderConfig { - const {loop, muted, controls, autoplay, title, preload, playsinline, mediaId, mediaSrc, startTime} = component; - const config = {loop, muted, controls, autoplay, title, preload, playsinline, startTime}; + const {loop, muted, controls, autoplay, title, preload, playsinline, mediaId, mediaSrc, startTime, focusable} = component; + const config = {loop, muted, controls, autoplay, title, preload, playsinline, startTime, focusable}; if (mediaId) Object.assign(config, {mediaId}); if (mediaSrc) Object.assign(config, {mediaSrc}); return config; diff --git a/src/modules/esl-media/core/esl-media.ts b/src/modules/esl-media/core/esl-media.ts index d9de1a2b3e..fa1363dd55 100644 --- a/src/modules/esl-media/core/esl-media.ts +++ b/src/modules/esl-media/core/esl-media.ts @@ -5,7 +5,7 @@ import {CSSClassUtils} from '../../esl-utils/dom/class'; import {SPACE, PAUSE} from '../../esl-utils/dom/keys'; import {prop, attr, boolAttr, listen} from '../../esl-utils/decorators'; import {debounce} from '../../esl-utils/async'; -import {parseAspectRatio} from '../../esl-utils/misc/format'; +import {parseAspectRatio, parseBoolean} from '../../esl-utils/misc/format'; import {ESLMediaQuery} from '../../esl-media-query/core'; import {ESLResizeObserverTarget} from '../../esl-event-listener/core'; @@ -101,6 +101,9 @@ export class ESLMedia extends ESLBaseElement { @boolAttr() public playInViewport: boolean; /** Allows to start viewing a resource from a specific time offset. */ @attr({parser: parseInt}) public startTime: number; + /** Allows player to accept focus */ + @attr({parser: parseBoolean, defaultValue: ($this: ESLMedia) => $this.controls}) public focusable: boolean; + /** Preload resource */ @attr({defaultValue: 'auto'}) public preload: 'none' | 'metadata' | 'auto' | ''; diff --git a/src/modules/esl-media/providers/html5/media-provider.ts b/src/modules/esl-media/providers/html5/media-provider.ts index 928cabede6..59765574b1 100644 --- a/src/modules/esl-media/providers/html5/media-provider.ts +++ b/src/modules/esl-media/providers/html5/media-provider.ts @@ -25,7 +25,7 @@ export abstract class HTMLMediaProvider extends BaseProvider { el.loop = cfg.loop; el.muted = cfg.muted; el.controls = cfg.controls; - el.tabIndex = 0; + el.tabIndex = cfg.focusable ? 0 : -1; el.toggleAttribute('playsinline', cfg.playsinline); return el; } diff --git a/src/modules/esl-media/providers/iframe-provider.ts b/src/modules/esl-media/providers/iframe-provider.ts index 7993ffc548..584df2fb25 100644 --- a/src/modules/esl-media/providers/iframe-provider.ts +++ b/src/modules/esl-media/providers/iframe-provider.ts @@ -32,7 +32,7 @@ export class IframeBasicProvider extends BaseProvider { el.title = this.config.title; el.setAttribute('aria-label', this.config.title); el.setAttribute('frameborder', '0'); - el.setAttribute('tabindex', '0'); + el.setAttribute('tabindex', this.config.focusable ? '0' : '-1'); el.setAttribute('scrolling', 'no'); el.setAttribute('allowfullscreen', 'yes'); el.toggleAttribute('playsinline', this.config.playsinline); diff --git a/src/modules/esl-media/providers/youtube-provider.ts b/src/modules/esl-media/providers/youtube-provider.ts index 8bd1f5f889..342c8bf8bb 100644 --- a/src/modules/esl-media/providers/youtube-provider.ts +++ b/src/modules/esl-media/providers/youtube-provider.ts @@ -71,7 +71,7 @@ export class YouTubeProvider extends BaseProvider { el.title = sm.title; el.setAttribute('aria-label', el.title); el.setAttribute('frameborder', '0'); - el.setAttribute('tabindex', '0'); + el.setAttribute('tabindex', sm.focusable ? '0' : '-1'); el.setAttribute('allowfullscreen', 'yes'); return el; }