diff --git a/blocks/carousel/carousel.css b/blocks/carousel/carousel.css index a7c76a6..5d8dfe1 100644 --- a/blocks/carousel/carousel.css +++ b/blocks/carousel/carousel.css @@ -64,11 +64,11 @@ background-color: #ed3e49; } -.carousel-wrapper .carousel.block .carousel-title-wrapper .carousel-title.courses::before { +.carousel-wrapper .carousel.block[class*='courses'] .carousel-title-wrapper .carousel-title::before { background-color: #105259; } -.carousel-wrapper .carousel.block .carousel-title-wrapper .carousel-title.loop::before { +.carousel-wrapper .carousel.block[class*='loop'] .carousel-title-wrapper .carousel-title::before { background-color: #e8b94d; } diff --git a/blocks/default-article/default-article.css b/blocks/default-article/default-article.css index 8ad279c..07b0709 100644 --- a/blocks/default-article/default-article.css +++ b/blocks/default-article/default-article.css @@ -9,6 +9,12 @@ padding: 20px; } +@media (min-width: 1025px) { + .default-article-wrapper .default-article.block .container { + margin-top: 40px; + } +} + .default-article-wrapper .default-article.block .container .gd-plus-icon { border-right: 2px solid #f6f6f6; margin-right: 10px; diff --git a/blocks/default-article/default-article.js b/blocks/default-article/default-article.js index c8716f9..30482cf 100644 --- a/blocks/default-article/default-article.js +++ b/blocks/default-article/default-article.js @@ -2,6 +2,7 @@ import { addPhotoCredit, addPortraitClass, assignSlot, + createAndInsertTrendingBannerBlock, generateArticleBlocker, normalizeAuthorURL, parseFragment, @@ -29,6 +30,7 @@ export default async function decorate(block) { // HTML template in JS to avoid extra waterfall for LCP blocks const HTML_TEMPLATE = ` +
@@ -76,6 +78,12 @@ export default async function decorate(block) { assignSlot(block, 'heading', 'h1'); assignSlot(block, 'image', 'picture'); + if (getMetadata('hlx:long-form-path').includes('/the-loop/')) { + await createAndInsertTrendingBannerBlock(block, 'loop-trending-banner'); + } else { + template.querySelector('slot[name="loop-trending-banner"]').remove(); + } + const picture = block.querySelector('picture'); // Picture is optional if (picture) { diff --git a/blocks/embed/embed.css b/blocks/embed/embed.css index 2aaf7d4..ae50598 100644 --- a/blocks/embed/embed.css +++ b/blocks/embed/embed.css @@ -6,6 +6,14 @@ main .embed { position: relative; } +main .embed.block:has(iframe) { + max-width: 100%; +} + +main .embed-wrapper .embed.block { + padding: 0 !important; +} + main .embed > div { display: flex; justify-content: center; @@ -75,14 +83,19 @@ main .embed .embed-placeholder-play button::before { left: 7px; } -main .embed.block:has(div > iframe, iframe) { - max-width: 100%; +main article.article-content .embed.block:has(iframe) { + max-width: 800px; } main article.article-content .embed.block:has(div > iframe, iframe) { max-width: 800px; } +main .open-article.block article.article-content .embed.block:has(iframe) { + max-width: none; + margin: 0; +} + main .embed.block[data-embed-link^="https://view.ceros.com/golf-digest/"] { max-width: var(--layout-width); } @@ -95,3 +108,8 @@ main .embed.block[data-embed-link^="https://view.ceros.com/golf-digest/"] .embed main .embed.block iframe[src^="https://view.ceros.com/golf-digest/"] { padding: 0 15px; } + +main .long-form-wrapper .long-form.block .embed.block[data-embed-link^="https://view.ceros.com/golf-digest/"] .embed-placeholder picture, +main .long-form-wrapper .long-form.block .embed.block iframe[src^="https://view.ceros.com/golf-digest/"] { + padding: 0; +} diff --git a/blocks/header/header.js b/blocks/header/header.js index f58069f..04bb878 100644 --- a/blocks/header/header.js +++ b/blocks/header/header.js @@ -1,3 +1,4 @@ +import { getMetadata } from '../../scripts/lib-franklin.js'; import { createTag } from '../../scripts/scripts.js'; import leaderboard from './leaderboard.js'; @@ -721,7 +722,7 @@ function getChannelPathPart(url) { function isActiveMenuURL(url) { const channelPath = getChannelPathPart(url); - return (window.location.pathname.lastIndexOf(channelPath) > -1); + return (getMetadata('hlx:long-form-path').lastIndexOf(channelPath) > -1); } let activeItem = null; diff --git a/blocks/long-form/long-form.css b/blocks/long-form/long-form.css index fb10888..bea4679 100644 --- a/blocks/long-form/long-form.css +++ b/blocks/long-form/long-form.css @@ -1,3 +1,8 @@ +.long-form-wrapper .long-form.block .center-seperator { + width: max-content; + margin: auto; +} + .long-form-wrapper .long-form.block .container { margin: 0 auto; @@ -117,19 +122,6 @@ margin: 20px 0; } -.long-form-wrapper .long-form.block .article-body > div > div > div > * { - display: block; - line-height: 30px; - margin: 0 auto 20px; - padding: 0 20px; - max-width: var(--article-width); -} - -.long-form-wrapper .long-form.block .article-body > div > div > div > div:has(iframe:not([src*="players.brightcove.net"])) { - max-width: none; - padding: 0; -} - .long-form-wrapper .long-form.block .article-body h2 { font-family: var(--font-tungsten); font-size: 37px; @@ -144,6 +136,29 @@ text-align: center; } +.long-form-wrapper .long-form.block .article-body div > h2, +.long-form-wrapper .long-form.block .article-body div > h3, +.long-form-wrapper .long-form.block .article-body div > h4, +.long-form-wrapper .long-form.block .article-body div > h5, +.long-form-wrapper .long-form.block .article-body div > h6, +.long-form-wrapper .long-form.block .article-body div > b, +.long-form-wrapper .long-form.block .article-body div > i, +.long-form-wrapper .long-form.block .article-body div > em, +.long-form-wrapper .long-form.block .article-body div > blockquote, +.long-form-wrapper .long-form.block .article-body div > strong, +.long-form-wrapper .long-form.block .article-body div > p { + display: block; + line-height: 30px; + margin: 0 auto 20px; + padding: 0 20px; + max-width: var(--article-width); +} + +.long-form-wrapper .long-form.block .article-body > div > div > div > div:has(iframe:not([src*="players.brightcove.net"])) { + max-width: none; + padding: 0; +} + .long-form-wrapper .long-form.block .article-body div > h2 { margin-top: 0; margin-bottom: 20px; @@ -151,7 +166,17 @@ } @media (min-width: 1025px) { - .long-form-wrapper .long-form.block .article-body > div > div > div > * { + .long-form-wrapper .long-form.block .article-body div > h2, + .long-form-wrapper .long-form.block .article-body div > h3, + .long-form-wrapper .long-form.block .article-body div > h4, + .long-form-wrapper .long-form.block .article-body div > h5, + .long-form-wrapper .long-form.block .article-body div > h6, + .long-form-wrapper .long-form.block .article-body div > b, + .long-form-wrapper .long-form.block .article-body div > i, + .long-form-wrapper .long-form.block .article-body div > em, + .long-form-wrapper .long-form.block .article-body div > blockquote, + .long-form-wrapper .long-form.block .article-body div > strong, + .long-form-wrapper .long-form.block .article-body div > p { padding: 0 15px 0 35px; margin-bottom: 60px; } diff --git a/blocks/long-form/long-form.js b/blocks/long-form/long-form.js index 3863134..bbf0b15 100644 --- a/blocks/long-form/long-form.js +++ b/blocks/long-form/long-form.js @@ -112,6 +112,12 @@ export default async function decorate(block) { replaceLinksWithEmbed(block); + block.querySelectorAll('p').forEach((p) => { + if (p.textContent.includes('• • •')) { + p.classList.add('center-seperator'); + } + }); + // Render template render(template, block, ARTICLE_TEMPLATES.LongForm); diff --git a/blocks/loop/loop.css b/blocks/loop/loop.css index 870a0aa..1eefe5f 100644 --- a/blocks/loop/loop.css +++ b/blocks/loop/loop.css @@ -17,121 +17,6 @@ } } -/* -* -* Trending Styling -* -*/ - -.loop-container .loop-wrapper .loop.block .trending-wrapper { - width: 100%; - display: flex; - position: relative; - overflow-x: auto; -} - -.loop-container .loop-wrapper .loop.block .trending-wrapper .trending-heading { - position: absolute; - top: 0; - left: 0; - margin: 10px; - padding: 9px 15px; - width: 132px; - height: 28px; - z-index: 1; - background-color: #e8b94d; - display: flex; - justify-content: space-between; - align-items: center; -} - -.loop-container .loop-wrapper .loop.block .trending-wrapper .trending-heading span { - font-size: 10px; - letter-spacing: 1px; - font-family: var(--font-gotham); - text-transform: uppercase; - font-weight: 500; -} - -.loop-container .loop-wrapper .loop.block .trending-wrapper .trending-content { - list-style: none; - display: flex; - gap: 2px; - padding: 0; - margin: 0 auto; - position: relative; - background-color: white; -} - -.loop-container .loop-wrapper .loop.block .trending-wrapper .trending-content .trending-item { - width: 220px; - height: 220px; -} - -.loop-container .loop-wrapper .loop.block .trending-wrapper .trending-content .trending-item .trending-link { - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - justify-content: flex-end; - cursor: pointer; - position: relative; - overflow: hidden; -} - -.loop-container .loop-wrapper .loop.block .trending-wrapper .trending-content .trending-text-wrapper { - width: 100%; - padding: 15px; -} - -.loop-container .loop-wrapper .loop.block .trending-wrapper .trending-content .trending-text-wrapper .trending-title { - margin: 0; - font-weight: 400; - color: #fff; - font-size: 14px; - font-family: var(--font-gotham); - line-height: 130%; - position: relative; -} - -.loop-container .loop-wrapper .loop.block .trending-wrapper .trending-content .trending-image-wrapper { - width: 100%; - height: 100%; - top: 0; - left: 0; - display: flex; - position: absolute; - background: linear-gradient(180deg, transparent 30%, #000); -} - -.loop-container .loop-wrapper .loop.block .trending-wrapper .trending-content .trending-image-wrapper picture { - width: 100%; - height: 100%; -} - -.loop-container .loop-wrapper .loop.block .trending-wrapper .trending-content .trending-image-wrapper picture img { - width: 100%; - height: 100%; - object-fit: cover; -} - -@media (max-width: 768px) { - .loop-container .loop-wrapper .loop.block .trending-wrapper .trending-content .trending-item { - width: 180px; - height: 180px; - } - - .loop-container .loop-wrapper .loop.block .trending-wrapper .trending-heading { - width: 93px; - height: 22px; - padding: 7px 12px; - } - - .loop-container .loop-wrapper .loop.block .trending-wrapper .trending-heading span { - font-size: 8px; - } -} - /* * * Header Styling @@ -475,4 +360,4 @@ width: 100%; max-width: 100%; } -} +} \ No newline at end of file diff --git a/blocks/loop/loop.js b/blocks/loop/loop.js index 3f6f6c3..c393955 100644 --- a/blocks/loop/loop.js +++ b/blocks/loop/loop.js @@ -4,10 +4,10 @@ import { removeEmptyElements, render, getBlockId, + createAndInsertTrendingBannerBlock, } from '../../scripts/scripts.js'; import { facebookSvg, twitterSvg, linkedInSvg } from '../social-share/social-share.js'; -const trendingSvg = ''; let numberOfEagerCards = 3; if (window.innerWidth < 1024) { numberOfEagerCards = 2; @@ -36,9 +36,9 @@ const placeholderLoopCardHtml = ({ ]).outerHTML : ''}
-
+ ${rubric ? `
${rubric} -
+
` : ''}

${title}

@@ -49,44 +49,11 @@ const placeholderLoopCardHtml = ({ `; }; -const placeholderTrendingItemHtml = ({ - image = '', imageAlt = 'alt-text', title = '', path = '#', -} = {}) => ` - -`; - const encodedUrl = encodeURIComponent(window.location.href); const placeholderHtml = (data) => ` -
- -
+
+

This is the Loop

@@ -107,27 +74,31 @@ const placeholderHtml = (data) => `
${!data ? placeholderLoopCardHtml().repeat(30) : data.map((loopItem, index) => placeholderLoopCardHtml(loopItem, index)).join('')}
+
`; export default async function decorate(block) { const id = getBlockId(block); - let loopData; + await createAndInsertTrendingBannerBlock(block, 'trending'); // using placeholder html - if (!loopData) { - block.innerHTML = placeholderHtml(); - } + const placeholderTemplate = parseFragment(placeholderHtml()); + + render(placeholderTemplate, block); + block.innerHTML = ''; + block.append(placeholderTemplate); - // Rendering content upon fetch complete + // Re-rendering content upon fetch complete document.addEventListener(`query:${id}`, (event) => { - loopData = event.detail.data; + const loopData = event.detail.data; const HTML_TEMPLATE = placeholderHtml(loopData); // Template rendering const template = parseFragment(HTML_TEMPLATE); + // Render template render(template, block); diff --git a/blocks/more-cards/more-cards.css b/blocks/more-cards/more-cards.css index 43bfb3f..9145cbe 100644 --- a/blocks/more-cards/more-cards.css +++ b/blocks/more-cards/more-cards.css @@ -128,6 +128,10 @@ padding: 0 20px 20px; } +.more-cards div a:not(:has(span)) strong { + margin-top: 15px; +} + .more-cards:not(.multiple) strong { padding: 0 10px 10px; } diff --git a/blocks/trending-banner/trending-banner.css b/blocks/trending-banner/trending-banner.css new file mode 100644 index 0000000..1e8529e --- /dev/null +++ b/blocks/trending-banner/trending-banner.css @@ -0,0 +1,121 @@ +.trending-banner-wrapper .trending-banner.block .trending-wrapper { + width: 100%; + display: flex; + position: relative; + overflow-x: auto; +} + +.trending-banner-wrapper .trending-banner.block .trending-wrapper a{ + text-decoration: none; +} + +.trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-heading { + position: absolute; + top: 0; + left: 0; + margin: 10px; + padding: 9px 15px; + width: 132px; + height: 28px; + z-index: 1; + background-color: #e8b94d; + display: flex; + justify-content: space-between; + align-items: center; +} + +.trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-heading span { + font-size: 10px; + letter-spacing: 1px; + font-family: var(--font-gotham); + text-transform: uppercase; + font-weight: 500; +} + +.trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-content { + list-style: none; + display: flex; + gap: 2px; + padding: 0; + margin: 0 auto; + position: relative; + background-color: white; +} + +.trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-content .trending-item { + width: 220px; + height: 220px; +} + +.trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-content .trending-item .trending-link { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: flex-end; + cursor: pointer; + position: relative; + overflow: hidden; +} + +.trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-content .trending-text-wrapper { + width: 100%; + padding: 15px; +} + +.trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-content .trending-text-wrapper .trending-title { + margin: 0; + font-weight: 400; + color: #fff; + font-size: 14px; + font-family: var(--font-gotham); + line-height: 130%; + position: relative; +} + +.trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-content .trending-image-wrapper { + width: 100%; + height: 100%; + top: 0; + left: 0; + display: flex; + position: absolute; +} + +.trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-content .trending-image-wrapper picture { + width: 100%; + height: 100%; +} + +.trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-content .trending-image-wrapper picture img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-content .trending-image-wrapper:has(picture img)::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient(180deg, transparent 30%, #000); +} + +@media (max-width: 768px) { + .trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-content .trending-item { + width: 180px; + height: 180px; + } + + .trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-heading { + width: 93px; + height: 22px; + padding: 7px 12px; + } + + .trending-banner-wrapper .trending-banner.block .trending-wrapper .trending-heading span { + font-size: 8px; + } +} diff --git a/blocks/trending-banner/trending-banner.js b/blocks/trending-banner/trending-banner.js new file mode 100644 index 0000000..5ed2419 --- /dev/null +++ b/blocks/trending-banner/trending-banner.js @@ -0,0 +1,74 @@ +import { createOptimizedPicture } from '../../scripts/lib-franklin.js'; +import { + getBlockId, parseFragment, removeEmptyElements, render, +} from '../../scripts/scripts.js'; + +const trendingSvg = ''; + +const placeholderTrendingItemHtml = ({ + image = '', imageAlt = 'alt-text', title = '', path = '#', +} = {}) => ` + +`; + +const generateTemplate = (loopData) => ` + +
`; + +export default async function decorate(block) { + const id = getBlockId(block); + + block.innerHTML = generateTemplate(); + + document.addEventListener(`query:${id}`, (event) => { + const HTML_TEMPLATE = generateTemplate(event.detail.data); + + // block reference from function argument is no longer + // the node in the DOM, so we need to query it again. + const blockInDom = document.getElementById(id); + + // Rendering + const template = parseFragment(HTML_TEMPLATE); + + // Render template + render(template, block); + + // Post-processing + removeEmptyElements(template, 'p'); + + blockInDom.innerHTML = ''; + blockInDom.append(template); + }); + + // Trigger query + window.store.query(block); +} diff --git a/scripts/scripts.js b/scripts/scripts.js index bf376ee..32b21d0 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -11,7 +11,7 @@ import { waitForLCP, loadBlocks, loadCSS, - toCamelCase, getMetadata, toClassName, + toCamelCase, getMetadata, toClassName, decorateBlock, loadBlock, } from './lib-franklin.js'; export const ARTICLE_TEMPLATES = { @@ -30,6 +30,17 @@ const LCP_BLOCKS = [...Object.values(ARTICLE_TEMPLATES), 'hero']; // add your LC const range = document.createRange(); +// getting real path, and adjusting canonical link to use the vanity path +const canonicalLinkTag = document.head.querySelector('link[rel="canonical"]'); +if (canonicalLinkTag) { + const longPathMetadata = document.createElement('meta'); + longPathMetadata.setAttribute('property', 'hlx:long-form-path'); + longPathMetadata.content = canonicalLinkTag?.href; + document.head.appendChild(longPathMetadata); + window.canonicalLocation = canonicalLinkTag.href; + canonicalLinkTag.href = window.location.href; +} + export function replaceLinksWithEmbed(block) { const embeds = ['youtube', 'brightcove', 'instagram', 'ceros']; block.querySelectorAll(embeds.map((embed) => `a:only-child[href*="${embed}"]`).join(',')).forEach((embedLink) => { @@ -217,28 +228,43 @@ function buildTemplate(main) { // TODO remove once importer fixes more cards const checkForMoreCards = (el, elems) => { - if (el.tagName === 'P' && el.querySelector('picture') && el.querySelector('a') && el?.nextElementSibling?.tagName === 'P' && el.nextElementSibling.children[0]?.tagName === 'A' && el.nextElementSibling?.nextElementSibling.tagName === 'P' && el.nextElementSibling.nextElementSibling.children[0]?.tagName === 'A') { + if (el.tagName === 'P' && el.querySelector('picture') && el.querySelector('a')) { + const hasRubric = el.nextElementSibling.children[0]?.tagName === 'A'; + const hasDesc = el.nextElementSibling?.nextElementSibling?.children[0]?.tagName === 'A'; + const rubric = document.createElement('span'); - rubric.textContent = el.nextElementSibling.textContent.trim(); + rubric.textContent = (hasRubric && hasDesc) ? el.nextElementSibling.textContent.trim() : ''; const desc = document.createElement('strong'); - desc.textContent = el.nextElementSibling.nextElementSibling.textContent.trim(); + desc.textContent = ''; + if (hasRubric && hasDesc) { + desc.textContent = el.nextElementSibling.nextElementSibling.textContent.trim(); + } else if (hasRubric) { + desc.textContent = el.nextElementSibling.textContent.trim(); + } const link = document.createElement('a'); link.setAttribute('href', new URL(el.querySelector('a').getAttribute('href')).pathname); link.append(el.querySelector('picture')); - link.append(rubric); - link.append(desc); + if (rubric.textContent) { link.append(rubric); } + if (desc.textContent) { link.append(desc); } - el.nextElementSibling.nextElementSibling.classList.add('remove'); - el.nextElementSibling.classList.add('remove'); + if (hasRubric && hasDesc) { el.nextElementSibling.nextElementSibling.classList.add('remove'); } + if (hasRubric || hasDesc) { el.nextElementSibling.classList.add('remove'); } el.classList.add('remove'); elems.push(link); - if (el.nextElementSibling.nextElementSibling.nextElementSibling) { - checkForMoreCards(el.nextElementSibling.nextElementSibling.nextElementSibling, elems); + let checkAfterSibling = el.nextElementSibling; + if (hasRubric && hasDesc) { + checkAfterSibling = el.nextElementSibling.nextElementSibling.nextElementSibling; + } else if (hasRubric || hasDesc) { + checkAfterSibling = el.nextElementSibling.nextElementSibling; + } + + if (checkAfterSibling) { + checkForMoreCards(checkAfterSibling, elems); } } }; @@ -580,6 +606,7 @@ window.store = new (class { }, carousel: () => 20, loop: () => 30, + 'trending-banner': () => 6, 'series-cards': () => 100, 'tiger-cards': () => 35, 'tiger-vault-hero': () => 1, @@ -589,7 +616,7 @@ window.store = new (class { this.blockNames = Object.keys(this._blockQueryLimit); this.spreadsheets = Object.keys(this._spreadsheets); - this.initQueries(); + // this.initQueries(); this._cache = {}; @@ -665,6 +692,7 @@ window.store = new (class { */ query(block) { const id = getBlockId(block); + // this.initQueries(); let query = this.getQuery(block); if (!query) { @@ -884,3 +912,22 @@ export const generateArticleBlocker = (block, selector) => { articleBody.appendChild(articleBlocker); }; + +/** + * Generates a Block for trending loop articles, assigns the slot article and appends the block. + * + * This function must be awaited! + * + * @param {block} Block that should contain the new trending-banner block. + * @param {slotName} Slot name that should be assigned to the new trending-banner block. + */ +export const createAndInsertTrendingBannerBlock = async (block, slotName) => { + // TODO use trending query instead of loop articles + const trendingBannerBlock = buildBlock('trending-banner', [[]]); + trendingBannerBlock.classList.add('loop-article'); + trendingBannerBlock.setAttribute('slot', slotName); + block.append(trendingBannerBlock); + decorateBlock(trendingBannerBlock); + await loadBlock(trendingBannerBlock); + return trendingBannerBlock; +};