Untitled
unknown
plain_text
7 months ago
14 kB
4
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