# Embed

A poster and a play button in place of a player from another site, which loads only when the visitor asks, after consent.

### Known issues
Two things to know before you rely on it.

- The question has no button to take “Always play” back. To let a visitor withdraw it, offer the category as a checkbox in the cookie banner, with its “change” button: the banner’s answer is merged into the same record, and its `luz:consent` event lists what was withdrawn in `detail.withdrawn`.
- It has not been tested with a screen reader.

### Copy the markup
The link is the page without JavaScript, so write it as the page you want a reader to land on: it points to the video where it lives. `src` is the address of the player, in full, as the other site gives it (here, the privacy-enhanced embed address that YouTube gives for a video); LUZ builds no address and names no provider. The poster is your own image, on your own server: a poster fetched from the other site would reach it on page load.

`catalog.min.js` loads the element’s own file, `embed.min.js`, when it scans the page; a page without `catalog.min.js` loads that file on its own.

Embed markup
```html
<script type="module" src="https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/catalog.min.js"></script>

<luz-embed src="https://www.youtube-nocookie.com/embed/g5aPoRtF2vw?autoplay=1" consent="youtube">
  <a class="luz-embed__link" href="https://www.youtube.com/watch?v=g5aPoRtF2vw">
    <img class="luz-embed__poster" src="/media/apollo-16-poster.jpg" alt="" width="1280" height="720" loading="lazy">
    <span class="u-sr-only">Play video: </span>
    <span class="luz-embed__title">John Young’s Lunar Salute on Apollo 16</span>
  </a>
  <div class="luz-embed__ask" data-luz-embed-ask hidden>
    <p>This video is hosted by YouTube (Google). If you play it, YouTube receives your IP address and details of your browser, and may store information on your device. We receive none of it. <a href="/docs/privacy/">Privacy and storage</a></p>
    <div class="o-actions">
      <button class="luz-btn luz-btn--primary" type="button" value="once">Play this video</button>
      <button class="luz-btn luz-btn--primary" type="button" value="cancel">Do not play</button>
      <button class="luz-btn luz-btn--secondary" type="button" value="always">Always play YouTube videos on this site</button>
    </div>
  </div>
</luz-embed>
```

Your scripts can ask what the element would load:

Script that reads the address
```js
import { playerURL } from "@luz-ds/catalog/embed";

// The address the element would load, or null when it stays a link
const url = playerURL(document.querySelector("luz-embed"));
```

### Variants and options
There are no variants. The ratio is a property, and the hooks are attributes.

- `<luz-embed>`: The custom element the module defines: a block with the ratio of the frame. It wires itself when it connects
- `src`: Required. The full address of the player, written by you: `https:`, or of the page’s own origin. Anything else (`javascript:`, `http:` of another origin, a typo) leaves the link
- `consent`: The name of a category of the [cookie consent](https://nandovejer.github.io/luz/docs/catalog/cookie-consent/) (a lowercase letter, then lowercase letters, digits or hyphens, 32 at most). Until it is granted nothing is requested from the player’s origin, and a click asks first. Without an ask block and without the category granted, it stays the link
- `data-luz-consent-key`: The storage key of the choice, which must start with `luz-`; `luz-consent`, the banner’s, by default
- `data-luz-consent-days`, `data-luz-consent-policy`: Read from the [cookie banner](https://nandovejer.github.io/luz/docs/catalog/cookie-consent/) of the page, if there is one: how many days “Always” lasts (180 by default, 395 at most) and the version of the policy shown, stored with the choice
- `--luz-embed-ratio`: The ratio of the frame, `16 / 9` by default. Set it on the element: `style="--luz-embed-ratio: 4 / 3"`
- `.luz-embed__link`: The link of the page without JavaScript: it holds the poster and the title, and takes the frame whole. With JavaScript it becomes a `button.luz-embed__play` with the same children, so its name does not change
- `.luz-embed__poster`, `.luz-embed__title`: Your image, which covers the frame, and the title, on a scrim at its foot
- `.luz-embed__ask` with `data-luz-embed-ask`: Optional, `hidden` in the markup: the question that shows when the click needs a consent that is not there. Its buttons have a `value`: `once`, `always` or `cancel`
- `data-luz-state`: Written by the script: `ready`, `ask` or `playing`. Style it, never set it
- `playerURL(el)`: Exported by `@luz-ds/catalog/embed`: the validated address of the element, or `null`

### How it works
CSS from `@luz-ds/catalog` and a file of its own, `@luz-ds/catalog/embed` (`dist/embed.min.js`, under 1.5 kB compressed), which defines `<luz-embed>`. It uses no library, and the player’s own script, if any, runs only inside the frame, once loaded. A native video or audio does not need it: use the [player](https://nandovejer.github.io/luz/docs/components/player/). This is for what only another site can show.

- **Before the click:** the page holds a poster and a button, and requests nothing from the other site. When the pointer goes over the button, or focus reaches it, the browser is told to open a connection to the player’s origin (a `preconnect`, once per origin), unless the site wants consent and it is not granted.
- **The click:** if nothing needs consent, or it is granted, the frame is written with `autoplay` permission, and focus goes into it. If consent is needed, the question shows in its place and focus goes to its first button.
- **The question:** `value="once"` plays this video. `value="always"` plays it and stores the category, as the cookie banner does, in `localStorage` as `{"version":1,"expires":…,"asked":[…],"granted":[…],"given":"…"}`, merged into the record that is there so the banner’s categories stay, dispatches `luz:consent` on `document` and unlocks every other embed with that category. `value="cancel"` goes back to the poster, with focus on its button. Escape does nothing; the button that cancels is the way back.
- **The frame:** it has the title of the video, `allow` for the features players use, `allowfullscreen` and `referrerpolicy="strict-origin-when-cross-origin"`, which some players need to accept the embed.
- The script writes no text: every word is in your markup, in the page’s language.

A server that builds your pages can write `src` and save the poster when the content is saved, so a reader never contacts the other site before choosing to.

### Without JavaScript
The poster is a link with a visible title that opens the video where it lives, and the question stays hidden. It does the same when `src` is not valid, and when the category is not granted and there is no question to ask.

### Keyboard and ARIA
- **Keys:** Tab reaches the button; Enter or Space presses it, as on any button. In the question, Tab goes through its buttons. Escape does nothing.
- **Name:** the button has the name of the link it replaces: the hidden words “Play video:” then the title.
- **Focus:** to the first button of the question when it shows, into the frame when the player loads, back to the button on Do not play. Once the player is in the frame, its own keys and controls are the other site’s, and the page cannot reach them.
- **Language:** the question and the names are yours, in the page’s language. The player’s are the other site’s.

### When to use
Use it for a video, a map or any player that a page takes from another site. Loading such a frame sends the reader’s address to that site, and its script weighs more than the rest of the page; a poster and a button cost one image.

### When not to use
Do not use it for a video or sound you host: that is the [player](https://nandovejer.github.io/luz/docs/components/player/), which has controls that LUZ styles and a keyboard that LUZ tests.

- Do not use it for a link to a page that happens to have a video: that is a [card](https://nandovejer.github.io/luz/docs/components/card/) or a link.
- Do not use it to hide a frame the reader never asked for: it loads only after a click.

It replaces the iframe code that the other site gives you, and the facade scripts for one provider. Nothing in LUZ is removed.
