Untitled
unknown
plain_text
21 days ago
14 kB
2
Indexable
import { a, span, div, input, ul, li, } from '../../scripts/dom-builder.js'; import Tag from '../../libs/tag/tag.js'; import Avatar from '../../libs/avatar/avatar.js'; import Button from '../../libs/button/button.js'; import Hero from '../../libs/hero/hero.js'; import { fetchTagList, getContentType, getMetadataOverride, getPageTags, getTagLink, } from '../../scripts/utils/tags-utils.js'; import { formatDate, toTitleCase } from '../../scripts/utils/text-utils.js'; import { fetchAuthors, getAuthorMetadata, lookupProfiles } from '../../scripts/utils/author-utils.js'; import { isArticle } from '../../scripts/utils/article-utils.js'; import highlight from '../../scripts/utils/fuse-search-utils.js'; import isNewsPage from '../../scripts/utils/news-utils.js'; import { getPublishedDate, isMachineTranslated } from '../../scripts/utils/metadata-utils.js'; import { moveInstrumentation } from '../../scripts/utils/editor-support-utils.js'; import { getMetadata, toCamelCase } from '../../scripts/utils/aem-utils.js'; import { fetchPlaceholders } from '../../scripts/utils/i18n-utils.js'; import { decorateIcons } from '../../scripts/aem.js'; function buildAuthorEl(author) { const renderLink = author.path && author.path.indexOf('/people/') === -1; if (renderLink) { return a({ class: 'hero__content__info__author', href: author.path }, author.name); } return span({ class: 'hero__content__info__author' }, author.name); } function buildMetaInfo(placeholders, authors = []) { const info = []; if (authors.length > 0) { const authorEl = span({ class: 'hero__content__info__authors' }); if (authors.length === 1) { const avatar = Avatar.fromAuthorEntry(authors[0]); if (avatar.getImage()) { info.push(avatar.render('small', true, false)); } authorEl.append(buildAuthorEl(authors[0])); } else { authors.forEach((author) => { if (author) { authorEl.append(buildAuthorEl(author)); } }); } info.push(authorEl); } if (isNewsPage() || !getMetadata('modified-date')) { const publishedDate = getPublishedDate(); if (publishedDate) { info.push( span({ class: 'hero__content__info__date' }, `${placeholders.publishedOn || 'Published on'} ${formatDate(publishedDate)}`), ); } } else if (getMetadata('modified-date')) { info.push( span({ class: 'hero__content__info__date' }, `${placeholders.updatedOn || 'Updated on'} ${formatDate(getMetadata('modified-date'))}`), ); } const readingTime = getMetadataOverride('twitter:data2'); if (readingTime) { info.push(span({ class: 'hero__content__info__read-time' }, readingTime)); } return info; } function replacePlaceholderText(elem, tags) { if (elem && (elem.innerText.includes('[page]') || elem.innerText.includes('[author]'))) { // find the first tag in tags which matches the path in topics-path or news-path let h1TitleTag; Object.keys(tags).forEach((tag) => { const tagData = tags[tag]; if ( tagData['topic-path'] === window.location.pathname || tagData['news-path'] === window.location.pathname ) { h1TitleTag = tagData; } }); elem.innerHTML = elem.innerHTML.replace('[page]', h1TitleTag?.label || ''); let author = getMetadata('author'); if (!author) { const path = window.location.pathname; if (path.includes('/author/')) { author = toTitleCase(path.split('/author/').pop()); } } elem.innerHTML = elem.innerHTML.replace('[author]', author || ''); } return elem; } function findFirstTag(tags) { if (getMetadata('primarytag')) { const tag = tags[toCamelCase(getMetadata('primarytag').split(',')[0].trim())]; return new Tag(tag.label, getTagLink(tag, document.location.pathname)); } const articleTags = getPageTags(); const tagsLiEL = articleTags.filter((articleTag) => { const tag = tags[toCamelCase(articleTag)]; return tag && !tag.key.startsWith('contenthub:content-type/') && (tag['topic-path'] || tag['news-path']); }) .map((articleTag) => { const tag = tags[toCamelCase(articleTag)]; return new Tag(tag.label, getTagLink(tag, document.location.pathname)); }); return tagsLiEL[0]; } function getEyebrowContent(eyebrow, tags, isAnArticle) { let eyebrowText = eyebrow?.textContent; const contentTypeTag = tags[toCamelCase(getContentType())]; if (!eyebrowText && isAnArticle) { // if no eyebrow text is set, use the content type for articles eyebrowText = contentTypeTag?.label || getContentType()?.split('/')[1].replace('-', ' '); } let newEyebrow = ''; if (eyebrow?.firstElementChild?.tagName === 'A') { // If author has added a custom link, add appropriate classes for styling newEyebrow = eyebrow.firstElementChild; } else if (eyebrowText && isAnArticle) { // If article, add link to parent topics page, and appropriate classes for styling const eyeBrowHref = (() => { if (contentTypeTag && contentTypeTag['topic-path'] && contentTypeTag['topic-path'] !== '0') return contentTypeTag['topic-path']; if (contentTypeTag && contentTypeTag['news-path'] && contentTypeTag['news-path'] !== '0') return contentTypeTag['news-path']; return null; })(); newEyebrow = eyeBrowHref ? a({ href: eyeBrowHref }, eyebrowText) : eyebrowText; } else if (eyebrowText) { // Else display simple span or nothing newEyebrow = eyebrowText; } return newEyebrow; } function dispatchSearchEvent(searchValue) { const searchEvent = new CustomEvent('searchEvent', { detail: { searchValue } }); document.dispatchEvent(searchEvent); } function getMatchIndicesLength(match) { return match.indices.reduce((sum, [start, end]) => sum + (end - start + 1), 0); } function getBestMatch(matches) { if (!matches || matches.length === 0) return ''; let bestMatch = matches[0]; let bestMatchLength = getMatchIndicesLength(bestMatch); matches.slice(1).forEach((currentMatch) => { const currentMatchLength = getMatchIndicesLength(currentMatch); if (currentMatchLength > bestMatchLength) { bestMatch = currentMatch; bestMatchLength = currentMatchLength; } }); return bestMatch; } function hideAutocompleteList(autocompleteList) { autocompleteList.classList.remove('hero__content__autocomplete-list-visible'); autocompleteList.innerHTML = ''; } function updateAutocomplete( // eslint-disable-line no-unused-vars autocompleteList, searchInput, results, ) { if (!results.length) { autocompleteList.classList.remove('hero__content__autocomplete-list-visible'); return; } autocompleteList.classList.add('hero__content__autocomplete-list-visible'); autocompleteList.innerHTML = ''; const listTitle = span({ class: 'hero__content__autocomplete-title' }); listTitle.textContent = 'suggested searches'; autocompleteList.append(listTitle); results.forEach((matchResult) => { const listItem = li({ class: 'hero__content__autocomplete-item' }); const searchIcon = span({ class: 'icon icon-search' }); const bestMatch = getBestMatch(matchResult.matches); const itemText = matchResult.item[bestMatch.key]; const highlightedTextWrapper = span(); highlightedTextWrapper.innerHTML = highlight(itemText, bestMatch); listItem.append(searchIcon, highlightedTextWrapper); listItem.addEventListener('click', () => { searchInput.value = itemText; dispatchSearchEvent(itemText); hideAutocompleteList(autocompleteList); }); autocompleteList.appendChild(listItem); }); } function removeHeroElementsForSearchMode(heroEl) { heroEl.querySelector('.hero__content__eyebrow')?.remove(); heroEl.querySelector('.hero__additional-content')?.remove(); heroEl.querySelector('.hero__content__info')?.remove(); } function addSearchInput({ hero, contentContainer }) { removeHeroElementsForSearchMode(hero); const searchInputPlaceholder = contentContainer.querySelector('h6')?.previousElementSibling; const searchInputContainer = div({ class: 'hero__content__input-container', role: 'search' }); const searchAutocompleteList = ul({ class: 'hero__content__autocomplete-list' }); const searchInput = input( { class: 'hero__content__input', placeholder: searchInputPlaceholder?.textContent || 'Search for your SAP product here', }, ); searchInput.addEventListener('input', () => { const searchValue = searchInput.value; if (searchValue.length >= 1) { searchInput.classList.add('has-text'); } else { searchInput.classList.remove('has-text'); } dispatchSearchEvent(searchValue); }); searchInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') { dispatchSearchEvent(searchInput.value); } }); // TODO: uncomment, please, for autocomplete functionality // document.addEventListener('searchResults', (e) => { // const { results } = e.detail; // updateAutocomplete(searchAutocompleteList, searchInput, results); // decorateIcons(searchAutocompleteList); // }); document.addEventListener('click', (event) => { if (!searchInput.contains(event.target) && !searchAutocompleteList.contains(event.target)) { hideAutocompleteList(searchAutocompleteList); } }); const heroContentEl = hero.querySelector('.hero__content'); const searchIcon = span({ class: 'icon icon-search', 'aria-hidden': true }); const clearIcon = span({ class: 'icon icon-close' }); clearIcon.addEventListener('click', () => { searchInput.value = ''; searchInput.classList.remove('has-text'); dispatchSearchEvent(''); hideAutocompleteList(searchAutocompleteList); }); searchIcon.addEventListener('click', () => { dispatchSearchEvent(searchInput.value); }); searchInputContainer.append(searchInput, clearIcon, searchIcon, searchAutocompleteList); heroContentEl.append(searchInputContainer); decorateIcons(heroContentEl); } /** * loads and decorates the hero * @param {Element} block The hero block element */ export default async function decorate(block) { const isAnArticle = isArticle(); const isMediaBlend = isAnArticle || block.classList.contains('media-blend'); const tags = await fetchTagList(); let videoHref = null; const backgroundImageContainer = block.children[0]; const contentContainer = block.children[1]; // extract block content const heading = contentContainer.querySelector('h1'); const eyebrow = contentContainer.querySelector('h6'); const hasFullBackgroundImage = block.classList.contains('full-background-image'); const hasSearchMode = block.classList.contains('search'); const backgroundImage = backgroundImageContainer.querySelector('picture'); const additionalContentImage = contentContainer.querySelector('picture'); if (isMediaBlend) { const link = contentContainer.querySelector('p:has(~ h1) a'); videoHref = link?.href; link?.remove(); } if (backgroundImage) { if (hasFullBackgroundImage) { backgroundImage.querySelectorAll('source[type="image/webp"]').forEach((source) => { source.srcset = source.srcset.replaceAll('format=webply', 'format=webpll'); }); backgroundImage.classList.add('full-background-image', 'hero__background-image'); block.parentElement.append(backgroundImage); } } const placeholders = await fetchPlaceholders(); // Add primary tag or news placeholder const tagEls = []; if (isNewsPage() && isAnArticle) { tagEls.push(new Tag(placeholders[toCamelCase('SAP News Center')], '/news').render()); } else { const firstTag = findFirstTag(tags); if (firstTag) { tagEls.push(firstTag.render()); } } const buttons = [...contentContainer.querySelectorAll('h1 ~ p.button-container a')].map((anchor) => { const type = anchor.parentElement.nodeName === 'EM' ? 'secondary' : 'primary'; return new Button(anchor.textContent, null, type, { xs: 'medium', l: 'large', }, anchor.href).render(); }); const description = contentContainer.querySelectorAll('p:not(.button-container, :has(~ h1))'); const searchHeroProps = { heading: replacePlaceholderText(heading, tags), eyebrow: getEyebrowContent(eyebrow, tags, isAnArticle), description, additionalContent: { additionalContentImage, additionalContentVideoHref: videoHref, }, metadata: isMediaBlend ? buildMetaInfo(placeholders) : [], buttons, tags: tagEls, isMachineTranslated: isMachineTranslated(), placeholders, }; const heroProps = hasSearchMode ? searchHeroProps : { ...searchHeroProps, backgroundImage: hasFullBackgroundImage ? null : backgroundImage, }; const hero = new Hero(heroProps); if (isMediaBlend) { fetchAuthors().then((authorIndex) => { hero.setMetadata(buildMetaInfo( placeholders, lookupProfiles(getAuthorMetadata(), authorIndex), )); }); } const heroEl = hero.render(); if (hasSearchMode) { addSearchInput({ hero: heroEl, contentContainer }); } heroEl.classList.add(...block.classList); moveInstrumentation(block, heroEl); block.replaceWith(heroEl); }
Editor is loading...
Leave a Comment