Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MWPW-129910-Play video on hover #1106

Merged
merged 15 commits into from
Aug 16, 2023
7 changes: 5 additions & 2 deletions libs/blocks/aside/aside.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* Aside - v5.1
*/

import { decorateBlockBg, decorateBlockText } from '../../utils/decorate.js';
import { decorateBlockBg, decorateBlockText, applyHoverPlay } from '../../utils/decorate.js';
import { createTag } from '../../utils/utils.js';

// standard/default aside uses same text sizes as the split
Expand Down Expand Up @@ -54,7 +54,10 @@ function decorateLayout(el) {
const text = foreground.querySelector('h1, h2, h3, h4, h5, h6, p')?.closest('div');
text?.classList.add('text');
const media = foreground.querySelector(':scope > div:not([class])');
if (!el.classList.contains('notification')) media?.classList.add('image');
if (!el.classList.contains('notification')) {
media?.classList.add('image');
if (media?.querySelector('video')) applyHoverPlay(media.querySelector('video'));
}
chrischrischris marked this conversation as resolved.
Show resolved Hide resolved
const picture = text?.querySelector('picture');
const iconArea = picture ? (picture.closest('p') || createTag('p', null, picture)) : null;
iconArea?.classList.add('icon-area');
Expand Down
3 changes: 3 additions & 0 deletions libs/blocks/figure/figure.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { applyHoverPlay } from '../../utils/decorate.js';

function buildCaption(pEl) {
const figCaptionEl = document.createElement('figcaption');
pEl.classList.add('caption');
Expand All @@ -21,6 +23,7 @@ export function buildFigure(blockEl) {
}
const video = clone.querySelector('video');
if (video) {
applyHoverPlay(video);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since applyHoverPlay is only used when there is a video - we should instead dynamically import decorate.js. applyHoverPlay can be applied async so it should not affect perf

Suggested change
applyHoverPlay(video);
import('../../utils/decorate.js').then(({ applyHoverPlay }) => applyHoverPlay(video));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

figEl.prepend(video);
}
const caption = clone.querySelector('em');
Expand Down
4 changes: 2 additions & 2 deletions libs/blocks/marquee/marquee.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
/*
* Marquee - v6.0
*/
import { decorateButtons, getBlockSize } from '../../utils/decorate.js';
import { decorateButtons, getBlockSize, applyHoverPlay } from '../../utils/decorate.js';
import { decorateBlockAnalytics, decorateLinkAnalytics } from '../../martech/attributes.js';
import { createTag } from '../../utils/utils.js';

Expand Down Expand Up @@ -135,7 +135,7 @@ export default function init(el) {

if (media) {
media.classList.add('media');

if (media.querySelector('video')) applyHoverPlay(media.querySelector('video'));
if (media.querySelector('a[href$=".mp4"]')) {
decorateVideo(media);
} else {
Expand Down
3 changes: 2 additions & 1 deletion libs/blocks/media/media.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* media - consonant v5.1
*/

import { decorateBlockBg, decorateBlockText, getBlockSize, decorateTextOverrides } from '../../utils/decorate.js';
import { decorateBlockBg, decorateBlockText, getBlockSize, decorateTextOverrides, applyHoverPlay } from '../../utils/decorate.js';
import { decorateBlockAnalytics } from '../../martech/attributes.js';
import { createTag } from '../../utils/utils.js';

Expand Down Expand Up @@ -49,6 +49,7 @@ export default function init(el) {
if (image) image.classList.add('image');
const img = image.querySelector(':scope img');
if (header && img?.alt === '') img.alt = header.textContent;
if (image.querySelector('video')) applyHoverPlay(image.querySelector('video'));
chrischrischris marked this conversation as resolved.
Show resolved Hide resolved

// lists
if (row.querySelector('ul')) {
Expand Down
23 changes: 20 additions & 3 deletions libs/blocks/video/video.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
export default function init(a) {
const { pathname, hash } = a;

const isAutoplay = !!(hash?.includes('autoplay'));
const isNotLooped = !!(hash?.includes('autoplay1'));

const attrs = isAutoplay ? `playsinline autoplay ${isNotLooped ? '' : 'loop'} muted` : 'playsinline controls';
const playOnHover = !!(hash.includes('hoverplay'));
chrischrischris marked this conversation as resolved.
Show resolved Hide resolved
let attrs = '';
switch (true) {
case (isAutoplay === true && isNotLooped === false):
attrs = 'playsinline autoplay loop muted';
break;
case (playOnHover === true && isNotLooped === true):
attrs = 'playsinline autoplay muted data-hoverplay';
break;
case (isNotLooped === true):
attrs = 'playsinline autoplay muted';
break;
default:
attrs = 'playsinline controls';
}
chrischrischris marked this conversation as resolved.
Show resolved Hide resolved
const video = `<video ${attrs}>
<source src=".${pathname}" type="video/mp4" />
</video>`;
a.insertAdjacentHTML('afterend', video);
const videoElem = document.querySelector('video');
if (attrs.includes('data-hoverplay')) {
videoElem.addEventListener('mouseenter', () => { videoElem.play(); });
videoElem.addEventListener('mouseleave', () => { videoElem.pause(); });
}
a.remove();
}
11 changes: 10 additions & 1 deletion libs/utils/decorate.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,19 @@ function applyTextOverrides(el, override) {
}

export function decorateTextOverrides(el, options = ['-heading', '-body', '-detail']) {
const overrides = [...el.classList].filter((elClass) => options.findIndex((ovClass) => elClass.endsWith(ovClass)) >= 0);
const overrides = [...el.classList].filter(
(elClass) => options.findIndex((ovClass) => elClass.endsWith(ovClass)) >= 0,
);
if (!overrides.length) return;
overrides.forEach((override) => {
applyTextOverrides(el, override);
el.classList.remove(override);
});
}

export function applyHoverPlay(video) {
if (video.hasAttribute('data-hoverplay')) {
video.addEventListener('mouseenter', () => { video.play(); });
video.addEventListener('mouseleave', () => { video.pause(); });
}
}
6 changes: 6 additions & 0 deletions test/blocks/video/mocks/body.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@
https://main--blog--adobecom.hlx.page/media_17927691d22fe4e1bd058e94762a224fdc57ebb7b.mp4#autoplay1
</a>
</div>
<div class="video autoplay no-loop hoverplay">
<a href="https://main--milo--adobecom.hlx.page/media_1e798d01c6ddc7e7eadc8f134d69e4f8d7193fdbb.mp4#autoplay1#_hoverplay">
https://main--milo--adobecom.hlx.page/media_1e798d01c6ddc7e7eadc8f134d69e4f8d7193fdbb.mp4#autoplay1#_hoverplay
</a>
</div>
</div>
</main>
13 changes: 13 additions & 0 deletions test/blocks/video/video.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,17 @@ describe('video uploaded using franklin bot', () => {

expect(block.firstElementChild.hasAttribute('loop')).to.be.false;
});

it('decorates video with autoplay, no loop and hover play', async () => {
chrischrischris marked this conversation as resolved.
Show resolved Hide resolved
const block = document.querySelector('.video.no-loop.hoverplay');
const a = block.querySelector('a');
const { href } = a;
a.textContent = href;
block.append(a);

init(a);

expect(block.firstElementChild.hasAttribute('loop')).to.be.false;
expect(block.firstElementChild.hasAttribute('data-hoverplay')).to.be.true;
});
});