1import { 2 buildBlock, 3 loadHeader, 4 loadFooter, 5 decorateButtons, 6 decorateIcons, 7 decorateSections, 8 decorateBlocks, 9 decorateBlock, 10 decorateTemplateAndTheme, 11 waitForFirstImage, 12 loadSection, 13 loadSections, 14 loadCSS, 15} from './aem.js'; 16 17import { 18 decorateLinkedPictures, 19 decorateExternalLinks, 20} from './shared.js'; 21 22/** 23 * Get metadata value based on the key 24 * @param {string} key The key to get the metadata value for 25 * @returns {string} The metadata value 26 */ 27function getMetadata(key) { 28 const metaElement = document.querySelector(`meta[name="${key}"]`); 29 if (metaElement) { 30 return metaElement.getAttribute('content'); 31 } 32 return ''; 33} 34 35/** 36 * Builds hero block and prepends to main in a new section. 37 * @param {Element} main The container element 38 */ 39function buildHeroBlock(main) { 40 const template = getMetadata('template'); 41 if ((template === 'Homepage') || (template === 'Articles') || (template === 'Resources') || (template === 'category') || (template === 'search-results')) { 42 const h1 = main.querySelector('h1'); 43 const h2 = main.querySelector('h2'); 44 const picture = main.querySelector('picture'); 45 // eslint-disable-next-line no-bitwise 46 if (h1 && picture && (h1.compareDocumentPosition(picture) & Node.DOCUMENT_POSITION_PRECEDING)) { 47 const section = document.createElement('div'); 48 section.append(buildBlock('hero', { elems: [picture, h1, h2] })); 49 main.prepend(section); 50 // Remove the now-empty section that contained the hero content 51 const nextSection = main.children[1]; 52 if (nextSection && !nextSection.textContent.trim()) { 53 nextSection.remove(); 54 } 55 } 56 } 57 if (template === 'Article') { 58 /* Hero block for Article */ 59 /* built in CSS */ 60 } 61 if (template === 'Resource') { 62 /* Hero block for Resource */ 63 /* built in CSS */ 64 } 65} 66 67/** 68 * Fix the h2 in the hero block 69 * by adding a break in it's content 70 * Disabled for now 71 * 72function fixh2hero() { 73 try { 74 // Get the element by ID 75 const element = document.getElementById('id'); 76 // Check if the element exists 77 if (!element) { 78 return; 79 } 80 // Replace the content safely 81 element.innerHTML = 'Partner<br>Resources'; 82 } catch (error) { 83 // eslint-disable-next-line no-console 84 console.error('Error replacing content:', error); 85 } 86} 87*/ 88 89function addSocialShare(target) { 90 const targetElement = document.getElementsByClassName(target)[0]; 91 const socialShare = buildBlock('sharethis-inline-share-buttons', { elems: [] }); 92 targetElement.parentElement.after(socialShare, targetElement.nextSibling); 93 decorateBlock(socialShare); 94} 95 96function buildArticlePropsBlock() { 97 const template = getMetadata('template'); 98 if (template === 'Article') { 99 addSocialShare('blade2-picture'); 100 /* 101 const hook = main.querySelector('picture'); 102 if (hook) { 103 hook.parentElement.classList.add('article-share-container'); 104 const socialShareBlock = buildBlock('social-share', { elems: [] }); 105 hook.parentElement.insertBefore(socialShareBlock, hook.parentElement.firstChild); 106 decorateBlock(socialShareBlock); 107 console.log('Article share block added'+hook.parentElement.firstChild); 108 } 109 */ 110 } 111 if (template === 'Resource') { 112 addSocialShare('blade2-picture'); 113 /* 114 const hook = main.querySelector('picture'); 115 if (hook) { 116 hook.parentElement.classList.add('article-share-container'); 117 const socialShareBlock = buildBlock('social-share', { elems: [] }); 118 hook.parentElement.insertBefore(socialShareBlock, hook.parentElement.firstChild); 119 decorateBlock(socialShareBlock); 120 console.log('Resource share block added'); 121 } 122 */ 123 } 124} 125/** 126 * load fonts.css and set a session storage flag 127 */ 128async function loadFonts() { 129 await loadCSS(`${window.hlx.codeBasePath}/styles/fonts.css`); 130 try { 131 if (!window.location.hostname.includes('localhost')) sessionStorage.setItem('fonts-loaded', 'true'); 132 } catch (e) { 133 // do nothing 134 } 135} 136 137// Prev/Next buttons functionality (prev) 138function leftScroll(value) { 139 const scrollElements = document.querySelectorAll(`div.${value} ul`);
140 scrollElements.forEach((div) => { 141 if (value === 's1') { 142 div.scrollBy({ 143 top: 0, 144 left: -300, 145 behavior: 'smooth', 146 }); 147 } 148 if (value === 's2') { 149 div.scrollBy({ 150 top: 0, 151 left: -400, 152 behavior: 'smooth', 153 }); 154 } 155 if (value === 's3') { 156 div.scrollBy({ 157 top: 0, 158 left: -300, 159 behavior: 'smooth', 160 }); 161 } 162 if (value === 's4') { 163 div.scrollBy({ 164 top: 0, 165 left: -375, 166 behavior: 'smooth', 167 }); 168 } 169 if (value === 's5') { 170 div.scrollBy({ 171 top: 0, 172 left: -600, 173 behavior: 'smooth', 174 }); 175 } 176 }); 177} 178window.leftScroll = leftScroll; 179 180// Prev/Next buttons functionality (next) 181function rightScroll(value) { 182 const scrollElements = document.querySelectorAll(`div.${value} ul`); 183 scrollElements.forEach((div) => { 184 if (value === 's1') { 185 div.scrollBy({ 186 top: 0, 187 left: 300, 188 behavior: 'smooth', 189 }); 190 } 191 if (value === 's2') { 192 div.scrollBy({ 193 top: 0, 194 left: 400, 195 behavior: 'smooth', 196 }); 197 } 198 if (value === 's3') { 199 div.scrollBy({ 200 top: 0, 201 left: 300, 202 behavior: 'smooth', 203 }); 204 } 205 if (value === 's4') { 206 div.scrollBy({ 207 top: 0, 208 left: 375, 209 behavior: 'smooth', 210 }); 211 } 212 if (value === 's5') { 213 div.scrollBy({ 214 top: 0, 215 left: 600, 216 behavior: 'smooth', 217 }); 218 } 219 }); 220} 221window.rightScroll = rightScroll; 222 223/** 224 * Builds all synthetic blocks in a container element. 225 * @param {Element} main The container element 226 */ 227function buildAutoBlocks(main) { 228 try { 229 buildHeroBlock(main); 230 } catch (error) { 231 // eslint-disable-next-line no-console 232 console.error('Auto Blocking failed', error); 233 } 234} 235 236/** 237 * Decorates the main element. 238 * @param {Element} main The main element 239 */ 240// eslint-disable-next-line import/prefer-default-export 241export function decorateMain(main) { 242 // hopefully forward compatible button decoration 243 decorateLinkedPictures(main); 244 decorateButtons(main); 245 decorateExternalLinks(main); 246 decorateIcons(main); 247 buildAutoBlocks(main); 248 decorateSections(main); 249 decorateBlocks(main); 250} 251 252/** 253 * Loads everything needed to get to LCP. 254 * @param {Element} doc The container element 255 */ 256async function loadEager(doc) { 257 document.documentElement.lang = 'en'; 258 decorateTemplateAndTheme(); 259 const main = doc.querySelector('main'); 260 if (main) { 261 decorateMain(main); 262 document.body.classList.add('appear'); 263 await loadSection(main.querySelector('.section'), waitForFirstImage); 264 } 265 266 try { 267 /* if desktop (proxy for fast connection) or fonts already loaded, load fonts.css */ 268 if (window.innerWidth >= 900 || sessionStorage.getItem('fonts-loaded')) { 269 loadFonts(); 270 } 271 } catch (e) { 272 // do nothing 273 } 274} 275 276/** 277 * Loads everything that doesn't need to be delayed. 278 * @param {Element} doc The container element 279 */ 280async function loadLazy(doc) { 281 const main = doc.querySelector('main'); 282 await loadSections(main); 283 284 const { hash } = window.location; 285 const element = hash ? doc.getElementById(hash.substring(1)) : false; 286 if (hash && element) element.scrollIntoView(); 287 288 loadHeader(doc.querySelector('header')); 289 loadFooter(doc.querySelector('footer')); 290 291 loadCSS(`${window.hlx.codeBasePath}/styles/lazy-styles.css`); 292 loadFonts(); 293 buildArticlePropsBlock(main); 294} 295 296/** 297 * Loads everything that happens a lot later, 298 * without impacting the user experience. 299 */ 300function loadDelayed() { 301 // eslint-disable-next-line import/no-cycle 302 window.setTimeout(() => import('./delayed.js'), 3000); 303 // load anything that can be postponed to the latest here 304} 305 306async function loadPage() { 307 await loadEager(document); 308 await loadLazy(document); 309 loadDelayed(); 310} 311 312loadPage();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.