From 0c0200a429e475cbfe3ae3f9a8c72baebafcad99 Mon Sep 17 00:00:00 2001 From: Drashti Modasara Date: Tue, 5 Dec 2023 15:56:38 +0530 Subject: [PATCH] Genfill changes --- .../interactive-marquee.js | 8 ++ .../interactive-marquee/milo-marquee.css | 5 + .../features/genfill/genfill-interactive.css | 106 ++++++++++++++++++ .../features/genfill/genfill-interactive.js | 103 +++++++++++++++++ creativecloud/scripts/scripts.js | 29 +++-- .../interactive-marquee.test.js | 39 +++++++ .../interactive-marquee/mocks/container.html | 26 +++++ .../genfill/genfill-interactive.test.js | 32 ++++++ test/features/genfill/mocks/genfill.html | 88 +++++++++++++++ 9 files changed, 424 insertions(+), 12 deletions(-) create mode 100644 creativecloud/features/genfill/genfill-interactive.css create mode 100644 creativecloud/features/genfill/genfill-interactive.js create mode 100644 test/blocks/interactive-marquee/interactive-marquee.test.js create mode 100644 test/blocks/interactive-marquee/mocks/container.html create mode 100644 test/features/genfill/genfill-interactive.test.js create mode 100644 test/features/genfill/mocks/genfill.html diff --git a/creativecloud/blocks/interactive-marquee/interactive-marquee.js b/creativecloud/blocks/interactive-marquee/interactive-marquee.js index 4eccf3b79..a175ec209 100644 --- a/creativecloud/blocks/interactive-marquee/interactive-marquee.js +++ b/creativecloud/blocks/interactive-marquee/interactive-marquee.js @@ -76,6 +76,14 @@ export default async function init(el) { changeBg(el); break; } + case el.classList.contains('genfill'): { + loadStyle('/creativecloud/blocks/interactive-marquee/milo-marquee.css'); + loadStyle('/creativecloud/features/genfill/genfill-interactive.css'); + interactiveInit(el, decorateButtons, decorateBlockBg, createTag); + const { default: decorateGenfill } = await import('../../features/genfill/genfill-interactive.js'); + await decorateGenfill(el); + break; + } case el.classList.contains('firefly'): { loadStyle('/creativecloud/blocks/interactive-marquee/milo-marquee.css'); loadStyle('/creativecloud/features/interactive-elements/interactive-elements.css'); diff --git a/creativecloud/blocks/interactive-marquee/milo-marquee.css b/creativecloud/blocks/interactive-marquee/milo-marquee.css index 2fb276283..31591f724 100644 --- a/creativecloud/blocks/interactive-marquee/milo-marquee.css +++ b/creativecloud/blocks/interactive-marquee/milo-marquee.css @@ -28,6 +28,7 @@ position: relative; top: 63px; /* mobile */ margin: 0 auto; + cursor: pointer; } .interactive-marquee .text { @@ -38,6 +39,10 @@ order: 2; } +[dir="rtl"] .interactive-marquee .text { + margin: 0 auto 0 0; +} + .interactive-marquee .text p:last-of-type { margin-bottom: 0; } diff --git a/creativecloud/features/genfill/genfill-interactive.css b/creativecloud/features/genfill/genfill-interactive.css new file mode 100644 index 000000000..13de115de --- /dev/null +++ b/creativecloud/features/genfill/genfill-interactive.css @@ -0,0 +1,106 @@ +.genfill .desktop-only, +.genfill .tablet-only, +.genfill .mobile-only { + -webkit-tap-highlight-color: transparent; + user-select: none; + display: none; +} + +.genfill .enticement-detail, +.genfill .enticement-mode, +.genfill .timer { + display: none; +} + +.genfill .media a { + display: none; +} + +.enticement-arrow { + display: none; + width: 49px; + height: 73px; + position: absolute; +} + +.enticement-text { + display: none; + max-width: 30ch; + position: absolute; + font-size: 28px; + line-height: 35px; + margin: 40px 0 16px -20px; + top: -90px; + color: var(--color-white); +} + +.enticement-text.light { + color: var(--color-black); +} + +@media screen and (max-width: 600px) { + .genfill .mobile-only a { + display: none; + } + + .genfill .media.mobile-only, + .genfill .media.mobile-only a:first-of-type { + display: block; + } + + .genfill .enticement { + display: none; + } +} + +@media screen and (min-width: 600px) and (max-width: 1200px) { + .genfill .tablet-only a { + display: none; + } + + .genfill .tablet-only, + .genfill .tablet-only a:first-of-type { + display: block; + } + + .enticement-arrow { + right: 575px; + top: -30px; + display: block; + } + + .enticement-text { + display: block; + } + + [dir="rtl"] .enticement-text { + position: absolute; + left: var(--spacing-xxs); + } +} + +@media screen and (min-width: 1200px) { + .genfill .desktop-only a { + display: none; + } + + .genfill .desktop-only, + .genfill .desktop-only a:first-of-type { + display: block; + } + + .enticement-arrow { + right: 575px; + top: -30px; + display: block; + } + + .enticement-text { + display: block; + } + + [dir="rtl"] .enticement-text { + position: absolute; + left: var(--spacing-xxs); + } +} diff --git a/creativecloud/features/genfill/genfill-interactive.js b/creativecloud/features/genfill/genfill-interactive.js new file mode 100644 index 000000000..43ca16ddb --- /dev/null +++ b/creativecloud/features/genfill/genfill-interactive.js @@ -0,0 +1,103 @@ +import { getLibs } from '../../scripts/utils.js'; +import { createEnticement } from '../interactive-elements/interactive-elements.js'; +import defineDeviceByScreenSize from '../../scripts/decorate.js'; + +function handleTransition(pics, index) { + pics[index].style.display = 'none'; + const nextIndex = (index + 1) % pics.length; + pics[nextIndex].style.display = 'block'; + return nextIndex; +} + +function startAutocycle(interval, pics, clickConfig) { + if (clickConfig.isImageClicked) return; + clickConfig.autocycleInterval = setInterval(() => { + clickConfig.autocycleIndex = handleTransition(pics, clickConfig.autocycleIndex); + if (clickConfig.autocycleIndex === pics.length - 1) { + clearInterval(clickConfig.autocycleInterval); + } + }, interval); +} + +function handleClick(aTags, clickConfig) { + aTags.forEach((a, i) => { + a.querySelector('img').removeAttribute('loading'); + a.addEventListener('click', () => { + clickConfig.isImageClicked = true; + if (clickConfig.autocycleInterval) clearInterval(clickConfig.autocycleInterval); + handleTransition(aTags, i); + }); + }); +} + +async function addEnticement(container, enticement, mode) { + const svgUrl = enticement.querySelector('a').href; + const enticementText = enticement.innerText; + const entcmtEl = await createEnticement(`${enticementText}|${svgUrl}`, mode); + entcmtEl.classList.add('enticement'); + const n = container.children.length; + const desktopMedia = container.querySelector('.desktop-only'); + const tabletMedia = (n > 2) ? container.querySelector('.tablet-only') : null; + desktopMedia.insertBefore(entcmtEl, desktopMedia.firstElementChild); + tabletMedia?.insertBefore(entcmtEl.cloneNode(true), tabletMedia.firstElementChild); +} + +async function removePTags(media, vi) { + const heading = media.closest('.foreground').querySelector('h1, h2, h3, h4, h5, h6'); + const hText = heading.id + .split('-').map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(''); + const miloLibs = getLibs(); + const { createTag } = await import(`${miloLibs}/utils/utils.js`); + const pics = media.querySelectorAll('picture'); + pics.forEach((pic, index) => { + if (pic.closest('p')) pic.closest('p').remove(); + const a = createTag('a', { class: 'genfill-link' }); + const img = pic.querySelector('img'); + const altTxt = img.alt + ? `${img.alt}|Marquee|${hText}` + : `Image-${vi}-${index}|Marquee|${hText}`; + a.setAttribute('daa-ll', altTxt); + a.appendChild(pic); + media.appendChild(a); + }); +} + +export default async function decorateGenfill(el) { + const clickConfig = { + autocycleIndex: 0, + autocycleInterval: null, + isImageClicked: false, + }; + const interactiveContainer = el.querySelector('.interactive-container'); + const allP = interactiveContainer.querySelectorAll('.media:first-child p'); + const pMetadata = [...allP].filter((p) => !p.querySelector('picture')); + const [enticementMode, enticement, timer = null] = [...pMetadata]; + enticementMode.classList.add('enticement-mode'); + enticement.classList.add('enticement-detail'); + timer?.classList.add('timer'); + const mode = enticementMode.innerText.includes('light') ? 'light' : 'dark'; + const timerValues = timer ? timer.innerText.split('|') : null; + const [intervalTime = 2000, delayTime = 1000] = (timerValues && timerValues.length > 1) + ? timerValues : [2000]; + [enticementMode, enticement, timer].forEach((i) => i?.remove()); + const viewports = ['mobile', 'tablet', 'desktop']; + const mediaElements = interactiveContainer.querySelectorAll('.media'); + mediaElements.forEach(async (mediaEl, index) => { + await removePTags(mediaEl, index); + const aTags = mediaEl.querySelectorAll('a'); + handleClick(aTags, clickConfig); + }); + viewports.forEach((v, vi) => { + const media = mediaElements[vi] + ? mediaElements[vi] + : interactiveContainer.lastElementChild; + media.classList.add(`${v}-only`); + if (defineDeviceByScreenSize() === v.toUpperCase()) { + setTimeout(() => { + const aTags = media.querySelectorAll('a'); + startAutocycle(intervalTime, aTags, clickConfig); + }, delayTime); + } + }); + addEnticement(interactiveContainer, enticement, mode); +} diff --git a/creativecloud/scripts/scripts.js b/creativecloud/scripts/scripts.js index 5c3294154..22378b8d4 100644 --- a/creativecloud/scripts/scripts.js +++ b/creativecloud/scripts/scripts.js @@ -155,18 +155,23 @@ const eagerLoad = (img) => { (async function loadLCPImage() { const firstDiv = document.querySelector('body > main > div:nth-child(1) > div'); - if (firstDiv?.classList.contains('marquee')) { - firstDiv.querySelectorAll('img').forEach(eagerLoad); - } else if (firstDiv?.classList.contains('changebg')) { - firstDiv.querySelector(':scope > div:nth-child(1)').querySelectorAll('img').forEach(eagerLoad); - import(`${CONFIG.codeRoot}/deps/interactive-marquee-changebg/changeBgMarquee.js`); - } else if (firstDiv?.classList.contains('interactive-marquee')) { - firstDiv.querySelector(':scope > div:nth-child(1)').querySelectorAll('img').forEach(eagerLoad); - if (firstDiv?.classList.contains('firefly')) { - firstDiv.querySelector(':scope > div:nth-child(2)').querySelectorAll('img').forEach(async (img) => eagerLoad(img)); - } - } else { - eagerLoad(document.querySelector('img')); + let fgDivs = null; + switch (true) { + case firstDiv?.classList.contains('changebg'): + firstDiv.querySelector(':scope > div:nth-child(1)').querySelectorAll('img').forEach(eagerLoad); + import(`${CONFIG.codeRoot}/deps/interactive-marquee-changebg/changeBgMarquee.js`); + break; + case firstDiv?.classList.contains('marquee'): + firstDiv.querySelectorAll('img').forEach(eagerLoad); + break; + case firstDiv?.classList.contains('interactive-marquee'): + firstDiv.querySelector(':scope > div:nth-child(1)').querySelectorAll('img').forEach(eagerLoad); + fgDivs = firstDiv.querySelector(':scope > div:nth-child(2)').querySelectorAll('div:not(:first-child)'); + fgDivs.forEach((d) => eagerLoad(d.querySelector('img'))); + break; + default: + eagerLoad(document.querySelector('img')); + break; } }()); diff --git a/test/blocks/interactive-marquee/interactive-marquee.test.js b/test/blocks/interactive-marquee/interactive-marquee.test.js new file mode 100644 index 000000000..1ec1c6d54 --- /dev/null +++ b/test/blocks/interactive-marquee/interactive-marquee.test.js @@ -0,0 +1,39 @@ +import { readFile } from '@web/test-runner-commands'; +import { expect } from '@esm-bundle/chai'; + +document.body.innerHTML = await readFile({ path: './mocks/container.html' }); +const { setLibs } = await import('../../../creativecloud/scripts/utils.js'); +const { default: init } = await import('../../../creativecloud/blocks/interactive-marquee/interactive-marquee.js'); + +describe('interactive marquee', () => { + const im = document.querySelector('.interactive-marquee'); + before(async () => { + setLibs('https://milo.adobe.com/libs'); + await init(im); + }); + it('interactive marquee light variant should exist', () => { + const light = im.classList.contains('light'); + expect(light).to.true; + }); + + it('has the interactive-area', () => { + const container = im.querySelector('.foreground .interactive-container'); + expect(container).to.exist; + }); + + it('has a heading-xxl', () => { + const heading = im.querySelector('.heading-xxl'); + expect(heading).to.exist; + }); + + it('has an icon area', () => { + const iconArea = im.querySelector('.icon-area'); + expect(iconArea).to.exist; + }); + + it('should have icon text', () => { + const iconText = im.querySelector('.icon-text'); + expect(iconText).to.exist; + expect(iconText.classList.contains('heading-xs')).to.be.true; + }); +}); diff --git a/test/blocks/interactive-marquee/mocks/container.html b/test/blocks/interactive-marquee/mocks/container.html new file mode 100644 index 000000000..83e363e17 --- /dev/null +++ b/test/blocks/interactive-marquee/mocks/container.html @@ -0,0 +1,26 @@ +
+
+
+ + + +
+
+
+
+

+ + + Photoshop +

+

Edit photos online with Adobe Photoshop

+

Add, remove, or expand content in images right in your browser with Photoshop on the web. Included in every Photoshop plan.

+

Free Trial Explore Photoshop online

+
+
+ + Jungle + +
+
+
diff --git a/test/features/genfill/genfill-interactive.test.js b/test/features/genfill/genfill-interactive.test.js new file mode 100644 index 000000000..8a863ad72 --- /dev/null +++ b/test/features/genfill/genfill-interactive.test.js @@ -0,0 +1,32 @@ +import { readFile } from '@web/test-runner-commands'; +import { expect } from '@esm-bundle/chai'; + +document.body.innerHTML = await readFile({ path: './mocks/genfill.html' }); +const { setLibs } = await import('../../../creativecloud/scripts/utils.js'); +const { default: init } = await import('../../../creativecloud/blocks/interactive-marquee/interactive-marquee.js'); + +describe('genfill variant of interactive marquee', () => { + const im = document.querySelector('.interactive-marquee'); + before(async () => { + setLibs('https://milo.adobe.com/libs'); + await init(im); + }); + it('desktop media should exist', () => { + const desktop = im.querySelector('.desktop-only'); + expect(desktop).to.exist; + }); + it('tablet media should exist', () => { + const tablet = im.querySelector('.tablet-only'); + expect(tablet).to.exist; + }); + it('mobile media should exist', () => { + const mobile = im.querySelector('.mobile-only'); + expect(mobile).to.exist; + }); + it('should have proper enticement', () => { + const ent = im.querySelector('.enticement'); + expect(ent).to.exist; + expect(ent.querySelector('.enticement-text')).to.exist; + expect(ent.querySelector('.enticement-arrow')).to.exist; + }); +}); diff --git a/test/features/genfill/mocks/genfill.html b/test/features/genfill/mocks/genfill.html new file mode 100644 index 000000000..a3aad1b62 --- /dev/null +++ b/test/features/genfill/mocks/genfill.html @@ -0,0 +1,88 @@ +
+
+
+ + + +
+
+
+
+

+ + + Photoshop +

+

Edit photos online with Adobe Photoshop

+

Add, remove, or expand content in images right in your browser with Photoshop on the web. Included in every Photoshop plan.

+

Free Trial Explore Photoshop online

+
+
+

Enticement

+

See it in action

+

2000|0

+

+ + + +

+

+ + + +

+

+ + + +

+

+ + + +

+

+ + + +

+

+ + + +

+

+ + + +

+
+
+

+ + + +

+

+ + + +

+

+ + + +

+

+ + + +

+

+ + + +

+
+
+