## Custom video placeholder with lazy load for better performance

### Features

- Full styling control of video placeholders
- An image/picture is used for the poster which allows the use of src-set
- Videos and embeds are lazy loaded to reduce page load
- Embeds are prefetched on user interaction to improve performance
- HTML Web Component version

## Examples

### Image

The default setup for the plugin with an image and a video.
The poster is the first frame of the video.

### Embed

Embedded video from a third-party site e.g. Youtube, Vimeo, etc.
The poster is the middle frame of the video.

### No image

The placeholder is styled instead of using an image.

### Web component

## Installation

    $ npm install responsive-video-poster --save-dev

## Usage

Import or add the JS into your project, add the elements to your HTML and initialize the plugin if needed.

### JavaScript

    import { ResponsiveVideoPoster, ResponsiveVideoPosterAuto } from 'responsive-video-poster.js';

OR

    <script src="responsive-video-poster.js" type="module"></script>

### Web Component

    import { ResponsiveVideoPoster } from 'responsive-video-poster-wc.js';

OR

    <script src="responsive-video-poster-wc.js" type="module"></script>

### Initialize JS

    // Initialize a single element
    const responsiveVideoPosterDefault = ResponsiveVideoPoster({
      selector: '#responsive-video-poster--default'
    });

    // Initialize all elements with default options, these can be overridden by reinitializing or by data attributes on the element.
    ResponsiveVideoPosterAuto();

### Markup

#### JS

    <div class="responsive-video-poster">

        <button class="rvp-placeholder" aria-label="Play video">
          <span class="rvp-button" aria-hidden="true"><svg class="rvp-button-icon"> ... </svg></span>

          <img srcset="/images/720.jpg 720w, /images/1080.jpg 1080w" src="/images/1080.jpg" class="rvp-poster" width="1080" height="608" loading="lazy">
        </button>

        <video src="/videos/video.mp4" class="rvp-video" preload="none" width="1080" height="608"></video>

      </div>

#### Web Component

    <responsive-video-poster>
      ...
    </responsive-video-poster>

### Options

The options can be set via initialization in the JS or by attributes on the element, which will be given the highest priority. The property is changed from camel case to dash case with with the prefix 'rvp' added for the JS version e.g. "activeClass" to "rvp-active-class".

    <div class="responsive-video-poster" data-rvp-active-class="is-open">

    <responsive-video-poster active-class="is-open">

Property | Default | Type | Description
--- | --- | --- | ---
`selector` | '.responsive-video-poster' | String || Element | Container element selector.
`placeholderSelector` | '.rvp-placeholder' | String | Placeholder element selector.
`posterSelector` | '.rvp-poster' | String | Poster element selector.
`videoSelector` | '.rvp-video' | String | Video element selector.
`animClass` | 'is-anim' | String | CSS class to transition the video placeholder between states.
`activeClass` | 'is-active' | String | CSS class when placeholder is transitioned and the video is playing.
`playDelay` | 'transition' | Integer(ms) || 'transition' | Delay playing the video by set time or wait for the placeholder transition to finish.
`playDelayOffset` | 0 | Integer(ms) | Reduces playDelay to start loading the video before the placeholder has finished transitioning.
`hideControlsOnLoad` | true | Boolean | Hide video controls while transitioning placeholder.
`hideControlsOnFirstPlay` | false | Boolean | Hide video controls on first video play.
`preConnections` | [] | Array || Comma seperated list | Domains to preconnect to for loading an embed. Youtube and Vimeo are automatically preconnected.

### API

Property | Type | Description
--- | --- | ---
`instance.playVideo()` | Method | Plays the video.
`instance.getInfo()` | Object | Returns the element and its properties.

## Performance optimizations

Responsive image techniques(srcset, sizes, source, etc) are used to load the most appropriate image. Native lazy loading is used on the responsive poster image to reduce initial page load. The plugin should also work normally with lazy load plugins.

The video element includes preload="metadata" or preload="none" so the video is not loaded until the user interacts with it. This will reduce the initial page load but may create lag in playback for some users. This can be removed if not needed.

The embedded video includes srcdoc="" so the video and third-party scripts are not loaded until the user interacts with it. The 'preConnections' option can be used to pass domains to start pre-connect connections for loading an embedded video. this happens when the user hovers/taps on the video using the pointerover event. For example Youtube could use ['https://www.youtube.com', 'https://www.google.com'].

## Events

A 'playVideo' event is started once a user clicks the video placeholder. The event is ended once the placeholder has become inactive and the video starts playing.

    document.querySelector('#responsive-video-poster--default').addEventListener('playVideo', (event) => {
      console.log(`Action: ${event.detail.action}`);
    });

You can also attach this to the document.

    document.addEventListener('playVideo', (event) => {
      console.log(`Target: ${event.target.matches('#responsive-video-poster--default')}`, `Action: ${event.detail.action}`);
    });

## Compatibility

Supports all modern browsers at the time of release.

## Demo site

Clone the repo from Github and run the commands below.

    $ npm install
    $ npm run dev

### References

Lazy loading of an embedded video by Arthur Corenzan. Lazy load third-party resources with facades. HTML Web Components by Jim Nielsen
Covverr videos of Lago di braies and Lofoten rocks. Youtube video of Tustan Karpaty mountains.