diff --git a/.eslintignore b/.eslintignore index f391acf72..d35e27f51 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,7 @@ helix-importer-ui -tools/sitemap -solutions/plugins/experimentation -solutions/vendor +_src/scripts/lib-franklin-api.js +_src/scripts/vendor +_src/scripts/zuora.js +_src/vendor +_src/plugins +tools diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..3f4db9dbb --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# @global-owner1 and @global-owner2 will be requested for +# review when someone opens a pull request. +* @enake diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index bd93f8e30..5dc84d4e3 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -3,5 +3,5 @@ Please always provide the [GitHub issue(s)](../issues) your PR is for, as well a Fix # Test URLs: -- Before: https://main--bitdefender--hlxsites.hlx.page/solutions/ -- After: https://--bitdefender--hlxsites.hlx.page/solutions/ \ No newline at end of file +- Before: https://main--www-websites--bitdefender.hlx.page/zh-hk/ +- After: https://--www-websites--bitdefender.hlx.page/zh-hk/ diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index 0b534167e..24ae18ff2 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -16,20 +16,20 @@ jobs: - name: Use node.js uses: actions/setup-node@v3 with: - node-version: '16' #required for npm 8 or later. + node-version: '20' #required for npm 8 or later. - run: npm install - run: npm run lint env: CI: true - ghost_inspector_tests: - needs: linting - runs-on: ubuntu-latest - steps: - - name: execute Ghost Inspector test - uses: docker://ghostinspector/cli - with: - args: suite execute ${{ secrets.GI_SUITE }} \ - --apiKey ${{ secrets.GI_API_KEY }} \ - --branchName ${{ env.BRANCH_NAME }} \ - --errorOnFail \ - --errorOnScreenshotFail + # ghost_inspector_tests: + # needs: linting + # runs-on: ubuntu-latest + # steps: + # - name: execute Ghost Inspector test + # uses: docker://ghostinspector/cli + # with: + # args: suite execute ${{ secrets.GI_SUITE }} \ + # --apiKey ${{ secrets.GI_API_KEY }} \ + # --branchName ${{ env.BRANCH_NAME }} \ + # --errorOnFail \ + # --errorOnScreenshotFail diff --git a/404.html b/404.html index 165f8c43b..b5e695b7f 100644 --- a/404.html +++ b/404.html @@ -9,12 +9,15 @@ - + - + + - + @@ -146,7 +149,7 @@

Page Not Found

The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.

+
diff --git a/solutions/blocks/accordion/accordion.css b/_src/blocks/accordion/accordion.css similarity index 100% rename from solutions/blocks/accordion/accordion.css rename to _src/blocks/accordion/accordion.css diff --git a/solutions/blocks/accordion/accordion.js b/_src/blocks/accordion/accordion.js similarity index 100% rename from solutions/blocks/accordion/accordion.js rename to _src/blocks/accordion/accordion.js diff --git a/solutions/blocks/awards-search/awards-search.css b/_src/blocks/awards-search/awards-search.css similarity index 98% rename from solutions/blocks/awards-search/awards-search.css rename to _src/blocks/awards-search/awards-search.css index d9fb85468..ec750ecad 100644 --- a/solutions/blocks/awards-search/awards-search.css +++ b/_src/blocks/awards-search/awards-search.css @@ -102,8 +102,8 @@ main .section .awards-search .awards-results-container .award-item-container h2 width: 1.5rem; height: 1.3125rem; /* stylelint-disable-next-line property-no-vendor-prefix */ - -webkit-mask: url('/solutions/icons/arrow-right.svg'); - mask: url('/solutions/icons/arrow-right.svg'); + -webkit-mask: url('/_src/icons/arrow-right.svg'); + mask: url('/_src/icons/arrow-right.svg'); background-color: var(--read-more-text-color); display: inline-block; opacity: 1; diff --git a/solutions/blocks/awards-search/awards-search.js b/_src/blocks/awards-search/awards-search.js similarity index 100% rename from solutions/blocks/awards-search/awards-search.js rename to _src/blocks/awards-search/awards-search.js diff --git a/_src/blocks/awards/awards.css b/_src/blocks/awards/awards.css new file mode 100644 index 000000000..9d0a150b5 --- /dev/null +++ b/_src/blocks/awards/awards.css @@ -0,0 +1,254 @@ +/* stylelint-disable no-descending-specificity */ +.awards-container { + display: flex; + justify-content: center; +} + +.awards-wrapper { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + max-width: 1300px; +} + +.awards-container .block.awards-component { + background-color: #edf9ff; + display: flex; + flex-direction: column; + align-items: center; + border-radius: 20px; +} + +.awards-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.awards-component { + display: flex; + justify-content: center; + align-items: center; + padding-top: 22px; + padding-bottom: 24px; + width: 100%; +} + +.awards-container h3 { + font-size: 32px; +} + +.awards-container h4 { + margin-bottom: 18px; + font-weight: normal; +} + +.awards-container .block.awards-component > div { + text-align: center; + display: flex; + align-items: center; + justify-content: center; +} + +.awards-component > div:nth-child(1) { + display: flex; + flex-direction: column; + align-items: center; + width: 85% !important; +} + +.awards-component > div:nth-child(2) { + display: flex; + flex-direction: column; + align-items: center; + width: 90%; +} + +.awards-component > div:nth-child(3) div { + display: flex; + flex-wrap: wrap; + justify-content: center; + width: 90%; + align-items: center; + gap: 4.5%; +} + + +.awards-component > div:nth-child(3) div img { + min-height: 56px; + height: auto; + max-width: 100%; + width: auto; + object-fit: contain; +} + +.awards-container .vsb picture{ + max-width: 90px; + min-width: 8%; +} + +.awards-container .vsb h3{ + margin-top: 0; + margin-bottom: 0; +} + +.awards-container .vsb p{ + margin-top: 0; + margin-bottom: 0; +} + +@media (min-width: 580px) { + .awards-component > div:nth-child(3) div { + max-width: 768px; + flex-wrap: nowrap; + } + + .vsb.awards-component > div:nth-child(3) div { + flex-wrap: wrap; + } +} + +@media (max-width: 768px) { + .awards-component > div:nth-child(3) div img { + min-height: auto; + margin: 5px 0; + } + + .awards-container h3 { + line-height: 38px; + } +} + +@media (min-width: 768px) { + .awards-component > div:nth-child(3) { + width: 95% !important; + } + + .awards-container .vsb picture{ + min-width: 100px; + } +} + +@media (min-width: 992px) { + .awards-component > div:nth-child(3) { + flex-wrap: nowrap; + justify-content: space-around; + width: 90%; + } + + .awards-wrapper .awards > div:nth-child(3) > div[data-valign="middle"] { + width: 100%; + display: flex; + justify-content: space-around; + align-items: center; + } + + .awards-component > div:nth-child(1) img { + width: 80px !important; + } + + .awards-component main .section.wide img { + height: auto; + object-fit: contain; + width: 70%; + } + + .awards-container .block.awards-component { + padding-bottom: 40px; + } + + .awards-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .awards-container .vsb picture{ + min-width: 75px; + } + + .vsb.awards-component > div:nth-child(3) div { + flex-wrap: nowrap; + } +} + +@media (min-width: 1200px) { + .awards-component { + display: flex; + justify-content: center; + align-items: center; + padding-top: 32px; + padding-bottom: 24px; + } + + .awards-container .block.awards-component { + padding-bottom: 50px; + } + + .awards-component div[data-align="center"][data-valign="middle"] img { + width: 80px; + } + + .awards-container .block.awards-component > div { + text-align: center; + display: flex; + align-items: center; + } + + .awards-component > div:nth-child(1) { + display: flex; + flex-direction: column; + align-items: center; + width: 55%; + } + + .awards-component > div:nth-child(2) { + display: flex; + flex-direction: column; + align-items: center; + width: 50% !important; + } + + .awards-component > div:nth-child(3) { + display: flex; + flex-direction: row; + justify-content: space-around; + width: 70%; + } + + .awards-component h3 { + font: normal normal bold 32px/38px Arial, sans-serif; + max-width: 726px; + margin-bottom: 0; + } + + .awards-component h4 { + font-size: 18px; + font-weight: normal; + line-height: 25px; + margin-bottom: 35px; + margin-top: 14px; + } + + .awards-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } + + .awards-container .vsb picture{ + min-width: 100px; +} +} + +@media (min-width: 1600px) { + .awards-containe.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/awards/awards.js b/_src/blocks/awards/awards.js new file mode 100644 index 000000000..58d8c2b72 --- /dev/null +++ b/_src/blocks/awards/awards.js @@ -0,0 +1,13 @@ +// eslint-disable-next-line no-unused-vars +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/banner-vsb/banner-vsb.css b/_src/blocks/banner-vsb/banner-vsb.css new file mode 100644 index 000000000..9150c61a2 --- /dev/null +++ b/_src/blocks/banner-vsb/banner-vsb.css @@ -0,0 +1,251 @@ +.banner-vsb-container, +.banner-vsb-container * { + box-sizing: border-box; +} + +.banner-vsb-container.section { + --gray-bg: rgb(246 246 246 / 100%); + --button-background-color: #eb0000; + --button-link-color: #fff; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --body-font-size-s: 16px; + --font-weight-bold: 500; + --button-hover-background-color: #d80000; + + padding: 0; +} + +/* imports from global */ +.banner-vsb-container a.button:any-link, input[type="submit"] { + font-family: var(--body-font-family); + font-size: var(--body-font-size-s); + font-style: normal; + font-weight: var(--font-weight-bold); + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: var(--button-link-color); + background-color: var(--button-background-color); + border: 2px solid var(--button-background-color); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.banner-vsb-container a.button:hover, +.banner-vsb-container a.button:focus, +.banner-vsb-container input[type="submit"]:hover, +.banner-vsb-container input[type="submit"]:focus { + background-color: var(--button-hover-background-color); + border: 2px solid var(--button-hover-background-color); + cursor: pointer; +} + +.banner-vsb-container a.button span.button-text { + transition: transform .2s cubic-bezier(.4,0,.2,1); + transform: translate(0, 0); +} + +.banner-vsb-container a.button:hover span.button-text { + transform: translate(-10px, 0); +} + +.banner-vsb-container a.button::after, +.banner-vsb-container input[type="submit"]::after, +.banner-vsb-container main .section.link-right a::after { + content: ''; + width: 24px; + height: 24px; + /* stylelint-disable-next-line property-no-vendor-prefix */ + -webkit-mask:url('/_src/icons/arrow-right.svg'); + mask: url('/_src/icons/arrow-right.svg'); + background-color: var(--button-link-color); + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + opacity: 0; + margin-left: -10px; +} + +.banner-vsb-container a.button:hover::after, +.banner-vsb-container input[type="submit"]:hover::after { + transform: translateX(5px); + opacity: 1; +} + +.banner-vsb-container .banner-vsb-wrapper .block { + display: flex; + flex-direction: column; +} + +.banner-vsb-container h1 { + font: normal normal bold 32px / 36px "IBM Plex Sans", sans-serif; + color: #006EFF; +} + +.banner-vsb-container h2, +.banner-vsb-container h3, +.banner-vsb-container h4 { + font: normal normal bold 20px/24px "IBM Plex Sans", sans-serif; +} + +.banner-vsb-container p, +.banner-vsb-container div { + font: normal normal normal 20px/16px "IBM Plex Sans", sans-serif; +} + +.banner-vsb-container .rte-wrapper { + position: relative; + z-index: 4; +} + +.banner-vsb-container .video-wrapper { + height: 300px; + position: relative; +} + +.banner-vsb-container .video-wrapper video { + width: 100%; + height: 100%; + object-fit: cover; +} + +.banner-vsb-container .video-wrapper::before { + content: ''; + position: absolute; + width: 100%; + height: 100%; + background: linear-gradient(to bottom, var(--gray-bg), rgb(246 246 246 / 0%)); + z-index: 1; +} + +.banner-vsb-container .default-content-wrapper { + padding-top: 20px !important; + z-index: 4; + order: -1; +} + +.banner-vsb-container a.button:any-link:not(.modal, .primary) { + border: solid white 2px !important; + width: 100%; + justify-content: center; +} + +.banner-vsb-container.we-container { + margin: 0 auto; + max-width: 1332px; + padding: 0 20px; + position: relative; + width: 100% +} + +@media(max-width: 1599px) { + .banner-vsb-container.we-container { + max-width:1300px; + padding: 0 50px + } +} + +@media(max-width: 991px) { + .banner-vsb-container.we-container { + padding:0 20px + } +} + +.banner-vsb-container.we-container::after { + clear: both; + content: ""; + display: block +} + +.banner-vsb-container.we-container-fluid { + max-width: 100% +} + +@media (min-width: 768px) { + .banner-vsb-container.section { + border-radius: 20px; + overflow: hidden; + } + + .banner-vsb-container .video-wrapper, + .banner-vsb-container .default-content-wrapper { + width: 50%; + flex-shrink: 0; + } + + .banner-vsb-container .video-wrapper::before { + top: 0; + left: -1px; + background: linear-gradient(to right, var(--gray-bg), rgb(246 246 246 / 0%)); + } + + .banner-vsb-container .default-content-wrapper { + padding: 30px; + } + + .banner-vsb-container .banner-vsb-wrapper { + border-radius: 20px; + background: var(--gray-bg); + overflow: hidden; + } + + .banner-vsb-container .banner-vsb-wrapper .block { + flex-direction: row; + } + + .banner-vsb-container a.button:any-link:not(.modal, .primary) { + width: unset; + justify-content: unset; + display: inline-flex; + margin-right: 15px; + } +} + +@media (min-width: 992px) { + .banner-vsb-container h1 { + font: normal normal bold 48px/55px "IBM Plex Sans", sans-serif; + } + + .banner-vsb-container h2, + .banner-vsb-container h3, + .banner-vsb-container h4 { + font: normal normal bold 40px/52px "IBM Plex Sans", sans-serif; + } + + .banner-vsb-container { + height: 422px; + } + + .banner-vsb-container .banner-vsb-wrapper { + height: 100%; + } + + .banner-vsb-container .banner-vsb-wrapper .block { + height: 100%; + display: flex; + flex-direction: row; + } + + .banner-vsb-container .rte-wrapper { + width: 100%; + } + + .banner-vsb-container .video-wrapper { + height: 100%; + } + + .banner-vsb-container .default-content-wrapper { + padding-top: 0 !important; + height: 100%; + display: flex; + align-items: center; + } +} diff --git a/_src/blocks/banner-vsb/banner-vsb.js b/_src/blocks/banner-vsb/banner-vsb.js new file mode 100644 index 000000000..6b1a3b52a --- /dev/null +++ b/_src/blocks/banner-vsb/banner-vsb.js @@ -0,0 +1,74 @@ +import { decorateButtons } from '../../scripts/lib-franklin.js'; + +export default async function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const [rte, videoUrlEl] = [...block.children]; + + const videoUrl = videoUrlEl.textContent.trim(); + const videoFormat = videoUrl.split('.').pop(); + + // const blockDataset = getDatasetFromSection(block); + const { videoPlayerSettings, videoPlayerPoster } = block.closest('.section').dataset; + + function appendPreloadedVideo() { + const linkVideoEl = document.createElement('link'); + const linkVideoPosterEl = document.createElement('link'); + linkVideoEl.rel = 'preload'; + linkVideoEl.as = 'video'; + linkVideoEl.href = videoUrl; + linkVideoEl.type = `video/${videoFormat}`; + + linkVideoPosterEl.rel = 'preload'; + linkVideoPosterEl.as = 'image'; + linkVideoPosterEl.href = videoPlayerPoster; + + document.head.prepend(linkVideoPosterEl); + document.head.prepend(linkVideoEl); + } + + appendPreloadedVideo(); + + const formattedVideoSettings = videoPlayerSettings + .split(',') + .map((item) => { + let newStr = item; + if (newStr.includes('=')) { + newStr = item.replace('=', '="'); + newStr = `${newStr}"`; + + return newStr; + } + + return newStr.trim(); + }) + .join(' '); + + block.innerHTML = ` +
+ +
+
+ ${rte.innerHTML} +
+ `; + + block.querySelectorAll('.button-container > a').forEach((anchorEl) => { + anchorEl.target = '_blank'; + anchorEl.rel = 'noopener noreferrer'; + }); + + decorateButtons(block); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/solutions/blocks/barchart/barchart.css b/_src/blocks/barchart/barchart.css similarity index 100% rename from solutions/blocks/barchart/barchart.css rename to _src/blocks/barchart/barchart.css diff --git a/solutions/blocks/barchart/barchart.js b/_src/blocks/barchart/barchart.js similarity index 77% rename from solutions/blocks/barchart/barchart.js rename to _src/blocks/barchart/barchart.js index e866cb18d..7c51e1cf3 100644 --- a/solutions/blocks/barchart/barchart.js +++ b/_src/blocks/barchart/barchart.js @@ -10,7 +10,9 @@ export default function decorate(block) { ul.querySelectorAll('.barchart-body').forEach((container) => { const progressBars = container.querySelectorAll('ul li:nth-child(odd)'); progressBars.forEach((progressBar) => { - const value = (parseFloat(progressBar.nextElementSibling.textContent / 6) * 100).toFixed(2); + let valueAsString = progressBar.nextElementSibling.textContent; + valueAsString = valueAsString.replace(',', '.'); + const value = (parseFloat(valueAsString / 6) * 100).toFixed(2); progressBar.style.setProperty('--bar-width', `${value}%`); }); }); diff --git a/_src/blocks/big-teaser-section/big-teaser-section.css b/_src/blocks/big-teaser-section/big-teaser-section.css new file mode 100644 index 000000000..c2fd416b1 --- /dev/null +++ b/_src/blocks/big-teaser-section/big-teaser-section.css @@ -0,0 +1,119 @@ +.big-teaser-section-container { + background: white; + color: black; +} + +.big-teaser-section-container .default-content-wrapper { + display: flex; + flex-direction: column; +} + +.big-teaser-section-container .rte { + order: 1; + margin-top: 15px; +} + +.big-teaser-section-container .rte em { + color: #006EFF; + font-style: normal; +} + +.big-teaser-section-container .imgs-wrapper { + position: relative; + height: 300px; + border-radius: 15px; + overflow: hidden; +} + +.big-teaser-section-container .main-img { + width: 100%; + height: 100%; +} + + +.big-teaser-section-container .second-img { + position: absolute; + top: 0; + right: 0; + height: 100%; +} + + +@media screen and (min-width: 768px) { + .big-teaser-section-container.pb-0 { + padding-bottom: 0; + } + + .big-teaser-section-container.pt-1 { + padding-top: 1em; + } + + .big-teaser-section.block { + position: relative; + } + + .big-teaser-section-container .wrapper { + position: relative; + display: flex; + align-items: center; + } + + .big-teaser-section.reverted .wrapper { + flex-direction: row-reverse; + } + + .big-teaser-section-container .rte { + position: relative; + z-index: 1; + } + + .big-teaser-section.reverted .wrapper .rte { + margin-right: 60px; + } + + .big-teaser-section-container .imgs-wrapper { + width: 100%; + height: 450px; + top: 0; + margin: 0; + } + + .big-teaser-section-container .imgs-wrapper::before { + content: ''; + width: 100%; + height: 100%; + display: block; + position: absolute; + } +} + +@media screen and (min-width: 992px) { + .big-teaser-section-container p { + line-height: 1.3; + } + + .big-teaser-section-container .default-content-wrapper { + flex-direction: row; + align-items: unset; + } + + .big-teaser-section-container .default-content-wrapper > * { + width: calc(50% - 60px); + flex-shrink: 0; + } + + .big-teaser-section-container .default-content-wrapper > *:last-child { + margin-right: 60px; + } + + .big-teaser-section-container .imgs-wrapper { + height: 550px; + } + + .big-teaser-section-container .rte { + display: flex; + flex-direction: column; + justify-content: center; + margin-top: unset; + } +} diff --git a/_src/blocks/big-teaser-section/big-teaser-section.js b/_src/blocks/big-teaser-section/big-teaser-section.js new file mode 100644 index 000000000..a0cb5a757 --- /dev/null +++ b/_src/blocks/big-teaser-section/big-teaser-section.js @@ -0,0 +1,38 @@ +import { getDatasetFromSection } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [richTextEl, imageOnTopEl] = [...block.children]; + + const blockDataset = getDatasetFromSection(block); + const { desktopPicture, mobilePicture } = blockDataset; + + const picture = document.createElement('picture'); + const img = document.createElement('img'); + img.setAttribute('src', `${mobilePicture}?format=webply&optimize=medium`); + img.setAttribute('alt', 'picture'); + + const desktopSource = document.createElement('source'); + desktopSource.setAttribute('media', '(min-width: 768px)'); + desktopSource.setAttribute('type', 'image/webp'); + desktopSource.setAttribute('srcset', `${desktopPicture}?format=webply&optimize=medium`); + + picture.prepend(img); + picture.prepend(desktopSource); + + block.innerHTML = ` +
+
${richTextEl.children[0].innerHTML}
+ +
+
+ ${picture.outerHTML} +
+ + ${imageOnTopEl.querySelector('picture')} +
+ ${imageOnTopEl.querySelector('picture')?.innerHTML} +
+
+
+ `; +} diff --git a/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.css b/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.css new file mode 100644 index 000000000..34e3f0635 --- /dev/null +++ b/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.css @@ -0,0 +1,212 @@ +/* stylelint-disable no-descending-specificity */ +.bitdef-vs-brands { + display: flex; + flex-direction: column; + align-items: center; +} + +.bitdef-vs-brands .heading-container { + text-align: center; + max-width: 420px; +} + +.bitdef-vs-brands .new-container { + display: flex; + flex-direction: column; + align-items: center; +} + +.bitdef-vs-brands-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.bitdef-vs-brands-wrapper h2 { + font: normal normal bold 32px/37px Arial, sans-serif; +} + +.bitdef-vs-brands-wrapper h3 { + margin-bottom: 6px; + margin-top: 5px; + font: normal normal bold 24px Arial, sans-serif; +} + +.bitdef-vs-brands-wrapper .row-2 { + margin-bottom: 22px; + font-size: 14px; +} + +.bitdef-vs-brands-wrapper .table-container { + padding: 20px; + background-color: #f8f8f8; + border-radius: 16px; + max-width: 410px; + margin-bottom: 50px; +} + +.bitdef-vs-brands-wrapper table .blue-background p { + background-color: #005bd5; + color: white; + padding: 9px; + margin-top: 4px; + margin-bottom: 4px; + font: normal normal bold 14px/14px Arial, sans-serif; +} + +.bitdef-vs-brands-wrapper table .grey-background p { + background-color: #dedede; + padding: 9px; + margin-top: 4px; + margin-bottom: 4px; + font: normal normal normal 14px/14px Arial, sans-serif; +} + +.bitdef-vs-brands-wrapper table .blue-background p:nth-child(1) { + width: 100%; + border-radius: 8px 0 0 8px; +} + +.bitdef-vs-brands-wrapper table .blue-background p:nth-child(2) { + border-radius: 0 8px 8px 0; +} + +.bitdef-vs-brands-wrapper table .grey-background p:nth-child(1) { + width: 100%; + border-radius: 8px 0 0 8px; +} + +.bitdef-vs-brands-wrapper table .grey-background p:nth-child(2) { + border-radius: 0 8px 8px 0; +} + +.bitdef-vs-brands-wrapper table .same-line { + display: flex; + animation: increaseWidth 1s forwards; + width: 0; +} + +.bitdef-vs-brands-wrapper table .same-line:nth-child(1) { + margin-right: auto; +} + +.bitdef-vs-brands-wrapper .same-line { + animation: none; +} + +.bitdef-vs-brands-wrapper .same-line.animate { + animation: increaseWidth 1s forwards; +} + +.bitdef-vs-brands .row-2 > .column-0 { + padding-bottom: 14px; + font: normal normal normal 14px/18px Arial, sans-serif; +} + +.bitdef-vs-brands .row-6 > .column-0 { + padding-top: 14px; + font: normal normal normal 12px/14px Arial, sans-serif; +} + +@keyframes increase-width-row1 { + from { + width: 0; + } + + to { + width: 95%; + } +} + +/* Keyframes for the second row animation */ +@keyframes increase-width-row2 { + from { + width: 0; + } + + to { + width: 90%; + } +} + +/* Keyframes for the third row animation */ +@keyframes increase-width-row3 { + from { + width: 0; + } + + to { + width: 85%; + } +} + +/* Apply different animations to each row */ +.bitdef-vs-brands-wrapper table .row-3 .same-line.animate-row1 { + animation: increase-width-row1 1s forwards; +} + +.bitdef-vs-brands-wrapper table .row-4 .same-line.animate-row2 { + animation: increase-width-row2 1s forwards; +} + +.bitdef-vs-brands-wrapper table .row-5 .same-line.animate-row3 { + animation: increase-width-row3 1s forwards; +} + +.bitdef-vs-brands-wrapper img { + max-width: 32px; /* Adjust as needed */ + height: auto; /* Maintain aspect ratio */ +} + +@media (min-width: 768px) { + .bitdef-vs-brands-wrapper .heading-container { + max-width: 610px; + } + + .bitdef-vs-brands-wrapper .new-container { + flex-direction: row; + gap: 3%; + justify-content: center; + } + + .bitdef-vs-brands-wrapper .table-container { + width: 340px; + } +} + +@media (min-width: 990px) { + .bitdef-vs-brands-wrapper .new-container { + flex-direction: row; + gap: 3%; + justify-content: center; + } + + .bitdef-vs-brands-wrapper .table-container { + max-width: 410px; + } + + .bitdef-vs-brands-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .bitdef-vs-brandss-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .bitdef-vs-brandss-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.js b/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.js new file mode 100644 index 000000000..e42778bb7 --- /dev/null +++ b/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.js @@ -0,0 +1,83 @@ +// eslint-disable-next-line no-unused-vars +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const tables = block.querySelectorAll('.bitdef-vs-brands-wrapper table'); + + tables.forEach((table) => { + const parentDiv = table.closest('div'); + + parentDiv.classList.add('table-container'); + + table.querySelectorAll('tr').forEach((row, rowIndex) => { + row.classList.add(`row-${rowIndex}`); + + if (rowIndex >= 3 && rowIndex <= 5) { + if (rowIndex === 3) row.classList.add('blue-background'); + else row.classList.add('grey-background'); + row.querySelectorAll('td').forEach((td) => { + td.classList.add('same-line'); + }); + } + + row.querySelectorAll('td').forEach((cell, cellIndex) => { + cell.classList.add(`column-${cellIndex}`); + }); + }); + }); + // Select the first div within the .bitdef-vs-brands container + const firstDiv = block.querySelector('.bitdef-vs-brands > div'); + + // Add class 'heading-container' to the first div + firstDiv.classList.add('heading-container'); + + // Create a new container div + const newContainerDiv = document.createElement('div'); + newContainerDiv.classList.add('new-container'); + + // Move the second and third divs into the new container + while (firstDiv.nextSibling) { + newContainerDiv.appendChild(firstDiv.nextSibling); + } + + // Insert the new container after the first div + const bitdefContainer = block; + bitdefContainer.insertBefore(newContainerDiv, firstDiv.nextSibling); + + // Animation + const section = block; + + const threshold = { + threshold: 0.5, // Trigger animation when 50% of the section is visible + }; + + // eslint-disable-next-line no-unused-vars, no-shadow + const observer = new IntersectionObserver(((entries, observer) => { + entries.forEach((entry) => { + if (entry.isIntersecting && !entry.target.dataset.animationTriggered) { + // Add animation class to each row based on its index + // eslint-disable-next-line no-shadow + const tables = entry.target.querySelectorAll('table'); + tables.forEach((table) => { + const rows = table.querySelectorAll('.same-line'); + rows.forEach((row, index) => { + row.classList.add(`animate-row${index + 1}`); + }); + }); + // Set dataset attribute to indicate animation has been triggered + entry.target.dataset.animationTriggered = true; + } + }); + }), threshold); + + observer.observe(section); + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/bitdefender-central/bitdefender-central.css b/_src/blocks/bitdefender-central/bitdefender-central.css new file mode 100644 index 000000000..580d5f3fa --- /dev/null +++ b/_src/blocks/bitdefender-central/bitdefender-central.css @@ -0,0 +1,476 @@ +.bitdefender-central-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1290px; + --section-desktop-padding: 20px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); +} + + +.bitdefender-central-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; +} + +.bitdefender-central.block > div { + display: grid; + grid-template-columns: 1fr; + grid-gap: 32px; +} + +.bitdefender-central-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.bitdefender-central.block > div > div { + background-color: #F8F8F8; + border-radius: 20px; + padding: 24px; +} + +.bitdefender-central.block > div > div:last-of-type { + background-color: transparent; + border-radius: 20px; + padding: 0; + display: flex; + align-items: stretch; +} + +.bitdefender-central.block > div > div:last-of-type p { + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type > p:nth-of-type(1) { + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type > p:nth-of-type(5) { + margin-bottom: 7px; +} + +.bitdefender-central.block > div > div:first-of-type h3 { + font: normal normal bold 32px/38px var(--body-font-family); + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type > p:nth-of-type(2) { + font: normal normal normal 20px/23px var(--body-font-family); + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container { + display: inline-block; + padding-right: 24px; + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type a.button { + font: normal normal bold 16px/20px var(--body-font-family); + margin-top: 24px; + padding: 14px 28px; + color: #006EFF; + background: transparent; + border: 2px solid #006EFF; + border-radius: 10px; + display: inline-block; + position: relative; + min-width: 120px; + text-decoration: none; + text-align: center; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a.blue { + background-color: #006EFF; + color: white; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:focus { + outline: 2px solid #48C1FF; + border-radius: 13px; + outline-offset: 2px; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:hover { + padding: 14px 28px; + background: #006EFF; + color: #fff; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a.blue:hover { + background-color: #0A53C5; + border: 2px solid #0A53C5; + color: white; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:active { + background: #0D499B; + order: 2px solid #0D499B; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a.blue:active { + background: #0A53C5; + order: 2px solid #0A53C5; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:disabled { + background: transparent; + order: 2px solid #B7B7B7; + color: #B7B7B7; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a.blue:disabled { + background: #E7E7E7; + order: 2px solid #B7B7B7; + color: #B7B7B7; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a span { + transition: none; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:hover span { + transform: none; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a::after { + content: ''; + width: 0; + height: 0; + margin: 0; + transition: none; +} + +.bitdefender-central.block > div > div:first-of-type ul { + list-style: none; + margin: 0; + padding: 22px 0 24px; + list-style-type: none; + border-bottom: 1px solid #D1D1D1; +} + +.bitdefender-central.block > div > div:first-of-type ul li { + margin: 0; + padding: 7px 0 0; + font: normal normal normal 16px/18px var(--body-font-family); +} + +.bitdefender-central.block img { + max-width: 100%; + width: auto; + height: auto; +} + +.modal-container .columns-wrapper img { + height: 225px; +} + +.bitdefender-central.block a.video-placeholder img { + object-fit: cover; + height: 100%; + border-radius: 20px; +} + +.bitdefender-central.block > div > div:first-of-type ul li::before { + content: url("/_src/icons/checkmark-green-circle.svg"); + display: inline-block; + width: 18px; + height: 18px; + position: relative; + top: 4px; + margin-right: 9px; +} + +.bitdefender-central.block > div > div:first-of-type .icon.icon-bd-round-thumb { + width: 64px; + height: 64px; + margin-bottom: 14px; + background-color: white; + padding: 6px; + border-radius: 16px; + display: block; +} + +.bitdefender-central.block > div > div:first-of-type .linked-image-container { + display: inline-block; + padding-right: 0; + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type .linked-image-container img { + width: 154px; + height: 46px; +} + +a.video-placeholder { + position: relative; + align-items: stretch; + display: flex; + color: var(--button-link-color); +} + +.video-placeholder .video-placeholder-play { + box-sizing: border-box; + position: absolute; + top: 50%; + left: 50%; + display: block; + transform: scale(3); + width: 1.375rem; + height: 1.375rem; + border: 0.125rem solid; + border-radius: 1.25rem; + padding: 0; + background-color: #2020e0; + border-color: #2020e0; + opacity: 0.8; + transition: opacity .3s ease-in-out; +} + +.video-placeholder:hover .video-placeholder-play { + opacity: 1; +} + +.video-placeholder .video-placeholder-play::before { + content: ''; + display: block; + box-sizing: border-box; + position: absolute; + width: 0; + height: 0.625rem; + border-top: 0.3125rem solid transparent; + border-bottom: 0.3125rem solid transparent; + border-left: 0.375rem solid; + top: 0.25rem; + left: 0.4375rem; +} + +/* modal */ +.modal-container { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: var(--modal-background-color); + z-index: 999; +} + +.modal-video-container { + display: flex; +} + +.modal-container .modal-content { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: transparent; + + /* padding: 20px 30px 30px; */ + border-radius: 8px; + + /* box-shadow: 0 3px 8px 0 rgb(0 0 0 / 10%); */ + + /* border: 1px solid #707070; */ + + /* width: 75%; */ + max-height: 90%; + overflow: visible; + opacity: 1; + animation: fade-in 0.5s ease-in-out forwards; +} + +.modal-container .modal-content .section:first-child { + border-bottom: 1px solid var(--horizontal-separator-color); + padding-bottom: 15px; +} + +.modal-container .modal-content .modal-close { + height: 30px; + width: 30px; + border: 0; + padding: 1px 1px 0 0; + border-radius: 50%; + position: absolute; + top: -20px; + right: -14px; + cursor: pointer; + transition: all .3s ease-in-out; + outline: none; +} + +.modal-container .modal-content .modal-close::before { + content: ""; + position: absolute; + top: 13px; + left: 4px; + width: 26px; + height: 2px; + background: #000; + transform: rotate(45deg); + transition: all .3s ease-in-out; +} + +.modal-container .modal-content .modal-close::after { + content: ""; + position: absolute; + top: 13px; + left: 4px; + width: 26px; + height: 2px; + background: #000; + transform: rotate(133deg); + transition: all .3s ease-in-out; +} + +.modal-container.video-modal .modal-content { + background-color: transparent; + border: none; + box-shadow: none; + padding-top: 40px; + width: 100%; + max-width: 900px; +} + +.modal-container.video-modal .modal-content .section:first-child { + border-bottom: none; +} + +.modal-container.video-modal .modal-content .modal-close { + position: absolute; + top: 0; + width: 32px; + height: 32px; + opacity: 0.3; + background-color: unset; +} + +.modal-container.video-modal .modal-content .modal-close:hover { + opacity: 1; +} + +.modal-container.video-modal .modal-content .modal-close::after, .modal-container.video-modal .modal-content .modal-close::before { + position: absolute; + content: ' '; + height: 33px; + width: 2px; + background-color: #040dfd; +} + +.modal-container.video-modal .modal-content .modal-close::after { + transform: rotate(45deg); +} + +.modal-container.video-modal .modal-content .modal-close::before { + transform: rotate(-45deg); +} + +@media (min-width: 992px) { + .bitdefender-central-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .bitdefender-central.block > div { + grid-template-columns: 1fr 1fr; + } + + .video-placeholder .video-placeholder-play { + width: 2rem; + height: 2rem; + } + + .video-placeholder .video-placeholder-play::before { + height: 1rem; + top: 0.39rem; + left: 0.625rem; + border-top: 0.5rem solid transparent; + border-bottom: 0.5rem solid transparent; + border-left: 0.7rem solid; + } + + /* .modal-container .modal-content { + padding: 52px 62px 54px 55px; + max-width: 660px; + } */ + + .modal-container .modal-content .columns-wrapper { + padding-left: 0; + padding-right: 0; + } +} + +@media (min-width: 1200px) { + .bitdefender-central-container.we-container { + max-width: 1290px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/bitdefender-central/bitdefender-central.js b/_src/blocks/bitdefender-central/bitdefender-central.js new file mode 100644 index 000000000..b4ed63589 --- /dev/null +++ b/_src/blocks/bitdefender-central/bitdefender-central.js @@ -0,0 +1,186 @@ +function embedYoutube(url, autoplay) { + const usp = new URLSearchParams(url.search); + const suffix = autoplay ? '&muted=1&autoplay=0&enablejsapi=1' : ''; + let vid = usp.get('v') ? encodeURIComponent(usp.get('v')) : ''; + const embed = url.pathname; + if (url.origin.includes('youtu.be')) { + [, vid] = url.pathname.split('/'); + } + const modalContainer = document.createElement('dialog'); + modalContainer.classList.add('modal-container'); + + const modalContent = document.createElement('div'); + modalContent.classList.add('modal-content'); + modalContainer.appendChild(modalContent); + + const closeModal = () => modalContainer.close(); + const close = document.createElement('div'); + close.classList.add('modal-close'); + modalContent.append(close); + + const iframe = document.createElement('iframe'); + iframe.width = 783; + iframe.height = 440; + iframe.src = `https://www.youtube.com${vid ? `/embed/${vid}?rel=0&v=${vid}${suffix}` : embed}`; + iframe.title = 'YouTube video player'; + iframe.frameborder = 0; + iframe.allow = 'autoplay; fullscreen; accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture'; + iframe.allowFullscreen = true; + iframe.loading = 'lazy'; + modalContent.appendChild(iframe); + close.addEventListener('click', () => { + iframe.contentWindow.postMessage('{"event":"command","func":"stopVideo","args":""}', '*'); + closeModal(); + }); + return modalContainer; + // `
+ // + //
`; +} + +function decorateLinkedPictures(main) { + main.querySelectorAll('picture').forEach((picture) => { + // this condition checks if the picture is part of some content block ( rte ) + // and not a direct element in some DIV block + // that could have different behaviour for some blocks (ex: columns ) + if (picture.closest('div.block') && picture.parentElement.tagName !== 'DIV') { + const next = picture.parentNode.nextElementSibling; + if (next) { + const a = next.querySelector('a'); + const link = a?.textContent; + /* Modal video */ + if (a && link.startsWith('https://') && link.includes('fragments')) { + a.innerHTML = ''; + a.className = 'video-placeholder'; + a.appendChild(picture); + const overlayPlayButton = document.createElement('span'); + overlayPlayButton.className = 'video-placeholder-play'; + a.appendChild(overlayPlayButton); + a.addEventListener('click', async (event) => { + event.preventDefault(); + // eslint-disable-next-line no-use-before-define + }); + const up = a.parentElement; + if (up.childNodes.length === 1 && (up.tagName === 'P' || up.tagName === 'DIV')) { + up.classList.add('modal-video-container'); + } + return; + } + // Basic linked image + if (a && link.startsWith('https://')) { + a.innerHTML = ''; + a.className = 'linked-image'; + const pictureParent = picture.parentNode; + a.append(picture); + if (pictureParent.children.length === 0) { + pictureParent.parentNode.removeChild(pictureParent); + } + const up = a.parentElement; + if (up.childNodes.length === 1 && (up.tagName === 'P' || up.tagName === 'DIV')) { + up.classList.add('linked-image-container'); + } + } + } + } + }); +} + +function decorateButtons(element) { + const wrapButtonText = (a) => ((a.innerHTML.startsWith('<')) + ? `${a.querySelector('span.icon')?.outerHTML || ''}${a.textContent}` + : `${a.textContent}${a.querySelector('span.icon')?.outerHTML || ''}` + ); + element.querySelectorAll('a').forEach((a) => { + if (a.closest('.nav-brand') || a.closest('.nav-sections')) { + return; + } + a.title = a.title || a.textContent; + if (a.href !== a.textContent) { + const up = a.parentElement; + const twoup = a.parentElement.parentElement; + const threeup = a.parentElement.parentElement?.parentElement; + + if (!a.querySelector('img')) { + // Example:

Text

+ if (up.childNodes.length === 1 && up.tagName === 'STRONG' + && twoup.childNodes.length === 1 && twoup.tagName === 'P') { + a.className = 'button primary'; + twoup.classList.add('button-container'); + up.replaceWith(a); + a.innerHTML = wrapButtonText(a); + return; + } + if (up.childNodes.length === 1 && up.tagName === 'EM' + && twoup.childNodes.length === 1 && twoup.tagName === 'STRONG' + && threeup?.childNodes.length === 1 && threeup?.tagName === 'P') { + a.className = 'button secondary'; + threeup.classList.add('button-container'); + up.replaceWith(a); + a.innerHTML = wrapButtonText(a); + return; + } + // Example:

Text (example.com)

+ if (up.childNodes.length === 1 && up.tagName === 'P' && a.href.includes('/fragments/')) { + a.className = 'button modal'; + up.classList.add('button-container'); + return; + } + // Example:

Text 50% Discount

+ if (up.childNodes.length === 3 && up.tagName === 'P' && a.nextElementSibling?.tagName === 'EM') { + a.className = 'button'; + up.classList.add('button-container'); + a.innerHTML = wrapButtonText(a); + a.dataset.modal = a.nextSibling.textContent.trim().slice(1, -1); + a.nextSibling.remove(); + return; + } + // Example:

? Text

+ if (up.childNodes.length === 1 && up.tagName === 'P' && up.innerText.startsWith('?')) { + a.className = 'info-button modal'; + up.classList.add('info-button-container'); + a.textContent = a.textContent.slice(1).trim(); + a.title = a.title.slice(1).trim(); + return; + } + // Example:

Text

+ if (up.childNodes.length === 1 && (up.tagName === 'P' || up.tagName === 'DIV')) { + a.className = 'button'; // default + up.classList.add('button-container'); + a.innerHTML = wrapButtonText(a); + } + } + } + }); +} + +export default async function decorate(block, options) { + const { + // eslint-disable-next-line no-unused-vars + videoUrl, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + decorateLinkedPictures(block); + decorateButtons(block); + + const wrapper = block.querySelector('.video-placeholder'); + block.appendChild(embedYoutube(new URL(videoUrl), true)); + const modalContainer = block.querySelector('dialog'); + wrapper.addEventListener('click', () => { + modalContainer.showModal(); + }); + } + const firstButton = block.querySelector('a.button'); + if (firstButton) { + firstButton.classList.add('blue'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/blog-insert/blog-insert.css b/_src/blocks/blog-insert/blog-insert.css new file mode 100644 index 000000000..689f9d1d1 --- /dev/null +++ b/_src/blocks/blog-insert/blog-insert.css @@ -0,0 +1,8 @@ +.blog-insert-container { + text-align: center; +} + +.blog-insert-container img { + width: 100%; + height: auto; +} \ No newline at end of file diff --git a/_src/blocks/blog-insert/blog-insert.js b/_src/blocks/blog-insert/blog-insert.js new file mode 100644 index 000000000..733a139fb --- /dev/null +++ b/_src/blocks/blog-insert/blog-insert.js @@ -0,0 +1,18 @@ +export default function decorate(block) { + const urlDiv = block.querySelector('div > div:nth-child(2) > div'); + const url = urlDiv.textContent.trim(); + + // Get the picture element + const pictureElement = block.querySelector('picture'); + + // Create a new anchor element + const anchorElement = document.createElement('a'); + anchorElement.href = url; + + // Wrap the picture element with the anchor element + pictureElement.parentNode.insertBefore(anchorElement, pictureElement); + anchorElement.appendChild(pictureElement); + + block.textContent = ''; + block.append(anchorElement); +} diff --git a/_src/blocks/box-carousel/box-carousel.css b/_src/blocks/box-carousel/box-carousel.css new file mode 100644 index 000000000..f561aeac0 --- /dev/null +++ b/_src/blocks/box-carousel/box-carousel.css @@ -0,0 +1,227 @@ +/* stylelint-disable no-descending-specificity */ +.box-carousel-container { + background: white; +} + +.box-carousel-container .carousel-header { + display: flex; + align-items: center; + justify-content: space; +} + +.box-carousel-container .carousel-header .title { + color: black; +} + +.box-carousel-container .carousel-header .title p { + margin: 0 0 16px; +} + +.box-carousel-container .carousel-header .left-arrow.disabled, +.box-carousel-container .carousel-header .right-arrow.disabled { + opacity: 0.3; +} + +.box-carousel-container .carousel-header .left-arrow, +.box-carousel-container .carousel-header .right-arrow { + color: black; +} + +.box-carousel-container .carousel-container { + width: 100%; + position: relative; + display: flex; + overflow: hidden; +} + +.box-carousel-container .carousel { + display: flex; + transition: transform 150ms cubic-bezier(0.165, 0.84, 0.44, 1) 0s; +} + +.box-carousel-container .block.scrollable .carousel { + overflow: auto; +} + +.box-carousel-container .block.scrollable .carousel::-webkit-scrollbar { + display: none; +} + +.box-carousel-container .carousel-item { + display: flex; + flex-direction: column; + width: 220px; + min-height: 220px; + margin: 10px; + box-sizing: border-box; + padding: 20px; + border-radius: 15px; + color: black; + font-size: 1em; + background: #eaf2ff; + flex-shrink: 0; + border: solid 1px black; +} + +.box-carousel-container.testimonials .carousel-item { + width: 300px; + height: 300px; + display: flex; + flex-direction: column; + border: solid 1px #ddd; + background: white; + position: relative; +} + +.box-carousel-container .carousel-item:first-child { + margin-left: 0; +} + +.box-carousel-container .carousel-item .title { + letter-spacing: 0; + overflow: hidden; + margin: 12px 0; +} + +.box-carousel-container.testimonials .carousel-item .title { + -webkit-line-clamp: 6; + line-clamp: 6; +} + +.box-carousel-container .carousel-item .subtitle { + font: normal normal normal 12px/15px "IBM Plex Sans", sans-serif; + letter-spacing: 0; + overflow: hidden; + margin-top: auto; + color: #242424; +} + +.box-carousel-container.testimonials .carousel-item .subtitle-secondary { + font: normal normal bold 14px/21px "IBM Plex Sans", sans-serif; + margin-top: auto; + position: relative; +} + +.box-carousel-container.testimonials .carousel-item .subtitle-secondary::before { + content: ''; + display: block; + position: absolute; + width: 40px; + height: 1px; + background: black; + top: -5px; +} + +.box-carousel-container.testimonials .carousel-item .subtitle { + margin-top: unset; + color: #242424; +} + +.box-carousel-container .left-arrow svg { + transform: rotate(180deg); +} + +.box-carousel-container .arrow { + width: 100px; +} + +.box-carousel-container .arrow svg { + width: 100%; + height: 50px; +} + +.box-carousel-container .arrow svg path { + fill: white; +} + +.box-carousel-container .arrow.disabled svg path { + fill: #a5a5a5; +} + +.box-carousel-container .carousel-item .icon { + width: 35px; + height: 35px; + margin: 0; +} + +.box-carousel-container svg path { + fill: black !important; +} + +.box-carousel-container.testimonials .img-container { + height: 60px; + width: 100%; +} + +.box-carousel-container.testimonials .img-container img { + object-fit: contain; + filter: grayscale(100%); + width: unset; +} + + +@media screen and (min-width: 768px) { + .box-carousel-container .carousel-header { + justify-content: space-between; + margin-bottom: 20px; + } + + .box-carousel-container.testimonials .img-container { + width: 60%; + } + + .box-carousel-container.testimonials .carousel-item { + width: calc((100% - 25px) / 2); + min-height: 390px; + } + + .box-carousel-container .carousel-item .subtitle { + font: normal normal normal 18px/23px "IBM Plex Sans", sans-serif; + } + + .box-carousel-container.testimonials .carousel-item .subtitle { + font: normal normal normal 12px/15px "IBM Plex Sans", sans-serif; + } +} + +@media screen and (min-width: 992px) { + .box-carousel-container .default-content-wrapper { + overflow: hidden; + } + + .box-carousel-container.testimonials .carousel-item { + width: calc((100% - 25px) / 3); + min-height: 390px; + } + + .box-carousel-container .carousel-item .title { + font-size: 22px; + color: #242424; + font-weight: 500; + } + + .box-carousel-container.testimonials .carousel-item .subtitle { + font-size: 17px; + } + + .box-carousel-container.testimonials .carousel-item .subtitle-secondary { + font-size: 18px; + } + + .box-carousel-container:not(.testimonials) .carousel-item:hover { + color: white; + background: #006dff; + box-shadow: 0 3px 40px #006EFFF2; + } + + .box-carousel-container .carousel-item:hover svg path { + fill: white !important; + } +} + +@media (min-width: 1600px) { + .box-carousel-container.testimonials .carousel-item { + width: calc(100% / 3); + } +} + diff --git a/_src/blocks/box-carousel/box-carousel.js b/_src/blocks/box-carousel/box-carousel.js new file mode 100644 index 000000000..4e08f4d14 --- /dev/null +++ b/_src/blocks/box-carousel/box-carousel.js @@ -0,0 +1,165 @@ +import { decorateIcons } from '../../scripts/lib-franklin.js'; +import { debounce } from '../../scripts/utils/utils.js'; +import { isView } from '../../scripts/scripts.js'; + +export default async function decorate(block) { + const [titleEl, ...slides] = [...block.children]; + let currentSlideIndex = 0; + + const isTestimonials = block.closest('.section').classList.contains('testimonials'); + + const carouselItemStyle = { + margin: 20, + }; + + function isFirstIndex() { + return currentSlideIndex === 0; + } + + function isLastIndex() { + return currentSlideIndex === slides.length - 3; + } + + function scrollCarousel(offset, carousel) { + const carouselItem = block.querySelector('.carousel-item'); + carousel.style.transform = `translateX(${-1 * offset * (carouselItem.offsetWidth + carouselItemStyle.margin)}px)`; + } + + function getCarousel() { + return block.querySelector('.carousel'); + } + + function updateDisabledArrow() { + const leftArrowEl = block.querySelector('.left-arrow'); + const rightArrowEl = block.querySelector('.right-arrow'); + + leftArrowEl.classList.remove('disabled'); + rightArrowEl.classList.remove('disabled'); + + if (isLastIndex()) { + block.querySelector('.right-arrow').classList.add('disabled'); + return; + } + + if (isFirstIndex()) { + block.querySelector('.left-arrow').classList.add('disabled'); + } + } + + function leftArrowHandler(e) { + e.preventDefault(); + if (isFirstIndex()) { + return; + } + currentSlideIndex -= 1; + scrollCarousel(currentSlideIndex, getCarousel()); + updateDisabledArrow(currentSlideIndex); + } + + function rightArrowHandler(e) { + e.preventDefault(); + if (isLastIndex()) { + return; + } + currentSlideIndex += 1; + scrollCarousel(currentSlideIndex, getCarousel()); + updateDisabledArrow(currentSlideIndex); + } + + function renderArrows() { + block.classList.remove('scrollable'); + + if (isView('desktop')) { + const cardsNotFullyVisible = window.innerWidth > 767; + return cardsNotFullyVisible ? ` + + + + + + + + + + + + + + + ` : ''; + } + + block.classList.add('scrollable'); + return ''; + } + + function render() { + block.classList.add('default-content-wrapper'); + + block.innerHTML = ` + + + + `; + + decorateIcons(block); + + const leftArrowEl = block.querySelector('.left-arrow'); + const rightArrowEl = block.querySelector('.right-arrow'); + + if (leftArrowEl && rightArrowEl) { + leftArrowEl.removeEventListener('click', leftArrowHandler); + rightArrowEl.removeEventListener('click', rightArrowHandler); + + leftArrowEl.addEventListener('click', leftArrowHandler); + rightArrowEl.addEventListener('click', rightArrowHandler); + } + } + + render(); + + window.addEventListener('resize', debounce(render, 250)); +} diff --git a/_src/blocks/box-image-round-card/box-image-round-card.css b/_src/blocks/box-image-round-card/box-image-round-card.css new file mode 100644 index 000000000..5ac577997 --- /dev/null +++ b/_src/blocks/box-image-round-card/box-image-round-card.css @@ -0,0 +1,109 @@ +.box-image-round-card-container .inner-wrapper { + display: flex; + background-color: #fff; + border-radius: 8px; + box-shadow: 0 3px 6px 0 rgb(0 0 0 / 8%); + position: relative; + overflow: hidden; + z-index: 2; + width: 100%; + margin: 10px 0; + padding: 40px 23px 2pc; +} + +/* .box-image-round-card-container .inner-wrapper > div:nth-child(1) { */ + +/* width: 50%; */ + +/* } */ + +/* .box-image-round-card-container .inner-wrapper > div:last-child { */ + +/* border-radius: 50%; */ + +/* position: absolute; */ + +/* right: -35px; */ + +/* top: -60px; */ + +/* width: 225px; */ + +/* height: 225px; */ + +/* overflow: hidden; */ + +/* } */ + +.box-image-round-card-container .icon-apple { + width: 60px; + transform: none; +} + +.box-image-round-card-container img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform .3s ease-in-out,-webkit-transform .3s ease-in-out; + transform: scale(1); +} + +.box-image-round-card-container .inner-wrapper > a:first-child { + position: absolute; + top: 0; + left: 0; + z-index: 2; + width: 100%; + height: 100%; + text-indent: -999999px; +} + +.box-image-round-card-container .inner-wrapper p.button-container { + display: inline-block; + margin-right: 10px; +} + +@media(min-width: 767px) { + /* tablet */ + .box-image-round-card-container .inner-wrapper p { + font-size: 18px; + } + + /* .box-image-round-card-container .inner-wrapper > div:last-child { */ + + /* width: 325px; */ + + /* height: 325px; */ + + /* } */ + .box-image-round-card-container .inner-wrapper > a:first-child:hover ~ div p.button-container > a::after { + transform: translateX(5px); + opacity: 1; + } + + .box-image-round-card-container .inner-wrapper > a:first-child:hover ~ div p.button-container > a span.button-text { + transform: translate(-10px, 0); + } + + .box-image-round-card-container .inner-wrapper > a:first-child:hover ~ div img { + transform: scale(1.1); + } + + .box-image-round-card-container .default-content-wrapper { + display: flex; + } + + .box-image-round-card-container .card-wrapper { + order: 2; + flex: 60%; + display: flex; + align-items: center; + } + + .box-image-round-card-container .picture-wrapper { + order: 1; + flex: 40%; + padding-right: 25px; + margin: 10px 0; + } +} diff --git a/_src/blocks/box-image-round-card/box-image-round-card.js b/_src/blocks/box-image-round-card/box-image-round-card.js new file mode 100644 index 000000000..19b12d4d0 --- /dev/null +++ b/_src/blocks/box-image-round-card/box-image-round-card.js @@ -0,0 +1,35 @@ +import { createOptimizedPicture } from '../../scripts/lib-franklin.js'; +import { getDatasetFromSection } from '../../scripts/utils/utils.js'; + +export default function decorate(block) { + const innerWrapper = block.children[0]; + innerWrapper.classList = 'inner-wrapper'; + + // const iconElement = innerWrapper.children[0].children[0].children[0]; + // innerWrapper.children[0].children[0].remove(); + // innerWrapper.children[0].prepend(iconElement); + + // const originalAnchorEl = innerWrapper.children[0].lastElementChild.firstElementChild; + // const newAnchorEl = originalAnchorEl.cloneNode(); + // newAnchorEl.classList = ''; + // innerWrapper.prepend(newAnchorEl); + + const defaultWrapper = document.createElement('div'); + defaultWrapper.classList = 'default-content-wrapper'; + + const carWrapper = document.createElement('div'); + carWrapper.classList = 'card-wrapper'; + + carWrapper.append(innerWrapper); + + const pictureWrapper = document.createElement('div'); + pictureWrapper.classList = 'picture-wrapper'; + + const blockDataset = getDatasetFromSection(block); + pictureWrapper.append(createOptimizedPicture(blockDataset.bgImage, 'title')); + + defaultWrapper.prepend(carWrapper); + defaultWrapper.append(pictureWrapper); + + block.prepend(defaultWrapper); +} diff --git a/solutions/blocks/cards/cards.css b/_src/blocks/cards/cards.css similarity index 100% rename from solutions/blocks/cards/cards.css rename to _src/blocks/cards/cards.css diff --git a/solutions/blocks/cards/cards.js b/_src/blocks/cards/cards.js similarity index 100% rename from solutions/blocks/cards/cards.js rename to _src/blocks/cards/cards.js diff --git a/_src/blocks/columns/columns.css b/_src/blocks/columns/columns.css new file mode 100644 index 000000000..c42e13436 --- /dev/null +++ b/_src/blocks/columns/columns.css @@ -0,0 +1,899 @@ +.columns-wrapper { + padding: 0 var(--body-padding); +} + +.columns-container.chat-options p { + font-size: var(--body-font-size-s) !important; +} + +.columns.benefits > p { + margin-bottom: 0; + margin-top: 0; +} + +.columns.benefits p { + font-size: var(--body-font-size-s); + line-height: 1.5; + letter-spacing: .006em; + font-weight: var(--font-weight-regular); +} + +.columns.new-v2 p { + font-size: 16px; + font-weight: 400; + line-height: 22px; +} + +.columns.awards > div > div > p { + margin: 0; + padding: 0 5px; +} + +.columns.video-presentation > div > div > p { + font-size: var(--body-font-size-s); +} + +.columns.carousel > div > div > p { + width: inherit; + padding: 0 50px; + text-align: center; +} + +.columns-container.video-left .columns-right-col p { + margin: 1.5em 0; +} + +.columns > div { + display: flex; + flex-direction: column; + justify-content: center; +} + +.columns > div > div { + order: 1; +} + +.text-over-image > div > div { + height: 600px; + border-radius: 12px; + display: flex; + flex-direction: column; + color: var(--white-color); + padding: 30px; + justify-content: flex-end; + background-size: cover; + background-repeat: no-repeat; +} + +.columns.carousel > div { + flex-direction: row; + gap: 22px; +} + +.columns.benefits > div { + align-items: flex-start; +} + +/* awards styling */ +.columns.awards > div { + row-gap: 30px; +} + +.columns img { + width: 100%; +} + +.modal-container.get-bitdefender-familypack img { + height: auto; +} + +.columns.awards > div img { + display: block; + object-fit: contain; +} + +.grey-version .columns > div { + display: flex; + justify-content: space-between; +} + +.grey-version .columns > div > div { + --tw-bg-opacity: 1; + background-color: rgb(245 245 247 / var(--tw-bg-opacity)); + border-radius: 1rem; + padding: 3em; + margin-bottom: 1em; +} + +.text-over-image > div > div:first-child { + font-size: var(--heading-font-size-s); + margin-bottom: -10px; +} + +.percent-table .columns table tr { + align-items: center; + display: flex; + justify-content: space-between; +} + +.percent-table .columns table tr td:first-of-type { + font-size: var(--heading-font-size-l); + padding-right: 1.5em; +} + +.percent-table .columns table tr td:last-of-type { + width: 220px; +} + +.grey-version .columns > div > div h4 { + font-size: var(--heading-font-size-l); +} + +.creators .columns-container p.button-container { + text-align: center; +} + +.grey-version .columns > div > div p.button-container { + margin-bottom: auto; +} + +.columns-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.columns.highlight-text.black { + background-color: var(--black-color); + padding: 25px 2pc 20px 30px; + text-align: left; + position: absolute; + width: 100%; +} + +.columns.benefits h3 { + font-size: var(--heading-font-size-m); + font-weight: var(--font-weight-bold); + line-height: 1.25; +} + +.section.subtitle-blue h2 { + margin: 0 auto 3em; + width: 100%; + text-align: center; +} + +.section.subtitle-blue h3 { + font-size: 1.25rem; + --tw-text-opacity: 1; + color: rgb(0 110 255 / var(--tw-text-opacity)); +} + +.columns.video-presentation > div > div { + margin: 0 auto; +} + +.columns.carousel > div > div { + margin: 10px 5px; + width: 100%; + box-sizing: border-box; +} + +.columns.with-box-shadow > div > div { + padding: 0 20px; + border-right: none; + border-bottom: 2px solid var(--overlay-background-color); +} + +.columns.carousel > div:nth-child(1) { + position: relative; + left: 0; + gap: 0; + transition: transform 0.3s ease-in-out; + height: 200px; +} + +.creators .columns-container .columns > div { + justify-content: space-between; + margin-bottom: 3em; +} + +.columns.bg-image > div > div:first-child { + font-size: var(--heading-font-size-xl); + font-weight: bold; +} + +.columns.with-box-shadow > div > div:last-child { + border: none; +} + +.section.subtitle-blue .columns.benefits > div { + gap: 45px; + margin-bottom: 2em; +} + +.columns.awards > div > div > p:first-of-type { + margin-bottom: 24px; +} + +.section.subtitle-blue .columns.benefits p { + font-size: var(--body-font-size-s); + font-weight: 400; + letter-spacing: .006em; + line-height: 24px; +} + +.columns > div > .columns-img-col { + order: 0; + text-align: center; + margin-bottom: 2em; +} + +.columns > div > .columns-img-col img { + display: block; +} + +.creators .columns-container .columns > div:last-of-type { + margin-bottom: 0; +} + +.creators .columns-container h3, .creators .columns-container h5 { + font-weight: bold; +} + +.columns.new-v2 h3 { + font-family: "IBM Plex Sans" ,sans-serif; + font-size: 25px; + font-weight: 700; + line-height: 30px; + text-align: left; + color: #006EFF; +} + +.creators .columns-container h5, .creators .columns-container.baby-blue-subtitles h3 { + color: #006DFF; +} + +.creators .columns-container h5 { + font-weight: bold; +} + +.creators .columns-container.baby-blue-subtitles h3 br { + display: block; +} + +.creators .columns-container a.button { + height: auto; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 30px; + justify-content: center; + padding: 5px 10px; + font-size: 14px; +} + +.columns.bg-image a{ + color: white +} + +.columns.new-v2 a { + color: #006EFF!important; + font-size: 18px; + text-decoration: none; + font-weight: 600; + transition: all .2s cubic-bezier(.4,0,.2,1); +} + +.columns.new-v2 a:hover { + color: #0A53C5; + transform: translateX(10px); +} + +.columns-container.chat-options p.button-container a { + background-color: transparent; + border: 2px solid black; + color: black +} + +.columns-container.chat-options p.button-container a:hover { + background-color: black; + color: white; +} + +.columns-container.chat-options table { + width: 100%; +} + +.columns-container.chat-options table tr { + display: flex; + justify-content: space-between; +} + +.grey-version .columns > div > div img, .small-icons .columns > div > div img { + height: 60px; + width: auto; +} + +.columns.video-presentation .linked-image-container img { + width: 150px; + height: 44px; +} + +.columns.new-v2 > div > .columns-img-col img { + object-fit: contain; +} + +.columns-container.chat-options table tr td:first-of-type img { + height: 40px; +} + +.columns-container.chat-options table tr td:last-of-type img { + height: 133px; + display: none; +} + +@media (min-width: 767px) { + .columns.benefits > div { + flex-direction: unset; + gap: 32px; + align-items: stretch; + } + + .columns.highlight-text.black { + width: 520px; + right: 2.5%; + top: 15%; + border-radius: 5px; + } + + .columns.highlight-text.black.imageleft { + left: 2.5%; + } +} + +@media (min-width: 992px) { /* desktop */ + .columns-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .columns > div { + align-items: center; + flex-direction: unset; + gap: 32px; + } + + .columns > div > div { + flex: 1; + order: unset; + } + + .columns-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } + + .columns.highlight-text.black { + right: 10%; + top: 10%; + } + + .columns.highlight-text.black.imageleft { + left: 10%; + } + + .section.subtitle-blue h2 { + margin: 0 auto 3em; + width: 630px; + } + + .section.subtitle-blue h3 { + font-size: 1.25rem; + } + + .columns-container.chat-options .columns > div > div { + padding: 2em; + } + + .section.subtitle-blue .columns.benefits > div { + margin-bottom: 0; + } + + .columns > div > .columns-img-col { + margin-bottom: 1em; + } + + .columns-container.chat-options table tr td:last-of-type img { + display: block; + } + + .creators .columns-container .columns > div > div.columns-left-col, .creators .columns-container .columns > div > div.columns-right-col { + width: 45%; + flex: none; + } + + .creators .columns-container .columns > div > div.columns-img-col { + width: 50%; + flex: none; + } + + .creators .columns-container h5 { + color: #006DFF; + font: normal normal bold 32px/45px "IBM Plex Sans", sans-serif; + } + + .creators .header-mobile.columns-container h1 { + font: normal normal bold 60px/70px "IBM Plex Sans", sans-serif; + } + + .creators .header-mobile.columns-container h2 { + color: #006DFF; + font: normal normal bold 32px/45px "IBM Plex Sans", sans-serif; + margin-bottom: 0; + } + + .creators .columns-container h3 { + font: normal normal bold 60px/70px "IBM Plex Sans", sans-serif; + } + + .creators .columns-container p { + font: normal normal normal 24px/33px Arial, sans-serif; + } + + .creators .columns-container.smaller-text p { + font: normal normal normal 18px / 27px Arial, sans-serif; + } + + .creators .columns-container p.button-container { + text-align: left; + } + + .creators .columns-container a.button { + min-width: 230px; + height: 48px; + padding: 10px 10px 10px 25px; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 40px; + justify-content: center; + font: normal normal 500 18px/24px Roboto, sans-serif; + } +} + +@media (min-width: 1200px) { + .columns-container.we-container { + max-width: 1350px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { /* large desktop */ + .columns-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +/* Benefits columns (icon, text, description) */ +.columns.benefits > .icon { + width: unset; + max-width: 66px; + margin-bottom: 16px; +} + +.columns-container.video-left video { + width: 100%; + border-radius: 10px; +} + +.columns-container.video-left .columns-right-col { + width: 100%; + flex: none; +} + +@media (min-width: 1271px) { + .columns.benefits p { + font-size: 18px; + } +} + +/* paragraph with image */ +.columns.video-presentation .button-container { + display: inline-block; + padding-right: 13px; +} + +.columns.video-presentation .linked-image-container { + display: inline-block; + padding-right: 3px; + margin-top: 0; + margin-bottom: 0; +} + +.columns.video-presentation ul { + padding-top: 1px; +} + +.columns.vpn-presentation .button-container, +.columns.vpn-presentation .info-button-container{ + display: inline-block; + padding-right: 13px; + margin-top: 13px; +} + +.columns.vpn-presentation .left-col { + margin-bottom: 40px; +} + +@media (min-width: 992px) { + .columns.vpn-presentation .left-col { + margin-bottom: 0; + } +} + +.section.bullet-points.columns-container ul { + list-style: disc; +} + +.section.migration.columns-container ul { + padding: 0; +} + +.section.migration.columns-container ul li { + display: flex; + padding-left: 0; + margin-bottom: 1em; +} + +.section.migration.columns-container ul li::before { + content: url("/_src/icons/checkmark-light-green-circle.svg"); + display: inline-block; + width: 18px; + height: 18px; + position: relative; + top: 4px; + margin-right: 9px; + flex-shrink: 0; +} + +.section.migration.columns-container .columns-img-col img { + border-radius: 10px; +} + +.columns.video-presentation .modal-video-container { + max-width: 520px; + max-height: 293px; +} + +.columns.carousel { + width: 100%; + margin-top: 50px; + overflow: hidden; + height: 437px; +} + +.section.migration .columns.carousel { + margin-top: 0; + height: auto; +} + +.carousel-buttons { + position: relative; + top: 30px; + display: flex; + justify-content: center; + align-items: center; + transition: all .4s ease-in-out; +} + +.section.migration .columns.carousel .carousel-buttons { + top: -10px; +} + +.columns.carousel button { + align-items: flex-start; + width: 10px; + height: 10px; + border-radius: 100%; + margin: 10px; + padding: 0; + background-color: var(--black-color); + border: none; + cursor: pointer; +} + +.columns.carousel button:hover { + background-color: var(--link-color); +} + +.section.wide.light-sky-blue.columns-container { + height: auto; +} + +.section.white.columns-container .columns.awards > div { + flex-direction: unset; + align-items: center; +} + +.section.white.columns-container .columns.awards > div img { + display: block; + height: 120px; + object-fit: contain; +} + +@media (min-width: 676px) { + .columns.carousel > div > div { + transition: transform 0.3s, opacity 0.3s; + } + + .columns.carousel > div:nth-child(1) { + width: max-content; + } +} + +@media (min-width: 676px) and (max-width: 989px) { + .slide-left { + transform: translateX(-50%); + } +} + +@media (min-width: 990px) { + .columns.carousel button { + margin: -5px; + } + + .slide-left { + transform: translateX(-25%); + } + + .columns.with-box-shadow > div > div{ + border-bottom: none; + border-right: 2px solid var(--overlay-background-color); + min-height: 350px; + } + + .columns-container.video-left .columns-right-col { + width: 440px; + flex: none; + } +} + +.columns.carousel .active-button { + background-color: var(--link-color); +} + +.modal-container.get-bitdefender-familypack .columns.block.columns-2-cols > div { + display: flex; + flex-direction: column-reverse; + text-align: center; +} + +@media (min-width: 768px) { + .modal-container.get-bitdefender-familypack .columns.block.columns-2-cols > div { + display: flex; + flex: 1; + flex-direction: row; + order: unset; + justify-content: center; + align-items: center; + } +} + +.modal-container.modal-container.get-bitdefender-familypack .modal-content .section.columns-container { + border-bottom: none; + padding: 0; +} + +.columns-container[data-bg-image]{ + background-image: var(--bg-image-url); + background-size: cover; + background-position: center; + transition: padding-left 0.3s ease; + color: white; + text-align: center; + background-color: black; +} + +.linear-gradient.columns-container[data-bg-image]{ + background-size: cover; + background-position: center; + transition: padding-left 0.3s ease; + color: white; + background-image: none; + background-color: black; +} + +.columns.new-v2 h2 { + font-family: "IBM Plex Sans" ,sans-serif; + font-size: 25px; + font-weight: 600; + line-height: 32px; + text-align: center; + margin: 1em auto; +} + + + +@media (min-width: 768px) { + .linear-gradient.columns-container[data-bg-image]{ + background-image: linear-gradient(to right, rgb(0 0 0 / 100%) 20%, rgb(0 0 0 / 0%)), var(--bg-image-url); + } + + .columns-container[data-bg-image]{ + background-image: var(--bg-image-url); + } + + .linear-gradient.columns.bg-image > div { + width: calc(100% - 30%)!important; + } + + .columns.new-v2 h2 { + font-family: "IBM Plex Sans" ,sans-serif; + font-size: 32px; + font-weight: 600; + line-height: 36px; + text-align: center; + width: 600px; + margin: 2em auto; + } + + .columns.new-v2 h3 { + font-family: "IBM Plex Sans" ,sans-serif; + font-size: 32px; + font-weight: 700; + line-height: 37px; + text-align: left; + color: #006EFF; + } + + .columns.new-v2 p { + font-size: 16px; + font-weight: 400; + line-height: 22px; + } + + .columns.new-v2 div.columns-text-col { + padding: 2em; + } + + .columns.new-v2 div.columns-right-col { + margin-left: 5em; + margin-right: 5em; + } + + .columns.new-v2 div.columns-left-col { + margin-left: 5em; + margin-right: 5em; + } +} + +@media (min-width: 1024px) { + .columns.new-v2 div.columns-left-col { + margin-right: 10em; + margin-left: 0; + } +} + +.columns.bg-image > div > div > h4 { + padding: 0 0 50px; + font-size: var(--heading-font-size-m); + font-style: bold; +} + +.columns.bg-image .button-container { + padding: 10px 0 0; +} + +.columns.bg-image svg { + filter: invert(1) grayscale(1) brightness(100); +} + +.columns.with-box-shadow { + box-shadow: 0 3px 8px 0 rgb(0 0 0 / 20%); + border-radius: 5px; + padding: 35px 0; + color: var(--checkbox-label); +} + +.columns.highlight-text.black.block > div > div:first-child { + font-size: var(--heading-font-size-l); +} + + +main .section.two-columns .right-col .products.plans a.button:any-link { + background-color: var(--button-background-color); + border: 2px solid var(--button-background-color); +} + +.two-columns .left-col p a.info-button.modal { + color: var(--white-color); + display: flex; + font-weight: var(--font-weight-regular); + align-items: baseline; +} + +.two-columns .left-col p a.info-button.modal:hover { + opacity: .8; +} + +.two-columns .left-col p a.info-button.modal::before { + content: url("/_src/icons/user-guide-white.svg"); + color: white; + padding-right: 8px; +} + +.columns.new-v2 a::after { + content: '\2192'; + width: 24px; + height: 24px; + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + margin-left: 2px; +} + +.columns.new-v2 a:hover::after { + transform: translateX(5px); +} + +.columns.new-v2 > div > .columns-img-col { + margin-bottom: 1em; +} + +@media (max-width: 768px) { + .columns img, .columns.new-v2 > div > .columns-img-col img { + height: auto!important; + } +} + +@media (max-width: 991px) { + .creators .columns > div > div { + text-align: center; + } + + .creators .header-mobile.columns-container div { + text-align: center; + } + + .creators .header-mobile h1 { + font-size: 32px; + line-height: 1.2; + } + + .creators .header-mobile h2 { + font-size: 16px; + line-height: 1.2; + color: #006DFF; + font-weight: bold; + margin-bottom: 0; + } + + .creators .header-mobile h3 { + font-size: var(--heading-font-size-l); + line-height: 1.2; + } + + .creators .columns-container h3, .creators .columns-container h5, .creators .columns-container h2, .creators .columns-container h1 { + font-family: "IBM Plex Sans", sans-serif; + } + + .creators .default-content-wrapper h2 { + font-family: "IBM Plex Sans", sans-serif; + } + + .creators .image-position.columns-container div.columns-img-col { + display: none; + } + + .creators .image-position.columns-container .columns > div > div { + text-align: center; + } + + .creators .no-space-top .default-content-wrapper h2 { + padding-top: 23px; + } +} \ No newline at end of file diff --git a/solutions/blocks/columns/columns.js b/_src/blocks/columns/columns.js similarity index 75% rename from solutions/blocks/columns/columns.js rename to _src/blocks/columns/columns.js index 38b8862d3..8fc583c6e 100644 --- a/solutions/blocks/columns/columns.js +++ b/_src/blocks/columns/columns.js @@ -1,3 +1,5 @@ +import { debounce } from '../../scripts/utils/utils.js'; + function getItemsToShow() { if (window.innerWidth <= 676) { return 1; // Show 1 item for mobile screens @@ -48,9 +50,11 @@ function showSlides(carousel, slideNumber) { const columnWidthPx = containerWidth / itemsToShow; for (let i = start; i < end && i < childDivs.length; i += 1) { - childDivs[i].style.opacity = '1'; - childDivs[i].style.position = 'relative'; - childDivs[i].style.width = `${columnWidthPx}px`; + if (childDivs[i]) { + childDivs[i].style.opacity = '1'; + childDivs[i].style.position = 'relative'; + childDivs[i].style.width = `${columnWidthPx}px`; + } } } @@ -142,18 +146,6 @@ function setupCarousel(carousel, resetSlidePosition = false) { hideExcessElements(carousel); } -function debounce(func, wait) { - let timeout; - return function executedFunction(...args) { - const later = () => { - clearTimeout(timeout); - func(...args); - }; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - }; -} - function setImageAsBackgroundImage() { const columns = document.querySelectorAll('.columns.text-over-image > div > div'); @@ -174,7 +166,15 @@ function setImageAsBackgroundImage() { }); } -export default function decorate(block) { +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const { linksOpenInNewTab, type } = block.closest('.section').dataset; const cols = [...block.firstElementChild.children]; block.classList.add(`columns-${cols.length}-cols`); @@ -188,10 +188,32 @@ export default function decorate(block) { // picture is only content in column picWrapper.classList.add('columns-img-col'); } + } else { + const children = [...row.children]; + + if (children.length === 1) { + col.closest('div').classList.add('columns-title-col'); + } else { + const firstParentIndex = children.indexOf(col.closest('div')); + + col.closest('div').classList.add('columns-text-col'); + if (firstParentIndex) { + col.closest('div').classList.add('columns-right-col'); + } else { + col.closest('div').classList.add('columns-left-col'); + } + } } }); }); + if (linksOpenInNewTab === 'true') { + block.querySelectorAll('.button-container > a').forEach((anchorEl) => { + anchorEl.target = '_blank'; + anchorEl.rel = 'noopener noreferrer'; + }); + } + if (block.classList.contains('text-over-image')) { setImageAsBackgroundImage(); } @@ -216,4 +238,19 @@ export default function decorate(block) { sectionDiv.style.setProperty('--bg-image-url', `url(${bgImageUrl})`); } } + + // This allows the event to cross the shadow DOM boundary + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, + }); + + if (type && type === 'video_left') { + block.closest('.section').classList.add('video-left'); + const leftCol = block.querySelector('.columns-img-col'); + const videoPath = leftCol.querySelector('tr:last-of-type').innerText.trim(); + const videoImg = leftCol.querySelector('img').getAttribute('src'); + + leftCol.innerHTML = ``; + } } diff --git a/_src/blocks/creators-block/creators-block.css b/_src/blocks/creators-block/creators-block.css new file mode 100644 index 000000000..4286944c2 --- /dev/null +++ b/_src/blocks/creators-block/creators-block.css @@ -0,0 +1,184 @@ +@media (min-width: 992px) { + /* desktop */ + .creators-block-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +@media (min-width: 1600px) { + /* large desktop */ + .creators-block-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +.creators-block-wrapper { + border-radius: 20px; +} + +.creators-block.block>div { + position: relative; + padding-top: 40px; +} + +.creators-block.block>div:first-of-type img { + position: absolute; + right: 0; + top: 40px; +} + +.creators-block.block>div h3 { + text-align: left; + font-size: 60px; + line-height: 70px; + font-family: "IBM Plex Sans", sans-serif; + font-weight: normal; + letter-spacing: 0; + color: #FFF; +} + +.creators-block.block>div p { + text-align: left; + font-size: 28px; + line-height: 32px; + font-family: "IBM Plex Sans", sans-serif; + font-weight: bold; + letter-spacing: 0; + color: #FFF; +} + +.creators-block.block>div:nth-child(3) { + display: flex; + align-items: center; + justify-content: center; +} + +.creators-block.block>div:nth-child(3) a.button:any-link { + min-width: 230px; + height: 48px; + padding: 10px 10px 10px 25px; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 40px; + justify-content: center; + font: normal normal 500 18px / 24px Roboto, sans-serif; + margin-bottom: 35px; + color: white; +} + +.creators-block.block>div:nth-child(2)>div { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + grid-gap: 30px; +} + +.creators-block.block>div:nth-child(2) .creator-box { + display: flex; + position: relative; + width: 220px; + height: 310px; + padding: 16px 23px; + border-radius: 20px; +} + +.creators-block.block>div:nth-child(2) .creator-box>div:nth-child(3) { + position: absolute; + color: #fff; + text-align: left; + font-size: 12px; + line-height: 16px; + font-family: Roboto, sans-serif; + font-weight: normal; + bottom: 16px; +} + +.creators-block.block>div:nth-child(2) .creator-box>div:nth-child(2) { + position: absolute; + color: #016DFF; + text-align: left; + font-size: 12px; + line-height: 16px; + font-family: Roboto, sans-serif; + font-weight: normal; + bottom: 33px; +} + +.creators-block.block>div:nth-child(2) .creator-box>div:nth-child(1) { + position: absolute; + color: #fff; + text-align: left; + font-size: 12px; + line-height: 16px; + font-family: Roboto, sans-serif; + font-weight: bold; + bottom: 64px; +} + +.creators-block.block>div:nth-child(2) .creator-box>div:nth-child(1) img { + position: relative; + top: 10px; + width: 30px; +} + +@media (max-width: 1320px) { + .creators-block-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 8px; + } +} + +@media (max-width: 990px) { + .creators-block-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 8px; + } +} + +@media (max-width: 768px) { + .creators.creators-block-container .creators-block-wrapper { + margin: 0 8px; + } + + .creators.creators-block-container >div h3 { + font-size: var(--heading-font-size-l); + line-height: 1.2; + } + + .creators-block.block>div { + padding: 30px 0; + } + + .creators-block.block>div:first-of-type { + padding: 30px 0 0; + } + + .creators-block.block>div:last-of-type { + padding: 0; + } + + .creators-block.block>div p { + font-size: 22px; + line-height: 26px; + } + + .creators-block.block>div p:first-of-type { + margin: 0; + } + + .creators-block.block>div:first-of-type img { + position: relative; + width: 60px; + top: 0; + } +} + +@media (max-width: 525px) { + .creators-block.block>div:nth-child(2) .creator-box { + width: 100%; + height: 120vw; + } +} \ No newline at end of file diff --git a/_src/blocks/creators-block/creators-block.js b/_src/blocks/creators-block/creators-block.js new file mode 100644 index 000000000..23f8a405d --- /dev/null +++ b/_src/blocks/creators-block/creators-block.js @@ -0,0 +1,57 @@ +export default function decorate(block) { + const parentBlockStyle = block.closest('.section > div').style; + const { + // eslint-disable-next-line no-unused-vars + backgroundColor, + } = block.closest('.section').dataset; + + if (backgroundColor) parentBlockStyle.backgroundColor = backgroundColor; + + block.querySelectorAll('table').forEach((table) => { + const newDiv = document.createElement('div'); + newDiv.classList.add('creator-box'); + + const linkToCreator = table.querySelector('tr:nth-child(4) td'); + const creatorLink = linkToCreator ? linkToCreator.textContent.trim() : ''; + + // Find the image from the last row + const lastRow = table.querySelector('tr:last-child'); + const img = lastRow.querySelector('img'); + let backgroundImage = ''; + + if (img) { + backgroundImage = `url(${img.src})`; + } + + table.querySelectorAll('tr').forEach((tr, rowIndex) => { + // Skip the last row since we've already processed the image + if (rowIndex === table.rows.length - 1) return; + + tr.querySelectorAll('td').forEach((td) => { + const innerDiv = document.createElement('div'); + innerDiv.innerHTML = td.innerHTML; + newDiv.style.background = `linear-gradient(to bottom, rgba(0, 0, 0, 0) 60%, #000 100%), ${backgroundImage}`; + newDiv.style.backgroundSize = 'cover'; // Cover the whole div + newDiv.style.backgroundPosition = 'center'; // Center the image + newDiv.appendChild(innerDiv); + }); + }); + + // Remove the 4th div from creator-box + const fourthDiv = newDiv.querySelectorAll('div:nth-child(4)'); + if (fourthDiv.length > 0) { + newDiv.removeChild(fourthDiv[0]); + } + + // Wrap the newDiv in an anchor element if a link is found + if (creatorLink) { + const anchor = document.createElement('a'); + anchor.href = creatorLink; + anchor.target = '_blank'; + anchor.appendChild(newDiv); + table.parentNode.replaceChild(anchor, table); + } else { + table.parentNode.replaceChild(newDiv, table); + } + }); +} diff --git a/_src/blocks/dropdown-box/dropdown-box.css b/_src/blocks/dropdown-box/dropdown-box.css new file mode 100644 index 000000000..ea4fd0a2d --- /dev/null +++ b/_src/blocks/dropdown-box/dropdown-box.css @@ -0,0 +1,619 @@ +.dropdown-box-container .block img { + width: 20px; +} + +.dropdown-box-container .block>div { + padding: 15px 30px; +} + +/* blue tbs */ +.dropdown-box-container .block>div>div { + border-bottom: 1px solid #D6D6D6; +} + +.dropdown-box-container .block>div:not(:first-child) { + padding: 0; + font-weight: 500; + display: flex; +} + +.dropdown-box-container .block>div:nth-child(1) { + color: #fff; + background-color: #006eff; + padding: 0; +} + +.dropdown-box-container .block>div:first-of-type>div, +.dropdown-box-container .block>div:last-of-type>div { + border-bottom: 0 none; +} + +.dropdown-box-container .block>div:nth-child(1)>div { + font-weight: bold; + cursor: pointer; + padding: 15px 30px; +} + +.dropdown-box-container .block>div:not(:first-child)>div { + flex: 1; + padding: 15px 2%; + display: inline-block; +} + +.dropdown-box-container .block>div>div strong em { + color: red; + font-style: normal; +} + +.dropdown-box-container .block.hide-title>div:nth-child(1)>div, +.dropdown-box-container.hide-title .block>div:nth-child(1)>div { + display: none; +} + +.dropdown-box-container .block:not(.selected-2)>div>div:nth-child(2), +.dropdown-box-container .block.selected-1>div>div:nth-child(2), +.dropdown-box-container .block.selected-2>div>div:nth-child(3), +.dropdown-box-container .block.selected-3>div>div:nth-child(4) { + background-color: #f6f6f6; +} + +.dropdown-box-container.selected-1 .block>div>div:nth-child(2), +.dropdown-box-container.selected-2 .block>div>div:nth-child(3), +.dropdown-box-container.selected-3 .block>div>div:nth-child(4) { + background-color: #f6f6f6; +} + +.dropdown-box-container.selected-2 .block>div>div:nth-child(2), +.dropdown-box-container.selected-3 .block>div>div:nth-child(2) { + background-color: white; +} + +.dropdown-box-container .block>div:not(:first-child)>div:first-child { + display: block; + align-items: center; +} + +.dropdown-box-container .block>div:not(:first-child)>div:first-child p { + margin: 0; +} + +.dropdown-box-container .block>div:not(:first-child)>div:first-child span { + margin-left: 10px; +} + +.dropdown-box-container .block.has2divs>div>div:nth-child(2) { + width: 66%; + background-color: white; +} + +.dropdown-box-container .block.inactive>div:not(:first-child)>div, +.dropdown-box-container .block.closed>div:not(:first-child)>div, +.dropdown-box-container.inactive .block>div:not(:first-child)>div, +.dropdown-box-container.closed .block>div:not(:first-child)>div { + display: none; +} + +.dropdown-box-container .block.baby-blue>div:not(:first-child)>div:first-child, +.dropdown-box-container.baby-blue .block>div:not(:first-child)>div:first-child { + background-color: #e3f2ff; +} + +.dropdown-box-container .block.closed.inactive>div:not(:first-child)>div, +.dropdown-box-container.closed .block.inactive>div:not(:first-child)>div { + display: inline-block; +} + +.dropdown-box-container .block.has2divs>div>div:nth-child(2) img { + width: 400px; +} + +.dropdown-box-container.awards90 .block.has2divs>div>div:nth-child(2) img { + width: 90%; +} + +.dropdown-box-container .block.inactive>div:nth-child(1)>div::before, +.dropdown-box-container .block.closed>div:nth-child(1)>div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 10px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(-135deg); +} + +.dropdown-box-container.arrow-dark .block.inactive>div:nth-child(1)>div::before, +.dropdown-box-container.arrow-dark .block.closed>div:nth-child(1)>div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 10px; + border: solid black; + border-width: 0 2px 2px 0; + transform: rotate(-135deg); +} + +/* handling - arrow down/up */ +/* stylelint-disable no-descending-specificity */ +.dropdown-box-container .block>div:nth-child(1)>div::before, +.dropdown-box-container .block.closed.inactive>div:nth-child(1)>div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 4px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.dropdown-box-container.arrow-dark .block>div:nth-child(1)>div::before, +.dropdown-box-container.arrow-dark .block.closed.inactive>div:nth-child(1)>div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 4px; + border: solid black; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.dropdown-box-container .default-content-wrapper h5 { + font-size: 40px; + line-height: 1.2; + font-weight: 500; + color: #000; + font-family: roboto, sans-serif; + margin-bottom: 22px; + text-align: left; +} + +.dropdown-box-container .new, +.dropdown-box-container.new .block { + padding: 0 0 2em 2em; + cursor: pointer; + box-shadow: 0 3px 8px 0 #E5E5E5; + position: relative; + border-radius: 10px; + margin-bottom: 1em; + z-index: 3; +} + +.dropdown-box-container .dropdown-box-wrapper { + position: relative; +} + +.dropdown-box-container>div:nth-child(2) .new::after, +.dropdown-box-container.new>div:nth-child(2) .block::after { + content: ""; + position: absolute; + top: -60px; + right: 0; + width: 196px; + height: 90pt; + background: url("../../images/patter_grid_blue.png") no-repeat; + z-index: -1; +} + +.dropdown-box-container .new div:nth-child(1), +.dropdown-box-container.new .block div:nth-child(1) { + background-color: white; + padding-top: 2em; + padding-right: 2em; +} + +.dropdown-box-container .new>div:not(:first-child), +.dropdown-box-container.new .block>div:not(:first-child) { + display: block; +} + +.dropdown-box-container .new.inactive>div:not(:first-child), +.dropdown-box-container.new .block.inactive>div:not(:first-child) { + display: none; +} + +.dropdown-box-container .new.closed>div:not(:first-child), +.dropdown-box-container.new.closed .block.inactive>div:not(:first-child) { + display: none; +} + +.dropdown-box-container .new.closed.inactive>div:not(:first-child), +.dropdown-box-container.new.closed .block>div:not(:first-child) { + display: block; +} + +.dropdown-box-container .new>div:nth-child(1)>div, +.dropdown-box-container.new .block>div:nth-child(1)>div { + background: transparent; + font-size: 24px; + line-height: 1.25; + font-weight: 600; + color: #000; + padding: 0; + position: relative; +} + +.dropdown-box-container .new>div:nth-child(1)>div::before, +.dropdown-box-container.new .block>div:nth-child(1)>div::before { + display: none; +} + +.dropdown-box-container .new>div:nth-child(1)>div::after, +.dropdown-box-container.new .block>div:nth-child(1)>div::after { + content: ""; + position: absolute; + display: block; + top: 0; + bottom: 0; + margin: auto 0; + right: 15px; + width: 10px; + height: 10px; + border: solid #c5c5c5; + border-width: 0 2px 2px 0; + transform: rotate(45deg); + transition: top 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; + transition: top 0.3s ease-in-out, transform 0.3s ease-in-out; + transition: top 0.3s ease-in-out, transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; +} + +.dropdown-box-container .new>div:not(:first-child)>div:first-child, +.dropdown-box-container.new .block>div:not(:first-child)>div:first-child { + padding: 0; + font-weight: 500; + display: block; + width: 100%; + font-size: 18px; + color: #3c3c3c; +} + +.dropdown-box-container .new>div:not(:first-child)>div:first-child a, +.dropdown-box-container.new .block>div:not(:first-child)>div:first-child a { + color: #006eff; +} + +.dropdown-box-container.slider .new>div:not(:first-child) p, +.dropdown-box-container.slider.new .block>div:not(:first-child) p { + text-align: center; +} + +.dropdown-box-container.slider .new>div:not(:first-child) p img, +.dropdown-box-container.slider.new .block>div:not(:first-child) p img { + width: 300px; +} + +.dropdown-box-container.dropdown-slider { + position: relative; + margin-bottom: 2em; +} + +.dropdown-box-container.dropdown-slider::after { + content: ""; + position: absolute; + top: 16px; + right: 0; + width: 196px; + height: 90pt; + background: url("../../images/patter_grid_blue.png") no-repeat; + z-index: 1; +} + +.dropdown-box-container.dropdown-slider .dropdown-box-wrapper { + display: none; +} + +.dropdown-box-container.dropdown-slider .slider-box { + position: initial; +} + +.dropdown-box-container.dropdown-slider .slider-box .title { + padding: 1em; + cursor: pointer; + box-shadow: 0 3px 8px 0 #E5E5E5; + position: relative; + border-radius: 10px; + margin-bottom: 1em; + z-index: 3; + font-size: 16px; + line-height: 1.25; + color: #000; +} + +.dropdown-box-container.dropdown-slider .slider-box .title::after { + content: ""; + position: absolute; + display: block; + top: 0; + bottom: 0; + margin: auto 0; + right: 15px; + width: 10px; + height: 10px; + border: solid #c5c5c5; + border-width: 0 2px 2px 0; + transform: rotate(45deg); + transition: top 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; + transition: top 0.3s ease-in-out, transform 0.3s ease-in-out; + transition: top 0.3s ease-in-out, transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; +} + +.dropdown-box-container.dropdown-slider.no-load-bar .slider-box .title { + cursor: default; +} + +.dropdown-box-container.dropdown-slider.no-load-bar .slider-box .title::after { + display: none; +} + +.dropdown-box-container.dropdown-slider .slider-box .title .loading-bar { + display: none; + position: absolute; + top: 0; + left: 0; + width: 0; + height: 4px; + background: #006eff; + font-size: 19px; + line-height: 22px; + margin-bottom: 1em; +} + +.dropdown-box-container.dropdown-slider .slider-box .description { + position: absolute; + top: 12em; + right: 0; + padding-left: 5%; + display: none; + background-color: white; + z-index: 2; +} + +.dropdown-box-container.dropdown-slider .slider-box .active .title::after { + border-color: #006eff; + transform: rotate(225deg); + top: 11px; +} + +.dropdown-box-container.dropdown-slider .slider-box .active .title .loading-bar { + display: block; +} + +.dropdown-box-container.dropdown-slider .slider-box .active .description { + display: block; +} + +.dropdown-box-container { + clear: both; + padding: 0 var(--body-padding); + + .row { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + + display: flex; + flex-wrap: wrap; + margin-top: calc(-1* var(--bs-gutter-y)); + margin-right: calc(-.5* var(--bs-gutter-x)); + } + + .row>* { + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--bs-gutter-x)* .5); + padding-left: calc(var(--bs-gutter-x)* .5); + margin-top: var(--bs-gutter-y); + } + + .col-12 { + flex: 0 0 auto; + width: 100%; + } + + @media (min-width: 768px) { + .col-md-7 { + flex: 0 0 auto; + width: 58.3333%; + } + } + + @media (min-width: 768px) { + .col-md-5 { + flex: 0 0 auto; + width: 41.6667%; + } + } + + &.container { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + + width: 100%; + padding-right: calc(var(--bs-gutter-x)* .5); + padding-left: calc(var(--bs-gutter-x)* .5); + margin-right: auto; + margin-left: auto; + + @media (min-width: 576px) { + max-width: 540px; + } + + @media (min-width: 768px) { + max-width: 720px; + } + + @media (min-width: 992px) { + max-width: 960px; + } + + @media (min-width: 1200px) { + max-width: 1140px; + } + + @media (min-width: 1400px) { + max-width: 1320px; + } + } + + @media (min-width: 990px) { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } + + @media (min-width: 1600px) { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + + +@media (width <=991px) { + .dropdown-box-container .default-content-wrapper h5 { + font-size: 33px; + } +} + +/* for mobile */ +@media (width <=768px) { + .dropdown-box-container { + clear: both; + padding: 0 15px 5px; + } + + .dropdown-box-container.dropdown-slider .dropdown-box-wrapper { + display: block; + } + + .dropdown-box-container.dropdown-slider .dropdown-box-wrapper img { + width: 90%; + } + + .dropdown-box-container.dropdown-slider .slider-box { + display: none; + } + + .dropdown-box-container .block>div:not(:first-child) { + display: block; + } + + .dropdown-box-container .block>div:nth-child(1)>div::before, + .dropdown-box-container .block.closed.inactive>div:nth-child(1)>div::before { + margin-top: 1px !important; + } + + .dropdown-box-container .block>div:nth-child(1)>div { + padding: 10px 3% !important; + display: flex; + font-size: 15px; + line-height: 17px; + } + + .dropdown-box-container .new>div:nth-child(1)>div::after, + .dropdown-box-container.new .block>div:nth-child(1)>div::after { + position: static; + margin-left: 15px; + flex: 0 0 auto; + } + + .dropdown-box-container.no-dropdown-logic .block>div:nth-child(1)>div { + display: block; + } + + .dropdown-box-container.no-dropdown-logic .new>div:nth-child(1)>div::after, + .dropdown-box-container.no-dropdown-logic.new .block>div:nth-child(1)>div::after { + display: none; + } + + .dropdown-box-container>div:nth-child(2) .new::after { + top: -90px; + right: 0; + width: 135px; + height: 90pt; + display: none; + } + + .dropdown-box-container.dropdown-slider::after { + display: none; + } + + .dropdown-box-container .block>div:not(:first-child)>div { + padding: 8px 2% !important; + font-size: 15px; + } + + .dropdown-box-container .block img { + width: 15px; + } + + .dropdown-box-container .block>div:not(:first-child)>div:nth-child(1) { + width: 100%; + text-align: center; + } + + .dropdown-box-container .block>div:not(:first-child)>div:not(:first-child) { + width: 50%; + float: left; + } + + .dropdown-box-container .block.has4divs>div:not(:first-child)>div:not(:first-child) { + width: 33%; + min-height: 3em; + font-size: 13px; + line-height: 16px; + } + + .dropdown-box-container .block.has4divs>div:not(:first-child)>div:first-child p { + line-height: 17px; + } + + .dropdown-box-container .block.has3divs>div:not(:first-child)>div:not(:first-child) { + width: 50%; + min-height: 3em; + font-size: 13px; + line-height: 16px; + } + + .dropdown-box-container .block.has2divs>div:not(:first-child)>div:not(:first-child) { + width: 100%; + } + + .dropdown-box-container .default-content-wrapper h5 { + font-size: 30px; + line-height: 32px; + } + + .dropdown-box-container .new, + .dropdown-box-container.new .block { + padding: 15px; + } + + .dropdown-box-container .new p, + .dropdown-box-container.new .block p { + font-size: 15px; + } + + .dropdown-box-container .new div:nth-child(1), + .dropdown-box-container.new .block div:nth-child(1) { + padding-top: 0; + padding-right: 0; + } + + .dropdown-box-container .new div:nth-child(1)>div, + .dropdown-box-container.new .block div:nth-child(1)>div { + font-size: 18px; + line-height: 24px; + } + + .dropdown-box-container .new ul, + .dropdown-box-container.new .block ul { + text-align: left; + } +} \ No newline at end of file diff --git a/_src/blocks/dropdown-box/dropdown-box.js b/_src/blocks/dropdown-box/dropdown-box.js new file mode 100644 index 000000000..468c09a25 --- /dev/null +++ b/_src/blocks/dropdown-box/dropdown-box.js @@ -0,0 +1,82 @@ +/* + Information: + - the tab is open by default + - [add-on] - will be treated as green tag + + Parameters: + - (closed) : for tab to be closed by default +*/ +export default function decorate(block) { + const parentSelector = block.closest('.section'); + const { type, topBackgroundColor, topTextColor } = parentSelector.dataset; + + // search for [] to replace with span greeenTag class + const getFirstDivs = block.querySelectorAll('.dropdown-box-container .block > div > div:nth-child(1)'); + getFirstDivs.forEach((item) => { + item.innerHTML = item.innerHTML.replace('[', ''); + item.innerHTML = item.innerHTML.replace(']', ''); + }); + + // make slideUp slideDown functionality + const getFirstTabs = block.querySelectorAll('.dropdown-box-container .block > div:first-child'); + getFirstTabs.forEach((tab) => { + tab.parentNode.classList.remove('inactive'); + tab.addEventListener('click', () => { + tab.parentNode.classList.toggle('inactive'); + }); + }); + + if (block.children.length >= 2) { + const childrenNr = block.children[1].children.length; + block.classList.add(`has${childrenNr}divs`); + + if (topBackgroundColor) { + block.querySelector('div:nth-child(1) > div > div').style.backgroundColor = topBackgroundColor; + } + + if (topTextColor) { + block.querySelector('div:nth-child(1) > div').style.color = topTextColor; + } + } + + // if it's slider + if (type === 'slider') { + block.closest('.dropdown-box-container').classList.add('container', 'dropdown-slider'); + const sliderBox = document.createElement('div'); + sliderBox.className = 'slider-box'; + + const infoTextEl = block.children[0].children[0]; + const infoTextEl2 = block.children[1].children[0]; + sliderBox.innerHTML = ` +
+
+
+ ${infoTextEl.innerHTML} +
+
${infoTextEl2.innerHTML}
+
+ `; + + block.closest('.dropdown-box-container').appendChild(sliderBox); + } + + // if it's slider + if (type === 'slider-no-load-bar') { + block.closest('.dropdown-box-container').classList.add('container', 'dropdown-slider', 'no-load-bar'); + const sliderBox = document.createElement('div'); + sliderBox.className = 'slider-box'; + + const infoTextEl = block.children[0].children[0]; + const infoTextEl2 = block.children[1].children[0]; + sliderBox.innerHTML = ` +
+
+ ${infoTextEl.innerHTML} +
+
${infoTextEl2.innerHTML}
+
+ `; + + block.closest('.dropdown-box-container').appendChild(sliderBox); + } +} diff --git a/_src/blocks/dropdownbox-compare/dropdownbox-compare.css b/_src/blocks/dropdownbox-compare/dropdownbox-compare.css new file mode 100644 index 000000000..98dcb951d --- /dev/null +++ b/_src/blocks/dropdownbox-compare/dropdownbox-compare.css @@ -0,0 +1,287 @@ +/* b-boxes .dropdownbox-compare-container */ +.dropdownbox-compare-container { + clear: both; + padding: 0!important; +} + +.dropdownbox-compare-container .block img { + width: 20px; +} + +.dropdownbox-compare-container .block > div { + padding: 0; + font-weight: 500; + display: flex; +} + +/* blue tbs */ +.dropdownbox-compare-container .block > div > div { + border-bottom: 1px solid #e4f2ff; + border: 1px solid #e4f2ff; + flex: 1; + padding: 15px 20px; + display: inline-block; +} + +.dropdownbox-compare-container .block > div:nth-child(1) > div { + font-weight: bold; + cursor: pointer; +} + +.dropdownbox-compare-container .block > div > div strong em { + color: red; + font-style: normal; +} + +.dropdownbox-compare-container .block > div:first-of-type > div, .dropdownbox-compare-container .block > div:last-of-type > div { + border-bottom: 0 none; +} + +.dropdownbox-compare-container .block > div > div:not(:nth-child(1)) { + display: flex; + align-items: center; + justify-content: center; +} + +.dropdownbox-compare-container .block > div:nth-child(1) > div:nth-child(1) { + color: #fff; + background-color: #006eff; +} + +.dropdownbox-compare-container .block > div:not(:nth-child(1)) > div:nth-child(1) { + background: #e4f2ff; +} + +.dropdownbox-compare-container .block:not(.selected-2) > div > div:nth-child(2), .dropdownbox-compare-container .block.selected-1 > div > div:nth-child(2), .dropdownbox-compare-container .block.selected-2 > div > div:nth-child(3), .dropdownbox-compare-container .block.selected-3 > div > div:nth-child(4) { + background-color: #f6f6f6; +} + +.dropdownbox-compare-container.selected-1 .block > div > div:nth-child(2), .dropdownbox-compare-container.selected-2 .block > div > div:nth-child(3), .dropdownbox-compare-container.selected-3 .block > div > div:nth-child(4) { + background-color: #f6f6f6; +} + +.dropdownbox-compare-container.selected-2 .block > div > div:nth-child(2), .dropdownbox-compare-container.selected-3 .block > div > div:nth-child(2) { + background-color: white; +} + +.dropdownbox-compare-container .block > div:not(:first-child) > div:first-child { + display: block; + align-items: center; +} + +.dropdownbox-compare-container .block > div > div p { + font-family: roboto, sans-serif; + font-size: 14px; + font-weight: 400; +} + +.dropdownbox-compare-container .block > div:first-child > div p { + color: white; +} + +.dropdownbox-compare-container .block > div:not(:first-child) > div p { + color: #616161; +} + +.dropdownbox-compare-container .block > div > div:first-child p { + margin: 0; + margin-left: 26px; +} + +.dropdownbox-compare-container .block > div > div span.green-tag { + background: #2cb43d; + border-radius: 50px; + color: #3c3c3c; + color: #fff !important; + display: block; + font-family: roboto, sans-serif; + font-size: 10px !important; + font-style: normal; + font-weight: 700; + margin: -5px 0 6px; + padding: 0 20px; + padding: 3px 9px !important; + text-transform: uppercase; + width: -moz-fit-content; + width: fit-content; +} + + +.dropdownbox-compare-container .block > div > div strong { + font-size: 14px; + line-height: 1.5; + font-weight: normal; +} + +.dropdownbox-compare-container .block.closed > div:not(:first-child) > div, .dropdownbox-compare-container.closed .block > div:not(:first-child) > div { + display: none; +} + +.dropdownbox-compare-container .block.closed > div > div:not(:nth-child(1)) { + display: flex; + align-items: center; + justify-content: center; +} + +.dropdownbox-compare-container .block.closed > div:not(:first-child) > div:first-of-type, .dropdownbox-compare-container.closed .block.closed > div:not(:first-child) > div:first-of-type { + display: inline-block; +} + +.dropdownbox-compare-container .block.closed > div:nth-child(1) > div:nth-child(1)::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 10px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(-135deg); +} + +/* handling - arrow down/up */ +/* stylelint-disable no-descending-specificity */ +.dropdownbox-compare-container.no-arrow .block > div:nth-child(1) > div::before { + visibility: hidden; +} + +.dropdownbox-compare-container .block > div:nth-child(1) > div::before, +.dropdownbox-compare-container .block.closed > div:nth-child(1) > div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 4px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.dropdownbox-compare-container .dropdownbox-compare-wrapper { + position: relative; +} + +@media (width <= 991px) { + .dropdownbox-compare-container .default-content-wrapper h5 { + font-size: 33px; + } +} + +/* for mobile */ +@media (width <= 991px) { + .dropdownbox-compare-container .block > div { + display: block; + } + + .dropdownbox-compare-container .block > div > div:nth-child(1) { + width: 100%; + } + + .dropdownbox-compare-container .block > div > div:not(:nth-child(1)) { + width: 33%!important; + float: left; + } +} + +@media (width <= 768px) { + .dropdownbox-compare-container { + clear: both; + padding: 0 15px 5px; + } + .dropdownbox-compare-container .block > div:not(:first-child) { + display: block; + } + .dropdownbox-compare-container .block > div:nth-child(1) > div:nth-child(1)::before, .dropdownbox-compare-container .block.closed.close > div:nth-child(1) > div:nth-child(1)::before { + margin-top: 1px !important; + } + .dropdownbox-compare-container .block > div:nth-child(1) > div { + padding: 10px 3% !important; + display: flex; + font-size: 15px; + line-height: 17px; + } + .dropdownbox-compare-container .new > div:nth-child(1) > div:nth-child(1)::after, .dropdownbox-compare-container.new .block > div:nth-child(1) > div:nth-child(1)::after { + position: static; + margin-left: 15px; + flex: 0 0 auto; + } + .dropdownbox-compare-container > div:nth-child(2) .new::after { + top: -90px; + right: 0; + width: 135px; + height: 90pt; + display: none; + } + .dropdownbox-compare-container .block > div:not(:first-child) > div { + padding: 8px 2% !important; + font-size: 15px; + } + .dropdownbox-compare-container .block img { + width: 15px; + } + .dropdownbox-compare-container .block > div:not(:first-child) > div:nth-child(1) { + width: 100%; + text-align: center; + } + .dropdownbox-compare-container .block > div:not(:first-child) > div:not(:first-child) { + width: 50%; + float: left; + } + .dropdownbox-compare-container .default-content-wrapper h5 { + font-size: 30px; + line-height: 32px; + } + .section.product-comparison-table-container.migration .old-price-box { + flex-direction: column; + } + .section.product-comparison-table-container.migration .old-price-box span { + flex-direction: column; + justify-content: center; + align-items: center; + margin: 5px 0; + } + .section.product-comparison-table-container.migration .old-price-box span del { + margin-left: 10px; + } + .section.product-comparison-table-container.migration .new-price-box { + flex-direction: column; + align-items: center; + justify-content: center; + font-size: 22px; + } + .section.product-comparison-table-container.migration .new-price-box span { + margin: 0 0 7px; + } + + .section.product-comparison-table-container.migration .product-comparison-price > p:last-of-type, .section.product-comparison-table-container.migration .product-comparison-header div[role="columnheader"] p { + text-align: center; + min-height: auto; + } + .section.product-comparison-table-container.migration h3 { + font-size: 15px !important; + } + + .section.product-comparison-table-container.migration p.button-container { + margin-bottom: 1em; + } + + .section.product-comparison-table-container.migration .product-comparison-price { + margin: 3px; + } +} + +@media (min-width: 992px) { + .dropdownbox-compare-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + } +} + +@media (min-width: 580px) { + .dropdownbox-compare-wrapper { + margin: 0 auto; + overflow-y: visible; + + } +} \ No newline at end of file diff --git a/_src/blocks/dropdownbox-compare/dropdownbox-compare.js b/_src/blocks/dropdownbox-compare/dropdownbox-compare.js new file mode 100644 index 000000000..4566f113d --- /dev/null +++ b/_src/blocks/dropdownbox-compare/dropdownbox-compare.js @@ -0,0 +1,17 @@ +export default function decorate(block) { + // search for [] to replace with span greeenTag class + const getFirstDivs = block.querySelectorAll('.dropdownbox-compare-container .block > div > div:nth-child(1)'); + getFirstDivs.forEach((item) => { + item.innerHTML = item.innerHTML.replace('[', ''); + item.innerHTML = item.innerHTML.replace(']', ''); + }); + + // make slideUp slideDown functionality + const getFirstTabs = block.querySelectorAll('.dropdownbox-compare-container .block > div:first-child'); + getFirstTabs.forEach((tab) => { + tab.parentNode.classList.remove('closed'); + tab.addEventListener('click', () => { + tab.parentNode.classList.toggle('closed'); + }); + }); +} diff --git a/_src/blocks/dual-teaser/dual-teaser.css b/_src/blocks/dual-teaser/dual-teaser.css new file mode 100644 index 000000000..6825ab5c7 --- /dev/null +++ b/_src/blocks/dual-teaser/dual-teaser.css @@ -0,0 +1,148 @@ +/* stylelint-disable no-descending-specificity */ +.dual-teaser-container.section { + background: transparent linear-gradient(180deg, #006EFF 0%, #000 100%) 0 0 no-repeat padding-box; + overflow: unset; + padding-top: 0; +} + +.dual-teaser-container.section::before { + content: ''; + display: block; + width: 100%; + height: 200px; + background: #EFF6FF; + position: relative; + top: -1px; +} + +.dual-teaser-container .col-container { + width: 100%; +} + +.dual-teaser-container .col-container:first-child { + margin-bottom: 20px; +} + +.dual-teaser-container .col-container .card { + width: 100%; + height: 350px; + position: relative; + display: flex; + flex-direction: column; + justify-content: flex-end; + border-radius: 10px; + overflow: hidden; +} + +.dual-teaser-container .default-content-wrapper { + margin-top: -120px; +} + +.dual-teaser-container .img-container { + width: 100%; + height: 100%; + position: absolute; + overflow: hidden; + border-radius: inherit; +} + +.dual-teaser-container .col-container .box { + height: 190px; + padding: 10px; + background: #003b89a3 0 0 no-repeat padding-box; + backdrop-filter: blur(30px); + display: flex; + flex-direction: column; + border-bottom-right-radius: 10px; + border-bottom-left-radius: 10px; +} + +.dual-teaser-container .col-container .box h2, +.dual-teaser-container .col-container .box h3, +.dual-teaser-container .col-container .box h4, +.dual-teaser-container .col-container .box h5 { + color: white; + letter-spacing: 0; +} + +.dual-teaser-container .col-container .box p, +.dual-teaser-container .col-container .box div { + font: normal normal normal 14px/18px "IBM Plex Sans", sans-serif; + letter-spacing: 0; + margin: 0; +} + +.dual-teaser-container .col-container .box .button-container { + margin-top: auto; +} + +.dual-teaser-container .col-container .box a { + width: 100%; + justify-content: center; +} + +.dual-teaser-container .col-container span.icon { + display: none; +} + +@media (min-width: 768px) { + .dual-teaser-container .default-content-wrapper { + width: 100%; + display: flex; + margin-top: -180px; + } + + .dual-teaser-container .col-container:first-child { + margin-top: unset; + } + + .dual-teaser-container .col-container:first-child .card { + border-radius: 20px 0 0 20px; + } + + .dual-teaser-container .col-container:last-child .card { + border-radius: 0 20px 20px 0; + } + + .dual-teaser-container .col-container { + position: relative; + margin-bottom: 0; + } + + .dual-teaser-container .col-container .card { + height: 600px; + } + + .dual-teaser-container .col-container .box { + padding: 33px 7% 33px 33px; + height: 270px; + border-bottom-right-radius: unset; + border-bottom-left-radius: unset; + } + + .dual-teaser-container .col-container .box a { + width: unset; + } + + .dual-teaser-container .col-container .box p, + .dual-teaser-container .col-container .box div { + font: normal normal normal 18px/23px "IBM Plex Sans", sans-serif; + letter-spacing: 0; + } + + .dual-teaser-container .col-container .box h2, + .dual-teaser-container .col-container .box h3, + .dual-teaser-container .col-container .box h4, + .dual-teaser-container .col-container .box h5 { + margin-bottom: 16px; + } + + .dual-teaser-container .col-container span.icon { + display: block; + position: absolute; + width: 90px; + height: 90px; + top: 20%; + left: -45px; + } +} diff --git a/_src/blocks/dual-teaser/dual-teaser.js b/_src/blocks/dual-teaser/dual-teaser.js new file mode 100644 index 000000000..ea070b10a --- /dev/null +++ b/_src/blocks/dual-teaser/dual-teaser.js @@ -0,0 +1,34 @@ +import { decorateIcons } from '../../scripts/lib-franklin.js'; + +export default async function decorate(block) { + const cols = [...block.children[1].children]; + const middleSvgIcon = block.children[0].querySelector('span'); + + block.innerHTML = ` +
+ ${cols.map((col, idx) => { + const pictureEl = col.querySelector('picture'); + const richTextEls = [...col.children]; + richTextEls.shift(); + const [titleEl, subtitleEl, buttonEl] = richTextEls; + + return ` +
+
+
+ ${pictureEl.outerHTML} +
+
+ ${titleEl.outerHTML} +
${subtitleEl.innerHTML}
+ ${buttonEl.outerHTML} +
+
+ ${idx === 1 ? middleSvgIcon.outerHTML : ''} +
+ `; + }).join('')} + `; + + decorateIcons(block); +} diff --git a/solutions/blocks/embed/embed.css b/_src/blocks/embed/embed.css similarity index 100% rename from solutions/blocks/embed/embed.css rename to _src/blocks/embed/embed.css diff --git a/solutions/blocks/embed/embed.js b/_src/blocks/embed/embed.js similarity index 100% rename from solutions/blocks/embed/embed.js rename to _src/blocks/embed/embed.js diff --git a/solutions/blocks/features/features.css b/_src/blocks/features/features.css similarity index 97% rename from solutions/blocks/features/features.css rename to _src/blocks/features/features.css index 065dc557c..3c6946251 100644 --- a/solutions/blocks/features/features.css +++ b/_src/blocks/features/features.css @@ -90,8 +90,8 @@ width: 14px; height: 8px; margin: 0 3px; - background: url("/solutions/icons/tabs_arrow.svg") no-repeat; - background-size: 100%;; + background: url("/_src/icons/tabs_arrow.svg") no-repeat; + background-size: 100%; transform: rotate(180deg); transition: all .3s linear; } diff --git a/solutions/blocks/features/features.js b/_src/blocks/features/features.js similarity index 100% rename from solutions/blocks/features/features.js rename to _src/blocks/features/features.js diff --git a/_src/blocks/footer/footer.css b/_src/blocks/footer/footer.css new file mode 100644 index 000000000..402b2f809 --- /dev/null +++ b/_src/blocks/footer/footer.css @@ -0,0 +1,768 @@ +footer.landingpage { + background: #006EFF; + color: white; + font-weight: 400; + +a:any-link { + color: white; + text-decoration: none; +} + +img { + width: 300px; + height: auto; + margin-bottom: 10px; +} +} + +footer.default { + padding: 2.5rem 0 1.5rem; + background-color: #000; + font-size: var(--body-font-size-s); +} + +footer.default .footer a { + color: #fff; + cursor: pointer; + outline: 0; + font-family: var(--body-font-family),sans-serif; +} + +footer.default .footer ul { + list-style: none; + padding: 0 1.25rem; + margin: 0; + font-family: var(--body-font-family), sans-serif; +} + +footer.default .footer ul li { + font-size: var(--body-font-size-s); + line-height: 1.63; + font-family: var(--body-font-family),sans-serif; + margin: 0 0 0.4375rem; + padding-left: 0; +} + +footer.default .footer ul li a { + font: normal normal var(--font-weight-boldest) 10px/30px var(--body-font-family); +} + +footer.default .footer p { + margin: 0; + padding: 0 1.25rem; +} + +footer.default .footer .deactivated a { + color: #999 !important; + cursor: auto; + pointer-events: none; +} + +footer.default .footer a:hover { + text-decoration: underline; +} + +footer.default .footer .deactivated::before { + content: "•"; + color: #999; + font-weight: var(--font-weight-boldest); + display: inline-block; + width: 1rem; + position: absolute; + z-index: 1; + left: -1rem; + top: 0.125rem; +} + +footer.default .footer > div { + display: grid; + margin: 0 auto; + max-width: 81.25rem; +} + +footer.default .footer > div div { + margin: 0; + padding: 0; + border-bottom: 0.0625rem solid #9098a3; +} + +footer.default .footer > div p { + text-align: left; + font: normal normal var(--font-weight-boldest) 13px/24px var(--body-font-family); + letter-spacing: 0; + color: #9098a3; + opacity: 1; + position: relative; + margin: 0; + transition: transform .5s ease-in-out; + cursor: pointer; + padding: 0.625rem 1.25rem; +} + +footer.default .footer > div > :nth-child(1) > p { + width: 100%; + margin-bottom: 1.875rem; + display: flex; + overflow: hidden; + border: none; +} + +footer.default .footer > div > :nth-child(1) > p a { + height: 100%; +} + +footer.default .footer > div > :nth-child(1) > p picture { + width: 11.875rem; + height: 1.9375rem; + overflow: hidden; + display: flex; +} + +footer.default .footer > div > :nth-child(1) > p a img { + height: 1.5rem; + width: auto; + object-fit: contain; +} + +footer.default .footer > div > :nth-child(1) > ul { + margin: 0; + display: block; + column-count: 2; + list-style-type: none; + padding-bottom: 1.875rem; +} + +footer.default .footer > div > :nth-child(1) > ul li { + padding: 0; + margin: 0 0 0.4375rem; +} + +footer.default .footer > div > :nth-child(1) > ul li a { + text-align: left; + letter-spacing: .78pt; + text-transform: uppercase; + font: normal normal var(--font-weight-boldest) 11px/30px var(--body-font-family); +} + +footer.default .footer > div > :nth-child(2) { + order: 4; + margin-top: 0.6875rem; + margin-bottom: 1.5rem; + border: none; +} + +footer.default .footer > div > :nth-child(3) { + order: 2; + padding-bottom: 0.625rem; +} + +footer.default .footer > div > :nth-child(4) { + order: 3; + padding-bottom: 0.625rem; +} + +footer.default .footer > div > :nth-child(5) { + order: 5; + padding: 0; + border-bottom-width: 1px; + border-style: solid; + border-color: rgb(144 152 163); + margin-bottom: 1.5rem; +} + +footer.default .footer > div > :nth-child(6) { + order: 6; + border: none; +} + +footer.default .footer > div > :nth-child(3) > p::before, +footer.default .footer > div > :nth-child(4) > p::before { + transform: rotate(45deg); + border-color: #fff; + border-style: solid; + border-width: 0 0.1875rem 0.1875rem 0; + content: ""; + width: 0.5rem; + height: 0.5rem; + display: inline-block; + position: absolute; + right: 1.25rem; + top: 0.75rem; + left: auto; + transition: transform .5s ease-in-out; +} + +footer.default .footer > div > :nth-child(3) > ul, +footer.default .footer > div > :nth-child(4) > ul { + width: 100%; + max-height: 125rem; + margin-bottom: 0.625rem; + transition: transform .5s ease-in-out; +} + +footer.default .footer > div > :nth-child(3) > ul li, +footer.default .footer > div > :nth-child(4) > ul li { + margin: 0 0 0.625rem; + padding-left: 0; +} + +footer.default .footer > div > :nth-child(3) > ul li > a, +footer.default .footer > div > :nth-child(4) > ul li > a { + font: normal normal var(--font-weight-bold) 10px/30px var(--body-font-family); + letter-spacing: 0; + opacity: 1; +} + +footer.default .footer > div > :nth-child(2) > ul { + column-count: 2; + padding: 0 1.25rem 0.375rem; + margin-top: 0.6875rem; +} + +footer.default .footer > div > :nth-child(3) > p + ul, +footer.default .footer > div > :nth-child(4) > p + ul { + display: none; + max-height: 0; + overflow: hidden; + transition: max-height 0.5s ease-in-out; +} + +footer.default .footer > div > :nth-child(3) > p + ul.visible, +footer.default .footer > div > :nth-child(4) > p + ul.visible { + display: block; +} + +footer.default .footer > div > :nth-child(3) > p + ul.open, +footer.default .footer > div > :nth-child(4) > p + ul.open { + max-height: 400px; +} + +footer.default .footer > div > :nth-child(3) > p, +footer.default .footer > div > :nth-child(4) > p { + padding-bottom: 0; +} + +footer.default .footer > div > :nth-child(3) > p.active, +footer.default .footer > div > :nth-child(4) > p.active { + padding-bottom: 0.625rem; +} + +footer.default .footer > div > :nth-child(4) > p + ul { + display: none; +} + +footer.default .footer > div > :nth-child(3) > p.active + ul, +footer.default .footer > div > :nth-child(4) > p.active + ul { + display: inline-block; +} + +footer.default .footer > div > :nth-child(4) > p.active + ul { + column-count: 2; +} + +footer.default .footer > div > :nth-child(3) > p.active::before, +footer.default .footer > div > :nth-child(4) > p.active::before { + transform: rotate(225deg); + top: 1.0625rem; +} + +footer.default .footer > div > :nth-child(2) > p { + padding: 0 1.25rem; + margin-bottom: 1rem; +} + +footer.default .footer > div > :nth-child(5) > p { + font-size: var(--body-font-size-m); + padding: 0 1.375rem 1.5rem; + color: rgb(255 255 255); + letter-spacing: 0; + line-height: 1.5rem; + font-weight: var(--font-weight-boldest); + font-family: "IBM Plex Sans" ,sans-serif; +} + +footer.default .footer > div > :nth-child(6) > p { + font: normal normal normal 10px/13px var(--body-font-family); + width: 100%; + max-width: 100%; + margin-top: 1rem; + margin-bottom: 1.625rem; + position: relative; + text-align: left!important; + letter-spacing: 0; + color: #9098a3; + opacity: 1; + line-height: 1.14!important; + padding: 0 1.25rem; +} + +footer.default .footer > div > :nth-child(6) > ul li { + display: block; + margin-bottom: 0.625rem; + font: normal normal var(--font-weight-regular) 10px/30px var(--body-font-family); + width: 100%; + line-height: 1; + font-size: var(--body-font-size-xxs); +} + +footer.default .footer > div > :nth-child(6) > ul li > a { + display: inline-block; + font: normal normal var(--font-weight-bold) 10px/30px var(--body-font-family); +} + +@media(min-width: 480px) { + footer.default .footer > div > :nth-child(6) > ul li > a { + font: normal normal var(--font-weight-bold) 11px/30px var(--body-font-family); + } + + footer.default .footer > div > :nth-child(6) > p { + font: normal normal normal 11px/13px var(--body-font-family); + } +} + +@media(min-width: 767px) { /* tablet */ + footer.default { + padding: 3.625rem 0 2.6875rem; + } + + footer.default .footer > div > :nth-child(1) > ul li > a { + font: normal normal var(--font-weight-boldest) 9pt/30px var(--body-font-family); + } + + footer.default .footer > div > :nth-child(6) > ul li > a { + font: normal normal var(--font-weight-bold) 9pt/30px var(--body-font-family); + } + + footer.default .footer > div > :nth-child(6) > p { + font: normal normal normal 9pt/13px var(--body-font-family); + } + + footer.landingpage img { + width: 400px; + } +} + +@media(min-width: 990px) { /* desktop */ + footer.default .footer .deactivated { + position: relative; + } + + footer.default .footer > div { + grid-template-columns: [first-col] 25% [second-col] 75%; + } + + footer.default .footer > div div { + border: none; + } + + footer.default .footer > div p { + pointer-events: none; + } + + footer.default .footer > div > :nth-child(1) { + order: 1; + display: flex; + justify-content: center; + flex-flow: row wrap; + padding: 0 3.125rem; + margin-bottom: 4.0625rem; + grid-column: first-col / span 2; + } + + footer.default .footer > div > :nth-child(1) > p { + max-width: 25%; + padding: 0; + pointer-events: visible; + } + + footer.default .footer > div > :nth-child(1) > p a img { + height: 1.75rem; + } + + footer.default .footer > div > :nth-child(1) > ul { + width: 66%; + margin-left: 9%; + display: inline-block; + vertical-align: top; + border-bottom: none; + column-count: 1; + list-style-type: none; + padding: 0; + } + + footer.default .footer > div > :nth-child(1) > ul li > a { + font: normal normal var(--font-weight-boldest) 13px/30px var(--body-font-family); + } + + footer.default .footer > div > :nth-child(2) { + order: 2; + margin-top: 0; + grid-column: first-col / span 1; + padding-left: 3.125rem; + margin-bottom: 0; + } + + footer.default .footer > div > :nth-child(2) > p, + footer.default .footer > div > :nth-child(3) > p, + footer.default .footer > div > :nth-child(4) > p { + padding: 0; + font: normal normal var(--font-weight-boldest) 13px/24px var(--body-font-family); + letter-spacing: 0; + color: #9098a3; + opacity: 1; + border-bottom: 1px solid #3a4350; + padding-bottom: 0.9375rem; + text-transform: none; + width: 100%; + margin-bottom: 0; + } + + footer.default .footer > div > :nth-child(3) ul, + footer.default .footer > div > :nth-child(4) ul { + display: block !important; + margin-bottom: 0; + } + + footer.default .footer > div > :nth-child(3) > ul { + padding: 0; + display: grid; + grid-template-columns: 1fr; + margin-top: 0.9375rem; + list-style: none; + } + + footer.default .footer > div > :nth-child(3) > p { + width: 95%; + } + + footer.default .footer > div > :nth-child(2) > ul { + padding: 0; + column-count: 1; + display: grid; + grid-template-columns: 1fr; + margin-top: 0.9375rem; + list-style: none; + } + + footer.default .footer > div > :nth-child(3) ul { + column-count: 2; + } + + footer.default .footer > div > :nth-child(2) > ul li, + footer.default .footer > div > :nth-child(4) > ul li { + margin-bottom: 0.5rem; + width: 100%; + padding: 0; + } + + footer.default .footer > div > :nth-child(2) > ul li > a, + footer.default .footer > div > :nth-child(3) > ul li > a, + footer.default .footer > div > :nth-child(4) > ul li > a { + font: normal normal var(--font-weight-bold) 13px/30px var(--body-font-family); + display: inline-block; + position: relative; + } + + footer.default .footer > div > :nth-child(3) { + order: 3; + grid-column: second-col / span 1; + margin-left: 14%; + padding-bottom: 0; + } + + footer.default .footer > div > :nth-child(3) > p::before, + footer.default .footer > div > :nth-child(4) > p::before { + display: none; + } + + footer.default .footer > div > :nth-child(4) ul { + column-count: 3; + padding: 0; + margin-top: 0.9375rem; + } + + footer.default .footer > div > :nth-child(4) { + order: 4; + grid-column: first-col / span 2; + margin-top: 4.0625rem; + padding: 0 3.125rem; + } + + footer.default .footer > div > :nth-child(5) { + order: 5; + grid-column: first-col / span 2; + margin-top: 2.5rem; + border: none; + padding: 0 3.125rem; + margin-bottom: 0; + padding-bottom: 1rem; + } + + footer.default .footer > div > :nth-child(5) > p { + padding: 0; + } + + footer.default .footer > div > :nth-child(6) { + order: 6; + grid-column: first-col / span 2; + padding: 0 3.125rem; + } + + footer.default .footer > div > :nth-child(6) > ul { + border-top: 1px solid #3a4350; + padding: 1rem 0 0; + display: flex; + } + + footer.default .footer > div > :nth-child(6) > ul li { + display: inline-block; + list-style: none; + padding: 0; + margin: 0; + position: relative; + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-regular); + line-height: 1.14; + width: auto; + } + + footer.default .footer > div > :nth-child(6) > ul li > a { + font: normal normal normal 13px/18px var(--body-font-family); + margin-right: 0.625rem; + padding-right: 1.25rem; + position: relative; + } + + footer.default .footer > div > :nth-child(6) > ul li > a::after { + content: ""; + position: absolute; + top: 0.125rem; + right: 0.1875rem; + width: 0.125rem; + height: 1rem; + background-color: #fff; + } + + footer.default .footer > div > :nth-child(6) > p { + padding: 0; + font: normal normal normal 13px/18px var(--body-font-family); + margin-top: 0.875rem; + margin-bottom: 0; + } + + footer.default .footer > div > :nth-child(3) > p + ul, + footer.default .footer > div > :nth-child(4) > p + ul { + overflow: visible; + max-height: 400px; + } + + footer.default .footer > div > :nth-child(4) > p.active + ul { + column-count: 3; + } +} + +#footer-ferrari { + background-color: #000; +} + +#footer-ferrari .section:nth-of-type(1) p { + width: 40%; +} + +#footer-ferrari ul { + margin-left: 0; + padding-left: 0; +} + +#footer-ferrari .section:nth-of-type(1) ul { + width: 60%; + display: flex; + justify-content: space-between; + padding-top: 0; + margin-top: 0; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) li:not(:first-of-type) { + float: left; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) li:not(:first-of-type) img { + width: 40px; + margin-right: 12px; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) li:first-of-type { + width: 100%; +} + +#footer-ferrari .section:nth-of-type(3) strong, +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) strong { + width: 100%; + margin-bottom: 10px; + font-size: 22px; + line-height: 27px; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) li:first-of-type strong { + width: 100%; + display: block; + font-size: 14px; + line-height: 1.71; + letter-spacing: 1.12px; + color: #fff; + padding-bottom: 13px; + border-bottom: 2px solid white; + margin-bottom: 25px; +} + +#footer-ferrari .section:nth-of-type(4) ul li a { + font-size: 14px; + font-weight: normal; + line-height: 1.14; + color: #fff; + position: relative; + margin-right: 10px; + padding-right: 20px; + margin-bottom: 10px; + border-right: 0 none; + display: inline-block; +} + +#footer-ferrari .section:nth-of-type(4) ul li:last-of-type a { + border-right: 0 none; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) li:not(:first-of-type) a { + font-size: 16px; + font-weight: 500; + line-height: 1.5; +} + +#footer-ferrari .section:nth-of-type(3) p { + border-bottom: 0 none; + margin-top: 1em; + padding-top: 10px; + font-size: 22px; + line-height: 27px; +} + +#footer-ferrari .section:nth-of-type(4) p { + text-align: right; + line-height: 17px; +} + +#footer-ferrari .section:nth-of-type(4) ul p { + font-size: 14px; + line-height: 1.14; +} + +#footer-ferrari .section:nth-of-type(1) { + display: none; +} + +#footer-ferrari .section:nth-of-type(4) ul { + width: 60%; + display: flex; + flex-direction: column; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) { + width: 100%; + margin-top: 0; +} + +#footer-ferrari .section:nth-of-type(4) { + padding-top: 0; +} + +#footer-ferrari .section:nth-of-type(4) div { + display: flex; + align-items: self-end; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) { + display: none; +} + +@media (min-width: 768px) { + footer.landingpage { + padding: 50px 0; + + .default-content-wrapper { + display: flex; + justify-content: space-between; + } + + p strong { + font-size: 32px; + font-weight: bold; + color: white; + } + } +} + +@media (min-width: 992px) { + #footer-ferrari .section:nth-of-type(1) { + display: block; + } + + #footer-ferrari .section:nth-of-type(4) ul { + display: flex; + flex-direction: row; + margin-top: 0; + margin-bottom: 0; + } + + + #footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) { + width: 40%; + } + + #footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) { + display: block; + width: 60%; + } + + #footer-ferrari .section:nth-of-type(3) p { + width: 100%; + border-bottom: 2px solid white; + margin-top: 100px; + padding-top: 10px; + line-height: 2; + } + + #footer-ferrari .section:nth-of-type(3) strong { + font-size: 31px; + } + + #footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) strong { + width: 120px; + display: block; + margin-bottom: 28px; + color: #fff; + font-size: 40px; + line-height: 45px; + } + + #footer-ferrari ul li { + list-style-type: none; + padding-left: 0; + } + + #footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) li:not(:first-of-type) { + width: 50%; + float: left; + margin-top: 0; + margin-bottom: 25px; + } +} + +@media(min-width: 1600px) { /* large desktop */ + footer.default .footer > div { + width: 100%; + margin: 0 auto; + padding: 0 1.25rem; + max-width: 83.25rem; + position: relative; + } +} diff --git a/_src/blocks/footer/footer.js b/_src/blocks/footer/footer.js new file mode 100644 index 000000000..09aad3479 --- /dev/null +++ b/_src/blocks/footer/footer.js @@ -0,0 +1,157 @@ +import { decorateIcons, getMetadata, loadBlocks } from '../../scripts/lib-franklin.js'; +import { adobeMcAppendVisitorId } from '../../scripts/utils/utils.js'; +import { decorateMain } from '../../scripts/scripts.js'; + +function wrapImgsInLinks(container) { + const pictures = container.querySelectorAll('picture'); + pictures.forEach((pic) => { + const link = pic.nextElementSibling; + if (link && link.tagName === 'A' && link.href) { + link.innerHTML = pic.outerHTML; + pic.replaceWith(link); + } + }); +} + +function onFooterElementClick(evt) { + const header = evt.target; + const ul = header.nextElementSibling; + header.classList.toggle('active'); + + if (ul.classList.contains('open')) { + ul.addEventListener('transitionend', function callback() { + if (!ul.classList.contains('open')) { // Ensure the ul is still closed + ul.classList.remove('visible'); + } + ul.removeEventListener('transitionend', callback); + }); + ul.classList.remove('open'); + } else { + ul.classList.add('visible'); + setTimeout(() => { + ul.classList.add('open'); + }, 10); // slight delay to allow the browser to apply the "visible" class first + } +} + +function disableSelectedCountry(container) { + const listOfCountries = container.querySelectorAll('li'); + listOfCountries.forEach((countryLanguage) => { + if (countryLanguage.innerHTML.includes('selected')) { + countryLanguage.classList.add('deactivated'); + countryLanguage.innerHTML = countryLanguage.innerHTML.replace('(selected)', ''); + } + }); +} + +function setupPrivacyButton(container) { + const privacyButton = container.querySelector('a[href="#privacybutton"]'); + if (privacyButton) { + privacyButton.href = '#'; + privacyButton.addEventListener('click', (e) => { + e.preventDefault(); + if (window.UC_UI) { + window.UC_UI.showSecondLayer(); + } + }); + } +} + +async function runDefaultFooterLogic(block) { + // fetch footer content + const footerPath = getMetadata('footer') || '/footer'; + const resp = await fetch(`${footerPath}.plain.html`, window.location.pathname.endsWith('/footer') ? { cache: 'reload' } : {}); + + if (resp.ok) { + const html = await resp.text(); + + // decorate footer DOM + const footer = document.createElement('div'); + footer.innerHTML = html; + + wrapImgsInLinks(footer); + + const sectionHeaders = footer.querySelectorAll('div > div > p'); + sectionHeaders[2].addEventListener('click', onFooterElementClick); + sectionHeaders[3].addEventListener('click', onFooterElementClick); + + const sectionsData = footer.querySelectorAll('div > div > ul'); + disableSelectedCountry(sectionsData[3]); + + decorateIcons(footer); + block.append(footer); + + setupPrivacyButton(footer); + + adobeMcAppendVisitorId('footer'); + } +} + +async function runLandingpageLogic(block) { + const footerPath = getMetadata('footer') || '/footer'; + const resp = await fetch(`${footerPath}.plain.html`); + + const fragment = document.createElement('main'); + if (resp.ok) { + fragment.innerHTML = await resp.text(); + decorateMain(fragment); + await loadBlocks(fragment); + } + const footer = block.closest('.footer-wrapper'); + + if (window.location.href.indexOf('scuderiaferrari') !== -1 || window.location.href.indexOf('spurs') !== -1) { + block.closest('.footer-wrapper').id = 'footer-ferrari'; + } + + if (fragment) { + const fragmentSections = fragment.querySelectorAll(':scope .section'); + if (fragmentSections) { + footer.replaceChildren(...fragmentSections); + } + } + + const replacements = [ + [/\[year\]/g, new Date().getFullYear()], + [/>Twitter Bitdefenderx<'], + [/>Linkedin Bitdefenderlinkedin<'], + [/>Facebook Bitdefenderfacebook<'], + [/>Youtube Bitdefenderyoutube<'], + ]; + + replacements.forEach(([pattern, replacement]) => { + footer.innerHTML = footer.innerHTML.replace(pattern, replacement); + }); + + setupPrivacyButton(footer); + + adobeMcAppendVisitorId('footer'); +} + +/** + * applies footer factory based on footer variation + * @param {String} footerMetadata The footer variation: landingpage' or none + * @param {Element} footer The footer element + */ +function applyFooterFactorySetup(footerMetadata, block) { + switch (footerMetadata) { + case 'landingpage': + runLandingpageLogic(block); + break; + default: + runDefaultFooterLogic(block); + break; + } +} + +/** + * loads and decorates the footer + * @param {Element} block The footer block element + */ +export default async function decorate(block) { + const footerMetadata = getMetadata('footer-type'); + block.parentNode.classList.add(footerMetadata || 'default'); + + block.textContent = ''; + + applyFooterFactorySetup(footerMetadata, block); +} diff --git a/_src/blocks/form-blog/form-blog.css b/_src/blocks/form-blog/form-blog.css new file mode 100644 index 000000000..0c949e408 --- /dev/null +++ b/_src/blocks/form-blog/form-blog.css @@ -0,0 +1,217 @@ +.form-blog { + --input-border: #d6d6d6; + } + + .form-blog-wrapper { + width: 100%; + margin: 0 auto; + max-width: var(--body-max-width); + padding: 0 var(--body-padding); + position: relative; + } + + .form-blog > div:first-child { + display: none; + } + + .form-blog input[type="email"] { + border: 1px solid var(--input-border); + border-radius: 5px; + transition: all 0.3s ease-in-out; + font-size: var(--body-font-size-s); + line-height: 50px; + padding: 0 15px; + margin-bottom: 15px; + width: 100%; + } + + .form-blog input[type="text"] { + border: 1px solid var(--input-border); + border-radius: 5px; + transition: all 0.3s ease-in-out; + font-size: var(--body-font-size-s); + line-height: 50px; + padding: 0 15px; + margin-bottom: 15px; + width: 100%; + } + + .checkbox { + display: flex; + align-items: flex-start; + color: var(--checkbox-label); + font-size: var(--body-font-size-xs); + margin: 15px 0; + } + + .checkbox input[type="checkbox"] { + margin: 5px 10px; + width: 25px; + height: auto; + zoom: 1.25; + + @media (min-width: 768px) { + zoom: 1; + } + } + + input[type="submit"] { + width: 100%; + justify-content: center; + } + + input[type="submit"]:disabled { + opacity: 0.5; + cursor: unset; + } + + input[type="submit"]:disabled::after { + display: none; + } + + input[type="submit"].disabled:hover .button-text { + transform: none; + } + + .form-blog-container > .default-content-wrapper:nth-child(3) { + display: flex; + justify-content: center; + } + + .form-blog-container > .default-content-wrapper:nth-child(3) > p strong { + color: var( --checkbox-label); + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-bold); + } + + + .form-blog-container input[type="submit"] { + font-family: var(--body-font-family); + font-size: var(--body-font-size-s); + font-style: normal; + font-weight: var(--font-weight-bold); + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: var(--button-link-color); + background-color: var(--button-background-color); + border: 2px solid var(--button-background-color); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + } + + .form-blog-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1300px; + --section-desktop-padding: 20px; + --section-large-desktop-max-width: 1332px; + --section-large-desktop-padding: 50px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + } + +/* stylelint-disable-next-line no-duplicate-selectors */ +.form-blog-container{ + .form-blog-wrapper { + box-sizing: border-box; + + .form-blog.blog-template { + box-shadow: 0 5px 15px 5px rgb(0 0 0 / 10%); + max-width: 390px; + padding: 15px; + box-sizing: border-box; + + input[type="email"] { + box-sizing: border-box;; + } + + input[type="text"] { + box-sizing: border-box;; + } + + > div:first-child { + display: block; + + h2 { + font-size: 22px; + font-weight: bold; + } + + p { + font-size: 16px; + } + + p.button-container { + display: none; + } + } + } + } +} \ No newline at end of file diff --git a/_src/blocks/form-blog/form-blog.js b/_src/blocks/form-blog/form-blog.js new file mode 100644 index 000000000..1a8474cdd --- /dev/null +++ b/_src/blocks/form-blog/form-blog.js @@ -0,0 +1,168 @@ +import Cookie from '../../scripts/utils/cookie.js'; + +function onChange(form) { + // Targeting the anchor inside .button-container + const submitButton = form.querySelector('input[type="submit"]'); + const emailInput = form.querySelector('input[type="email"]'); + + const allCheckboxesChecked = [...form.querySelectorAll('input[type="checkbox"]:required')].every((checkbox) => checkbox.checked); + const emailPopulated = emailInput.value.trim() !== ''; + + submitButton.disabled = !((allCheckboxesChecked && emailPopulated)); +} + +async function hashEmail(email) { + const encoder = new TextEncoder(); + const data = encoder.encode(email); + const hashBuffer = await crypto.subtle.digest('SHA-256', data); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join(''); + return hashHex; +} + +async function handleSubmitNewsletter(e, form, flow, successMessage, failMessage, formType = 'newsletter') { + e.preventDefault(); + const formData = new FormData(form); + const email = formData.get('email'); + const name = formData.get('name'); + const firstName = name.split(' ')[0]; + const lastName = name.split(' ')[1] || ''; + const update = formData.get('checkbox'); + + const jsonObject = { + email, + flow, + first_name: firstName, + last_name: lastName, + update, + }; + + const response = await fetch('https://www.bitdefender.com/site/Store/offerSubscribe', { + method: 'POST', + body: JSON.stringify(jsonObject), + }); + const formParent = form.parentElement; + if (response.ok) { + const hashedEmail = await hashEmail(email); + window.adobeDataLayer = window.adobeDataLayer || []; + window.adobeDataLayer.push({ + event: 'form completed', + user: { + form: formType, + formID: hashedEmail, + }, + }); + + formParent.innerHTML = ''; + formParent.appendChild(successMessage); + + Cookie.set('newsLetterIntentShown', '1'); + } else { + formParent.innerHTML = ''; + formParent.appendChild(failMessage); + } +} + +function parseHTML(html) { + // Regular expressions to match text inside curly braces and square brackets + const curlyRegex = /{{(.*?)}}/g; + const squareRegex = /\[\[(.*?)\]\]/g; + + const insideCurlyBrackets = []; + const insideSquareBrackets = []; + + // Match all occurrences of the curly braces regex + let match; + // eslint-disable-next-line no-cond-assign + while ((match = curlyRegex.exec(html)) !== null) { + insideCurlyBrackets.push(match[1].trim()); + } + + // Match all occurrences of the square brackets regex + // eslint-disable-next-line no-cond-assign + while ((match = squareRegex.exec(html)) !== null) { + insideSquareBrackets.push(match[1].trim()); + } + + return { + insideCurlyBrackets, + insideSquareBrackets, + }; +} + +// Function to create the form +async function createForm(types, labels, flow, successMessage, failMessage, formType) { + const form = document.createElement('form'); + form.setAttribute('method', 'post'); + + for (let i = 0; i < types.length; i += 1) { + const type = types[i].toLowerCase(); + const input = document.createElement('input'); + input.id = `form-${i}-${type}`; + input.addEventListener('change', () => onChange(form)); + input.addEventListener('input', () => onChange(form)); + + if (type === 'name') { + input.setAttribute('type', 'text'); + } else { + input.setAttribute('type', type); + } + + input.setAttribute('name', type); + input.setAttribute('placeholder', labels[i]); + input.setAttribute('required', ''); + input.setAttribute('aria-required', 'true'); + + form.append(input); + if (type === 'submit') { + input.classList.add('disabled'); + input.disabled = true; + } + + if (type === 'checkbox') { + const div = document.createElement('div'); + div.classList.add('checkbox'); + + const label = document.createElement('label'); + label.setAttribute('for', `form-${i}-${type}`); + label.innerHTML = labels[i]; + input.before(div); + div.append(input, label); + } + } + + form.addEventListener('submit', (e) => handleSubmitNewsletter(e, form, flow, successMessage, failMessage, formType)); + return form; +} + +export default async function decorate(block, options) { + const { + template, flow, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const formDataHTML = block.children[1]; + const successMessage = block.children[2].children[1]; + const failMessage = block.children[3].children[1]; + const formData = parseHTML(formDataHTML.innerHTML); + const [types, labels] = [formData.insideCurlyBrackets, formData.insideSquareBrackets]; + const form = await createForm(types, labels, flow, successMessage, failMessage, options.formType); + if (form) block.append(form); + block.children[1].innerHTML = ''; + block.children[2].innerHTML = ''; + block.children[3].innerHTML = ''; + if (template === 'blog') { + block.classList.add('blog-template'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/solutions/blocks/form/form.css b/_src/blocks/form/form.css similarity index 100% rename from solutions/blocks/form/form.css rename to _src/blocks/form/form.css diff --git a/_src/blocks/form/form.js b/_src/blocks/form/form.js new file mode 100644 index 000000000..0ed943ace --- /dev/null +++ b/_src/blocks/form/form.js @@ -0,0 +1,234 @@ +async function fetchData(url) { + const resp = await fetch(url); + const json = await resp.json(); + return json.data; +} + +/** + * + * @param {String} email + * @returns {Boolean} wether the email passed is valid or not + */ +const validateEmail = (email) => { + const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return re.test(email.toLowerCase()); +}; + +/** + * + * @param {HTMLInputElement} inputElement + * @returns {Boolean} validation status of the field + */ +const checkInputValue = (inputElement) => { + // real time field validation for the email field (For DIP only) + switch (inputElement.type) { + case 'email': + // validate the email inputs using the validation function if there are error fields + if (!validateEmail(inputElement.value)) { + return false; + } + + break; + case 'checkbox': + if (!inputElement.checked && inputElement.required) { + return false; + } + + break; + default: + break; + } + + return true; +}; + +/** + * + * @param {HTMLInputElement} inputElement + */ +const displayInputError = (inputElement) => { + const inputElementError = inputElement.parentElement.querySelector('.input-error-field'); + if (inputElementError) { + inputElementError.classList.remove('global-display-none'); + } +}; + +/** + * + * @param {HTMLInputElement} inputElement + */ +const hideInputError = (inputElement) => { + const inputElementError = inputElement.parentElement.querySelector('.input-error-field'); + if (inputElementError) { + inputElementError.classList.add('global-display-none'); + } +}; + +/** + * + * @param {HTMLFormElement} form + * set the onChange function for all the form inputs + */ +function checkFormValues(form) { + const submitButton = form.querySelector('input[type="submit"]'); + + // Targeting the anchor inside .button-container + const allInputFields = form.querySelectorAll('input:not([type="hidden"])'); + let disabledStatus = false; + allInputFields.forEach((inputField) => { + if (!disabledStatus && !checkInputValue(inputField)) { + disabledStatus = true; + } + }); + + submitButton.disabled = disabledStatus; +} + +async function handleSubmit(e, handler) { + e.preventDefault(); + try { + const mod = await import(handler); + if (mod.default) await mod.default(e); + } catch (error) { + // eslint-disable-next-line no-console + console.log('failed to load module for lib-identity-exposed-onsubmit', error); + } +} + +/** + * + * @param {HTMLInputElement} input the input to be adde inside the div wrapper + * @param {HTMLDivElement} newDivParent the div wrapper to hold the input + */ +const wrapInputInsideDiv = (input, newDivParent) => { + const label = input.nextElementSibling; + + // if the input has a label, also add it inside the wrapper + if (label && label.tagName === 'LABEL') { + input.before(newDivParent); + newDivParent.append(input, label); + } else { + input.after(newDivParent); + newDivParent.append(input); + } +}; + +// Debounce function to improve performance of input calls +/** + * + * @param {Function} func + * @param {Number} wait + * @param {Boolean} immediate + */ +const debounce = (func, wait, immediate) => { + let timeout; + + return (...args) => { + const later = () => { + timeout = null; + if (!immediate) { + func(args); + } + }; + + const callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) { + func(args); + } + }; +}; + +/** + * + * @param {HTMLInputElement} input + * @param {HTMLFormElement} form + * add the validations which get triggered whenever an input is filled with data + */ +const addInputValidation = (input, form) => { + if (input.dataset.containsErrorField && checkInputValue(input)) { + hideInputError(input); + } else if (input.dataset.containsErrorField) { + displayInputError(input); + } + + checkFormValues(form); +}; + +/** + * + * @param {string} formURL url to form html + * @returns {Promise} returns the form + */ +export async function createForm(formURL) { + const { pathname, search } = new URL(formURL); + const data = await fetchData(`${pathname}${search}`); + const form = document.createElement('form'); + + form.setAttribute('method', 'post'); + + data.forEach((field, index) => { + const input = document.createElement('input'); + input.id = `form-${index}-${field.Field}`; + input.setAttribute('type', field.Type); + input.setAttribute('name', field.Field); + input.setAttribute('placeholder', field.Default); + input.setAttribute('value', field.Value); + input.setAttribute('data-contains-error-field', Boolean(field.Error)); + + // add event listeners to the fields + input.addEventListener('input', debounce(() => addInputValidation(input, form), 100, false)); + + if (field.Required && field.Required.toLowerCase() === 'true') { + input.setAttribute('required', ''); + input.setAttribute('aria-required', 'true'); + } + + form.append(input); + + // Only create a label if the field.Label is not null + if (field.Label) { + const label = document.createElement('label'); + label.setAttribute('for', input.id); + label.textContent = field.Label; + form.append(label); + } + + if (field.Type === 'submit') { + input.classList.add('disabled'); + input.disabled = true; + } + + if (field.Field === 'handler') { + form.addEventListener('submit', (e) => handleSubmit(e, field.Value)); + } + + if (field.Type === 'checkbox') { + const newDivWrapper = document.createElement('div'); + newDivWrapper.classList.add('checkbox'); + + wrapInputInsideDiv(input, newDivWrapper); + } + + if (field.Error) { + const newDivWrapper = document.createElement('div'); + newDivWrapper.classList.add('input-container-with-error'); + + // add the error field + const errorField = document.createElement('p'); + errorField.classList.add('input-error-field', 'global-display-none'); + errorField.textContent = field.Error; + newDivWrapper.appendChild(errorField); + input.classList.add('input-with-error-field'); + + wrapInputInsideDiv(input, newDivWrapper); + } + }); + return form; +} + +export default async function decorate(block) { + const form = await createForm(block.textContent.trim()); + if (form) block.append(form); +} diff --git a/_src/blocks/four-cards/four-cards.css b/_src/blocks/four-cards/four-cards.css new file mode 100644 index 000000000..3129852f1 --- /dev/null +++ b/_src/blocks/four-cards/four-cards.css @@ -0,0 +1,311 @@ +.four-cards-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1300px; + --section-desktop-padding: 20px; + --section-large-desktop-max-width: 1332px; + --section-large-desktop-padding: 50px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); +} + +@media (min-width: 992px) { /* desktop */ + .four-cards-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +@media (min-width: 1600px) { /* large desktop */ + .four-cards-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +.creators .title-size .default-content-wrapper p { + font-size: 24px; +} + + +.creator-cards .four-cards.block { + display: flex; + justify-content: center; +} + +.creator-cards .four-cards.block ul li strong { + font-size: 22px; +} + +.four-cards-container h3 { + font: normal normal bold 32px/37px var(--body-font-family); + text-align: center; + margin-bottom: 56px; +} + +.creator-cards.four-cards-container h3 { + font: normal normal bold 60px/69px "IBM Plex Sans", sans-serif; + text-align: center; + margin-bottom: 28px; +} + +.creator-cards.four-cards-container h4 { + font: normal normal bold 22px/24px "IBM Plex Sans", sans-serif; + text-align: left; + +} + +.four-cards-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.four-cards-container .icon svg { + width: 48px; + height: 48px; + padding-right: 2px; + fill: #fff; +} + +.four-cards > ul { + list-style: none; + margin: 0; + padding: 0; + display: grid; + grid-template-columns: 1fr; + grid-gap: 24px; +} + +.four-cards > ul > li { + display: inline-block; + background-color: #f6f6f6; + padding: 24px; + margin: 0; + border-radius: 20px; + text-align: left; + font: normal normal normal 16px/24px var(--body-font-family); +} + +.creator-cards .four-cards > ul > li { + font-size: 18px; +} + +.four-cards .default-content-wrapper { + text-align: center; +} + +.creator-cards .default-content-wrapper { + text-align: center; +} + +.creator-cards .default-content-wrapper:last-of-type { + padding-top: 0; +} + +.creator-cards .four-cards ul li div img { + height: 48px; + margin-bottom: 0; +} + +/* a/b test styles, should be deleted after */ +.four-cards-container.we-container .default-content-wrapper { + text-align: center; +} + +.four-cards-container a { + font: normal normal bold 16px/20px var(--body-font-family); + margin-top: 32px; + padding: 14px 28px; + color: #006EFF; + background: white; + border: 2px solid #006EFF; + border-radius: 10px; + display: inline-block; + position: relative; + min-width: 180px; +} + +.four-cards-container p a { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + justify-content: center; + cursor: pointer; + color: #006DFF; + background-color: transparent; + border: 2px solid #006DFF; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + transition: all .2s cubic-bezier(.4,0,.2,1); +} + +.four-cards-container p a:hover { + color: white; + background-color: #006DFF; +} + +.four-cards-container p a:active { + background-color: #0D499B; +} + +.creator-cards .default-content-wrapper a.button:any-link { + min-width: 230px; + height: 48px; + padding: 10px 10px 10px 25px; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 40px; + justify-content: center; + font: normal normal 500 18px / 24px Roboto, sans-serif; + color: white; +} + +.creator-cards .default-content-wrapper a.button:hover { + color: white; + background-color: var(--button-background-color); +} + +.creator-cards .default-content-wrapper a.button:active { + color: white; + background-color: var(--button-background-color); + border: 0; +} + +.four-cards .icon { + width: 48px; + height: 48px; + margin-bottom: 16px; +} + +@media (max-width: 991px) { /* mobile/tablet */ + .four-cards-wrapper { + padding: var(--body-padding); + } + + .four-cards > ul > li { + margin: 0; + } +} + +@media (min-width: 768px) { + .four-cards > ul { + grid-template-columns: 1fr 1fr; + grid-gap: 14px; + } +} + +@media (min-width: 992px) { + .four-cards-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .four-cards > ul { + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-gap: 14px; + } + + .creator-cards .four-cards > ul { + grid-template-columns: 300px 300px 300px; + grid-gap: 14px; + } +} + +@media (min-width: 1200px) { + .four-cards-container.we-container { + max-width: 1350px; + padding-left: 20px; + padding-right: 20px; + } + +} + +@media (max-width: 991px) { + .creators .title-size .default-content-wrapper h2 { + font-size: 31px; + } + + .creators .title-size .default-content-wrapper p { + font-size: 18px; + line-height: 1.25; + margin-bottom: 9px; + } + + .creator-cards .default-content-wrapper a.button:any-link { + margin-top: 0; + } +} diff --git a/_src/blocks/four-cards/four-cards.js b/_src/blocks/four-cards/four-cards.js new file mode 100644 index 000000000..71922ba0c --- /dev/null +++ b/_src/blocks/four-cards/four-cards.js @@ -0,0 +1,50 @@ +export default async function decorate(block, options) { + const { + // eslint-disable-next-line no-unused-vars + margintop, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + const fourCardsWrapper = block.closest('.four-cards-wrapper'); + if (fourCardsWrapper) { + fourCardsWrapper.classList.remove('four-cards-wrapper'); + } + } + + if (margintop) { + const blockParent = block.closest('.section'); + blockParent.style.marginTop = `${margintop}px`; + } + + const ul = document.createElement('ul'); + [...block.children].forEach((row) => { + const li = document.createElement('li'); + li.innerHTML = row.innerHTML; + + ul.append(li); + }); + + block.textContent = ''; + block.append(ul); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + + // decorate icons only if the component is being called from www-websites + const isInLandingPages = window.location.href.includes('www-landing-pages') || window.location.href.includes('bitdefender.com/pages'); + if (!options && !isInLandingPages) { + const { decorateIcons } = await import('../../scripts/lib-franklin.js'); + decorateIcons(block.closest('.section')); + } + + if (isInLandingPages) { + const { decorateIcons } = await import('../../scripts/utils/utils.js'); + decorateIcons(block.closest('.section')); + } +} diff --git a/solutions/blocks/fragment-metadata/fragment-metadata.css b/_src/blocks/fragment-metadata/fragment-metadata.css similarity index 100% rename from solutions/blocks/fragment-metadata/fragment-metadata.css rename to _src/blocks/fragment-metadata/fragment-metadata.css diff --git a/solutions/blocks/fragment-metadata/fragment-metadata.js b/_src/blocks/fragment-metadata/fragment-metadata.js similarity index 100% rename from solutions/blocks/fragment-metadata/fragment-metadata.js rename to _src/blocks/fragment-metadata/fragment-metadata.js diff --git a/_src/blocks/header-aem/header-aem.css b/_src/blocks/header-aem/header-aem.css new file mode 100644 index 000000000..825d7e3c9 --- /dev/null +++ b/_src/blocks/header-aem/header-aem.css @@ -0,0 +1,50 @@ +.header-aem-wrapper { + .header-aem { + display: flex; + align-items: center; + height: 60px; + + img { + height: 26px; + width: auto; + } + } +} + +.header-aem-container { + background-color: #fff; + border-bottom: 1px solid #EDEDED; +} + +.header-aem-wrapper.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +@media (min-width: 992px) { + .header-aem-wrapper.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .header-aem-wrapper.we-container { + max-width: 1210px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1599px) { + .header-aem-wrapper.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} diff --git a/_src/blocks/header-aem/header-aem.js b/_src/blocks/header-aem/header-aem.js new file mode 100644 index 000000000..bbe10d78d --- /dev/null +++ b/_src/blocks/header-aem/header-aem.js @@ -0,0 +1,49 @@ +async function runWhitePageHeaderLogic(block, link) { + block.classList.add('white', 'py-3', 'default-content-wrapper'); + + if (link) { + // create a link and inside it put the logo + const logoLink = document.createElement('a'); + logoLink.href = link; + logoLink.classList.add('logo-link'); + const image = block.querySelector('picture'); + logoLink.appendChild(image); + block.appendChild(logoLink); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} + +/** + * applies header factory based on header variation + * @param {String} headerMetadata The header variation: landingpage' or none + * @param {Element} header The header element + */ +function applyHeaderFactorySetup(headerMetadata, header, link) { + switch (headerMetadata) { + case 'white': + runWhitePageHeaderLogic(header, link); + break; + default: + break; + } +} +export default async function decorate(block, options) { + const { + header, link, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.header-aem-wrapper'); + blockParent.classList.add('we-container'); + } + + block.parentNode.classList.add(header || 'default'); + + applyHeaderFactorySetup(header, block, link); +} diff --git a/_src/blocks/header/header.css b/_src/blocks/header/header.css new file mode 100644 index 000000000..504a337d7 --- /dev/null +++ b/_src/blocks/header/header.css @@ -0,0 +1,1247 @@ +/* stylelint-disable no-descending-specificity */ + +/* header and nav layout */ +header.header-wrapper { + position: sticky; + top: 0; + transition: height 0.3s ease-in-out; + background-color: var(--white-color); + z-index: 100; +} + +header.header-wrapper nav { + display: none; +} + + +:root { + --dark-header-icon-color: #000; +} + +header.header-wrapper p { + margin: 0; +} + +header.header-wrapper > p { + margin-top: 0; + padding: 15px; + text-align: center; + font-size: var(--body-font-size-s); + color: var(--horizontal-separator-color); + text-decoration: none; + cursor: pointer; + width: 175px; + height: 50px; +} + + + + + + +header.header-wrapper .nav-wrapper { + display: none; +} + +header.header-wrapper .nav-brand, +header.header-wrapper .nav-sections { + display: inline-flex; + align-items: flex-start; + width: 49.5%; +} + +header.header-wrapper .nav-brand { + flex-wrap: nowrap; + justify-content: flex-start; +} + +header.header-wrapper .nav-sections { + flex-wrap: nowrap; + justify-content: flex-end; +} + +header.header-wrapper .nav-brand p, +header.header-wrapper .nav-sections p { + display: inline-block; +} + +header.header-wrapper .bottom-links div, .bottom-links p{ + display: inline-block; +} + +header.header-wrapper .login-modal > p { + position: relative; + width: 100%; + display: block; + text-align: center; + margin-top: 45px; +} + +@keyframes animate-bottom-border { + 0% { + transform: scaleX(0); + transform-origin: left; + } + + 100% { + transform: scaleX(1); + transform-origin: left; + } +} + +header.header-wrapper .home-button-border { + position: absolute; + margin-top: 12px; + width: 70px; + height: 3px; + background-color: var(--color-highlight-blue); +} + +header.header-wrapper .nav-divider { + display: flex; + flex-wrap: nowrap; + justify-content: flex-end; + min-width: 2px; + width: 2px; + background-color: var(--color-dark-gray); + height: 20px; + margin-right: 15px; + margin-top: 7.5px; +} + +header.header-wrapper .login-modal { + display: none; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + position: absolute; + right: min(15px, calc(100vw - 880px)); + width: 375px; + height: 275px; + top: 80px; + background-color: var(--background-color); + border-radius: 5px; + opacity: 0; + transition: all 0.3s ease-in-out; + box-shadow: 0 10px 10px #0003; + z-index: 0; + transform: translateY(20px); +} + +header.header-wrapper .login-modal.show { + opacity: 1; + top: 60px; + z-index: 5; + transform: translateY(0); +} + + +header.header-wrapper .login-modal h2 { + position: relative; + white-space: nowrap; + color: var(--text-color); + font-size: var(--body-font-size-s); + width: 100%; + margin-left: 25px; + top: 15px; + text-align: left; +} + +header.header-wrapper .divider { + position: absolute; + margin-top: 45px; + width: 100%; + height: 1px; + background-color: var(--color-dark-gray); +} + +.login-modal a { + text-decoration: none; + color: var(--color-highlight-blue) !important; + width: 330px; + height: 55px; + border-radius: 9px; + border: 2px solid var(--color-highlight-blue) !important; + background-color: transparent !important; + margin: -70px; + padding: 5px; + display: inline-block; + font-size: var(--body-font-size-xs); + font-weight: 500; +} + +header.header-wrapper a.button:any-link { + padding: 0; +} + +header.header-wrapper .login-modal a.button:any-link { + height: 50px; + padding-right: 15px; +} + +header.header-wrapper a.button::after { + margin-left: 0; +} + +header.header-wrapper .login-modal a.button::after { + position: relative; + margin-left: 220px; +} + +header.header-wrapper .login-modal a.button:any-link span { + margin-left: 25%; + position: absolute; + font-weight: 500; +} + +header.header-wrapper .login-modal.show p.button-container:nth-child(3) span { + margin-left: 13%; +} + +header.header-wrapper .login-modal.show p.button-container:nth-child(3) a.button::after { + margin-left: 280px; +} + +header.header-wrapper .login-modal.show p.button-container:nth-child(4) span { + margin-left: 33%; +} + +header.header-wrapper .login-modal.show p.button-container:nth-child(4) a.button::after { + margin-left: 200px; +} + +header.header-wrapper .logo-container { + height: 100%; + display: flex; + justify-content: start; + align-items: center; + max-width: var(--section-desktop-max-width); + margin: 0 auto; + padding: 0 var(--body-padding); +} + +header.header-wrapper.expanded .logo-container { + height: var(--nav-height); + position: absolute; + top: 0; + left: 0; +} + +header.header-wrapper .logo-container > p { + display: none; +} + +header.header-wrapper .login-buttons a p { + text-align: center; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + margin-top: 5px; + transition: all 0.3s ease-in-out; + height: 100%; +} + +header.header-wrapper .icon { + position: absolute; + margin: 0; + z-index: 1000; + top: 15px; + width: 103px; + height: 30px; + filter: none; + left: 20px; + color: var(--dark-background-color); +} + +header.header-wrapper .bottom-links p > a { + text-decoration: none; + font-size: var(--body-font-size-xxs) !important; + font-weight: 500 !important; +} + +header.header-wrapper .login-modal a:hover { + background-color: var(--color-highlight-blue) !important; + color: var(--background-color) !important; +} + +header.header-wrapper a.button span.button-text { + display: flex; + font-size: var(--body-font-size-xs); + font-weight: 400; +} + +header.header-wrapper a.button:hover span.button-text { + transform: none; +} + +header.header-wrapper .options-wrapper.show a { + display: block; + margin-left: 40px; + color: var(--text-color); + font-size: var(--body-font-size-xs); + margin-top: 10px; + text-decoration: none; + animation: slide-in 0.2s 0.075s forwards; + background-color: transparent !important; + border: transparent !important; +} + +header.header-wrapper .bottom-links p:hover > a { + color: var(--color-highlight-blue) !important; +} + +header.header-wrapper > p a:hover{ + color: var(--background-color); +} + +header.header-wrapper .options-wrapper.show > a:first-child { + margin-top: 40px; +} + +header.header-wrapper .login-modal.show.button-container a:hover{ + background-color: var(--color-highlight-blue); + color: var(--background-color); +} + +header.header-wrapper .triangle { + position: absolute; + width: 0; + height: 0; + top: -13px; + left: 320px; + border-left: 15px solid transparent; + border-right: 15px solid transparent; + border-bottom: 20px solid white; +} + +header.header-wrapper .mega-menu-websites div h2 { + position: relative; + font-size: var(--body-font-size-s); + font-weight: 600; + margin-left: 25px; +} + +header.header-wrapper .mega-menu-websites > div:first-child { + display: grid; + grid-template-rows: auto auto; + grid-template-columns: 1fr 1fr 1fr; + align-items: start; + border-bottom: 2px solid #f5f6f7; +} + +header.header-wrapper .mega-menu-websites > div:first-child h2 { + grid-column: span 3; +} + +header.header-wrapper .mega-menu-websites > div:first-child p { + width: 250px; + margin-top: 5px; + border-radius: 5px; + padding: 10px; + height: 85px; +} + + +header.header-wrapper .mega-menu-websites > div:first-child p:hover { + background-color: var(--highlight-light-blue); +} + +header.header-wrapper .mega-menu-websites > div:first-child > p:first-child { + grid-column: 1; +} + +header.header-wrapper .mega-menu-websites > div:first-child p a > span::after { + content: ''; + width: 24px; + height: 24px; + /* stylelint-disable-next-line property-no-vendor-prefix */ + -webkit-mask:url('/_src/icons/arrow-right.svg'); + mask: url('/_src/icons/arrow-right.svg'); + background-color: var(--button-link-color); + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + opacity: 0; +} + +header.header-wrapper .mega-menu-websites > div:first-child p a:hover span::after { + opacity: 1; + background-color: var(--color-highlight-blue); +} + +header.header-wrapper .mega-menu-websites > div:first-child p a::after { + display: none; +} + +header.header-wrapper .options-wrapper.show div { + font-weight: var(--font-weight-bold); + font-size: var(--body-font-size-s); + margin: 25px 13px 25px 20px; + position: relative; +} + +header.header-wrapper .options-wrapper.show div::before { + border-color: black; + border-style: solid; + border-width: 0 2px 2px 0; + content: ""; + width: 0.5rem; + height: 0.5rem; + display: inline-block; + position: absolute; + right: 10px; + top: 50%; + transform: translateY(-50%) rotate(-45deg); +} + +@media (max-width: 992px) { + header.header-wrapper .nav-wrapper { + display: none; + } + + header.header-wrapper p { + margin: 0; + } + + header.header-wrapper > p{ + display: none; + } + +} + +header.header-wrapper .icon.icon-arrow-right { + position: absolute; + width: 10px; + height: 10px; + margin-left: 1px; + z-index: 5; +} + +header.header-wrapper .bottom-links div:nth-child(2) { + margin-left: 120px; +} + +header.header-wrapper .menu-bar { + display: block; + width: 100%; + height: 3px; + background-color: var(--text-color); + transition: transform 0.3s ease, opacity 0.3s ease; + will-change: transform, opacity; +} + +header.header-wrapper .menu-wrapper { + position: absolute; + top: 17px; + right: 20px; + width: 25px; + height: 25px; + cursor: pointer; + display: flex; + flex-direction: column; + justify-content: space-around; + z-index: 100; +} + +header.header-wrapper .menu-wrapper.change .menu-bar:first-child { + transform: rotate(-45deg) translate(-5px, 5px); +} + +header.header-wrapper .menu-wrapper.change .menu-bar:nth-child(2) { + opacity: 0; +} + +header.header-wrapper .menu-wrapper.change .menu-bar:last-child { + transform: rotate(45deg) translate(-6px,-7px); +} + +header.header-wrapper.expanded { + height: 100vh; + width: 100vw; + z-index: 2; +} + +header.header-wrapper .options-wrapper { + position: relative; + top: var(--nav-height); + width: 100vw; + height: 0; + display: none; +} + +header.header-wrapper .options-wrapper.show{ + width: 100vw; + height: 100vh; + box-shadow: 0 10px 10px #0003; + z-index: 3; + border-top: 1px solid #cecccc; + display: block; +} + +header.header-wrapper .sub-menu { + display: none; +} + +header.header-wrapper .sub-menu.show { + display: block; +} + +header.header-wrapper .options-wrapper.show .sub-menu-title { + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + margin-left: 20px; + padding-left: 20px; + position: relative; +} + +header.header-wrapper .options-wrapper.show .sub-menu-title::before { + border-color: black; + border-style: solid; + border-width: 0 2px 2px 0; + content: ""; + width: 0.5rem; + height: 0.5rem; + display: inline-block; + position: absolute; + left: 0; + top: 50%; + transform: translate(0, -50%) rotate(135deg); +} + +@keyframes slide-in { + from { + transform: translateX(100%); + } + + to { + transform: translateX(0); + } +} + +header.header-wrapper #icons-sprite-bitdefender-logo path { + fill: currentcolor +} + +#header-ferrari { + border-bottom: 2px solid #3C3C3C; + height: 40px; + box-shadow: 0 32px 73px #000; + background-color: black; +} + +#header-ferrari div div { + margin-top: -10px; +} + +#header-ferrari ul { + padding: 0; + margin: 0; + width: 50%; + float: left; +} + +#header-ferrari ul:nth-of-type(2) { + text-align: right; +} + +#header-ferrari ul:nth-of-type(3) { + width: 100%; + margin-top: -5px; +} + +#header-ferrari ul li { + color: white; + font-size: 12px; + list-style-type: none; + display: inline-block; + padding: 0 10px; + font-weight: 600; +} + +#header-ferrari ul:nth-of-type(2) li { + border-left: 1px solid #616161; +} + +#header-ferrari ul:nth-of-type(3) li { + padding: 0 25px 0 0; +} + +#header-ferrari ul:nth-of-type(1) li:nth-of-type(1) { + padding-left: 0; +} + +#header-ferrari ul li a { + color: #DEDEDE; + font-size: 12px; + padding-bottom: 10px; + position: relative; + font-weight: 600; +} + +#header-ferrari ul li a::before { + content: ""; + position: absolute; + bottom: -2px; + height: 4px; + background: #006EFF; + transition: all 0.3s ease; + transition-property: transform; + width: 100%; + transform: scaleX(0); + will-change: transform; + transform-origin: right; +} + +#header-ferrari ul li a:hover { + text-decoration: none; +} + +#header-ferrari ul li a:hover::before { + transform: scaleX(1); + transform-origin: left; +} + +#header-ferrari ul:nth-of-type(3) li a { + color: #FFF; + font-size: 16px; + font-weight: 500; +} + +#header-ferrari ul:nth-of-type(3) li a span.icon-logo-white { + display: inline-block; + background: url("/_src/images/sigla_bd_white.svg") 0 0 no-repeat; + width: 165px; + height: 25px; +} + +#header-ferrari ul:nth-of-type(3) :nth-of-type(3) a { + font-weight: bold; +} + +header.quiz { + background: black; + + .icon { + width: 155px; + } +} + +@media(min-width: 767px) { /* tablet */ + header.header-wrapper .logo-container .icon { + width: 180px; + } + +} + +@media(min-width: 992px) { + header.header-wrapper::after { + position: absolute; + top: 64px; + left: 0; + right: 0; + width: 100%; + height: 2px; + background-color: #3c3c3c; + margin: 0 auto; + } + + header.header-wrapper .icon { + color: var(--text-color); + position: static; + } + + header.header-wrapper.black-background .icon { + color: var(--text-dark-color); + } + + header.header-wrapper .menu-wrapper { + display: none; + } + + header.header-wrapper .nav-wrapper { + width: 100%; + background-color: var(--text-color); + z-index: 100; + display: block; + margin: 0 auto; + } + + header.header-wrapper nav { + display: block; + max-width: var(--section-desktop-max-width); + height: 100%; + margin: 0 auto; + padding: 6px var(--section-desktop-padding) 10px; + position: relative; + } + + header.header-wrapper nav p { + line-height: 1.4; + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-bold); + } + + header.header-wrapper .nav-sections { + display: inline-flex; + flex-wrap: wrap; + gap: 0; + } + + + header.header-wrapper .nav-brand a, + header.header-wrapper .nav-sections a { + color: var(--horizontal-separator-color); + text-decoration: none; + text-transform: uppercase; + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-bold); + margin-right: 0; + letter-spacing: 0.96px; + cursor: pointer; + line-height: 1.4; + display: inline-block; + position: relative; + } + + header.header-wrapper .nav-sections a { + margin: 0 15.5px; + } + + header.header-wrapper .logo a { + display: block; + } + + header.header-wrapper .nav-brand p a { + margin: 0 12px; + } + + header.header-wrapper .mega-menu-websites div h2 > a { + transition: all 0.2s ease-in-out; + border-radius: 3px; + text-decoration: none; + padding: 7px 10px; + color: var(--link-color); + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + } + + header.header-wrapper .mega-menu-websites div p a{ + position: relative; + font-size: var(--body-font-size-xs); + font-weight: 400; + color: var(--text-color); + } + + header.header-wrapper .nav-sections a:first-child{ + margin-right: 16px; + } + + header.header-wrapper .nav-brand p:first-child a{ + margin-left: 0; + } + + header.header-wrapper .nav-sections p a::before, + header.header-wrapper .nav-brand p a::before { + content: ""; + position: absolute; + top: 25px; + height: 3px; + background: var(--color-highlight-blue); + transition: all .3s ease; + width: 100%; + transform: scaleX(0); + transform-origin: left; + left: 0; + } + + header.header-wrapper .nav-sections p a:hover::before, + header.header-wrapper .nav-brand p a.active::before, + header.header-wrapper .nav-brand p a:hover::before, + header.header-wrapper .nav-sections p.clicked a::before { + transform: scaleX(1); + transform-origin: left; + } + + /* Other existing styles */ + header.header-wrapper .mega-menu-websites div h2 > a:hover { + background-color: var(--highlight-light-blue); + } + + header.header-wrapper .nav-sections p:last-child:hover::after { + width: 50px; + } + + header.header-wrapper .nav-sections p, + header.header-wrapper .nav-brand p { + position: relative; + } + + header.header-wrapper .nav-sections p::before, + header.header-wrapper .nav-brand p:not(:first-child)::before { + content: ""; + position: absolute; + top: 0; + left: 0; + height: 16px; + width: 2px; + background-color: #616161; + } + + header.header-wrapper .logo-container { + padding: 20px var(--section-desktop-padding); + margin: 21px auto 0; + gap: 10px; + } + + header.header-wrapper .logo-container > p { + display: block; + font-weight: var(--font-weight-bold); + line-height: 1.63; + font-size: 15px; + } + + header.header-wrapper .home-solutions-link-hover { + color: #FFF; + } + + header.header-wrapper .home-solutions-link-default { + display: block; + color: var(--text-color); + cursor: pointer; + padding: 0 27px 31px; + position: relative; + margin-top: 35px; + } + + header.header-wrapper.black-background .home-solutions-link-default { + color: #dedede; + } + + header.header-wrapper .home-solutions-link-default::before { + content: ""; + position: absolute; + bottom: 3px; + height: 4px; + background: #006eff; + transition: all .3s ease; + width: 100%; + transform: scaleX(0); + transform-origin: left; + left: 0; + } + + header.header-wrapper .home-solutions-link-hover::before { + transform: scaleX(1); + transform-origin: left; + } + + header.header-wrapper .mega-menu-websites { + flex-direction: column; + position: absolute; + left: 80px; + top: 123px; + max-width: 920px; + width: 100%; + background-color: var(--background-color); + z-index: 3; + transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out; + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + box-shadow: 0 10px 10px #0003; + visibility: hidden; + display: none; + opacity: 0; + } + + header.header-wrapper .mega-menu-websites-show { + opacity: 1; + visibility: visible; + display: flex; + } + + header.header-wrapper .mega-menu-websites div h2 { + position: relative; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-boldest); + line-height: 18px; + padding: 7px 10px; + margin: 10px 25px 0 15px; + } + + header.header-wrapper .other-options > div:nth-child(5) { + grid-area: 2 / 3 / 3 / 4; + } + + header.header-wrapper .other-options > div:nth-child(4) { + grid-area: 2 / 2 / 3 / 3; + } + + header.header-wrapper .other-options > div:nth-child(3) { + grid-area: 1 / 3 / 2 / 4; + } + + header.header-wrapper .other-options > div:nth-child(2) { + grid-area: 1 / 2 / 2 / 3; + } + + header.header-wrapper .other-options > div:nth-child(1) { + grid-area: 1 / 1 / 3 / 2; + } + + header.header-wrapper .other-options > div > p { + position: relative; + top: 0; + margin-left: 20px; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-regular); + line-height: 18px; + } + + header.header-wrapper .other-options > div > h2 { + margin-top: 0; + } + + header.header-wrapper .other-options > div > p a.button { + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-regular); + line-height: 18px; + text-decoration: none; + padding: 1px 10px; + background-color: transparent; + border-radius: 4px; + border: none; + } + + header.header-wrapper .other-options > div > p a.button:hover { + background-color: var(--highlight-light-blue); + transition: none; + transform: none; + } + + header.header-wrapper .mega-menu-websites > div:first-child p a::after { + display: none; + } + + header.header-wrapper .other-options > div > p a:hover::after { + background-color: var(--color-highlight-blue); + } + + header.header-wrapper .other-options > div > p a.button > span { + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-regular); + line-height: 18px; + position: relative; + color: var(--text-color); + } + + header.header-wrapper .mega-menu-websites > div:first-child p a > span:first-child { + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-boldest); + line-height: 18px; + align-items: center; + } + + header.header-wrapper .mega-menu-websites .button-container:hover a.button::after { + transform: none; + opacity: 1; + } + + header.header-wrapper .mega-menu-websites > div:first-child { + display: grid; + grid-template-rows: auto auto; + grid-template-columns: 1fr 1fr 1fr; + align-items: start; + border-bottom: 2px solid #f5f6f7; + padding-bottom: 14px; + } + + header.header-wrapper.mega-menu-websites > div:first-child > p > a > div { + margin-top: 5px; + line-height: 18px; + font-size: 13px; + font-weight: 400; + color: var(--color-dark-gray); + white-space: break-spaces; + text-align: left; + } + + header.header-wrapper .mega-menu-websites > div:first-child h2 { + grid-column: span 3; + } + + header.header-wrapper .mega-menu-websites div p { + margin-left: 15px; + } + + header.header-wrapper.bottom-links div p { + height: fit-content; + margin-left: 20px; + } + + header.header-wrapper .mega-menu-websites > div:first-child p { + width: 250px; + margin-top: 0; + border-radius: 5px; + padding: 0; + height: auto; + } + + header.header-wrapper .mega-menu-websites > div:first-child p:hover { + background-color: var(--highlight-light-blue); + } + + header.header-wrapper .mega-menu-websites > div:first-child > p:first-child { + grid-column: 1; + } + + header.header-wrapper .mega-menu-websites > div:first-child p a > span::after { + content: ''; + width: 24px; + height: 24px; + /* stylelint-disable-next-line property-no-vendor-prefix */ + -webkit-mask:url('/_src/icons/arrow-right.svg'); + mask: url('/_src/icons/arrow-right.svg'); + background-color: var(--button-link-color); + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + opacity: 0; + } + + header.header-wrapper .mega-menu-websites > div:first-child p a:hover > span::after { + opacity: 1; + background-color: var(--color-highlight-blue); + } + + + header.header-wrapper .mega-menu-websites > div:first-child p a { + padding: 7px 10px; + display: block; + color: var(--text-color) !important; + text-decoration: none; + font-size: var(--body-font-size-s); + background-color: transparent; + border: none; + } + + header.header-wrapper .mega-menu-websites > div:first-child p:hover a { + color: var(--color-highlight-blue) !important; + } + + header.header-wrapper .other-options { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: repeat(2, 1fr); + grid-gap: 0; + padding-top: 14px; + } + + header.header-wrapper #new, + header.header-wrapper #evolved { + position: relative; + font-size: var(--body-font-size-xxs); + font-weight: 600; + color: var(--background-color); + background-color: var(--color-highlight-blue); + padding: 2px; + border-radius: 3px; + margin-left: 5px; + } + + header.header-wrapper .bottom-links { + background-color: rgb(158 164 177 / 10%); + padding: 8px 11px; + margin-top: 20px; + } + + header.quiz { + .icon { + width: 200px; + height: 64px; + } + } +} + +@media (min-width: 1200px) { + header.header-wrapper .mega-menu-websites { + left: 80px; + transform: translateX(0); + } +} + +@media (min-width: 1400px) { + header.header-wrapper .mega-menu-websites { + left: 210px; + transform: translateX(0); + } +} + +@media (min-width: 1600px) { + header.header-wrapper .mega-menu-websites { + left: 240px; + transform: translateX(0); + } +} + +@media (min-width: 1600px) { + header.header-wrapper nav { + max-width: var(--section-large-desktop-max-width); + padding-left: var(--section-large-desktop-padding); + padding-right: var(--section-large-desktop-padding); + } + + header.header-wrapper .nav-brand p a { + margin: 0 19px; + } + + header.header-wrapper .logo-container { + max-width: var(--section-large-desktop-max-width); + padding-left: var(--section-large-desktop-padding); + padding-right: var(--section-large-desktop-padding); + } + + header.header-wrapper .logo-container > p { + font-size: 16px; + } + + header.header-wrapper .home-solutions-link-default { + padding-left: 20px; + } +} + +/* import header spurs lp */ +@media screen and (max-width: 989px) { + #header-ferrari.header-spurs { + background-color: white; + border-bottom: 0 none; + height: 40px; + position: static; + } + + #header-ferrari.header-spurs::before { + content: ''; + background: url('/_src/images/black_company_logo.svg') no-repeat 0 0 transparent; + width: 100px; + height: 20px; + display: block; + background-size: 100%; + margin: 10px; + position: relative; + top: 7px; + } + + #header-ferrari.header-spurs .lp-header { + padding: 0!important; + } + + #header-ferrari.header-spurs .lp-header::before { + content: ''; + background: url('/_src/icons/burger_menu.JPG') no-repeat 0 0 transparent; + width: 29px; + height: 29px; + display: block; + background-size: 100%; + position: absolute; + right: 7px; + top: -26px; + cursor: pointer; + } + + #header-ferrari.header-spurs .lp-header > div { + position: absolute; + z-index: 5; + background-color: white; + width: 100%; + visibility: hidden; + } + + #header-ferrari.header-spurs .lp-header.active > div { + visibility: visible; + } + + #header-ferrari.header-spurs .lp-header > div ul li { + border-bottom: 1px solid #0003; + padding-left: 15px; + } + + .btn-white .button-container a, .btn-white.button-container a:hover { + font-size: 14px; + line-height: 17px; + padding: 10px 1em; + } + + #header-ferrari.header-spurs .lp-header > div ul li, #header-ferrari.header-spurs .lp-header > div ul li a { + width: 100%; + display: block; + padding-bottom: 0; + color: black; + font-size: 15px; + font-family: 'IBM Plex Sans', sans-serif; + text-transform: uppercase; + } + + #header-ferrari.header-spurs .lp-header > div ul li a::before { + display: none; + } + + #header-ferrari.header-spurs ul:last-of-type li:first-of-type { + display: none; + } + + + #header-ferrari { + box-shadow: none; + position: static; + height: auto; + } + + #header-ferrari div div { + margin-top: 0; + flex-direction: column; + display: flex; + } + + #header-ferrari ul { + width: 100%; + float: none; + } + + #header-ferrari ul:nth-of-type(1) { + order: 2; + } + + #header-ferrari ul:nth-of-type(2) { + text-align: left; + order: 3; + } + + #header-ferrari ul li { + padding: 0 10px 0 0; + font-size: 12px; + } + + #flipdown .flip-clock-wrapper ul li { + line-height: 48px; + } + + #header-ferrari ul:nth-of-type(2) li { + border-left: 0 none; + } + + #header-ferrari ul:nth-of-type(3) { + margin-top: 0; + padding-bottom: 0; + order: 1; + } + + #header-ferrari ul:nth-of-type(3) li a span.icon-logo-white { + width: 100px; + height: 17px; + background-size: 100%; + } + + #header-ferrari ul:nth-of-type(3) li { + padding: 0 3px 0 0; + } + + #header-ferrari ul:nth-of-type(3) li a { + font-size: 12px; + } +} diff --git a/solutions/blocks/header/header.js b/_src/blocks/header/header.js similarity index 74% rename from solutions/blocks/header/header.js rename to _src/blocks/header/header.js index 3ec8f51e3..2582e6e8a 100644 --- a/solutions/blocks/header/header.js +++ b/_src/blocks/header/header.js @@ -2,8 +2,9 @@ import { getMetadata, decorateIcons, decorateButtons, decorateTags, } from '../../scripts/lib-franklin.js'; -import { decorateBlockWithRegionId, decorateLinkWithLinkTrackingId } from '../../scripts/scripts.js'; -import { adobeMcAppendVisitorId } from '../../scripts/utils.js'; +import { adobeMcAppendVisitorId } from '../../scripts/utils/utils.js'; + +import { decorateBlockWithRegionId, decorateLinkWithLinkTrackingId, getDomain } from '../../scripts/scripts.js'; function createLoginModal() { const loginModal = document.querySelector('nav > div:nth-child(4)'); @@ -34,7 +35,7 @@ function handleLoginClick() { } function appendUlToP() { - const divs = document.querySelectorAll('.mega-menu > div'); + const divs = document.querySelectorAll('.mega-menu-websites > div'); divs.forEach((div) => { const uls = div.querySelectorAll('ul'); @@ -60,7 +61,7 @@ function wrapDivsInMegaMenu() { const divs = Array.from(nav.children).filter((node) => node.tagName.toLowerCase() === 'div'); const navSectionsIndex = divs.findIndex((div) => div.classList.contains('nav-sections')); const megaMenuDiv = document.createElement('div'); - megaMenuDiv.className = 'mega-menu'; + megaMenuDiv.className = 'mega-menu-websites'; decorateBlockWithRegionId(megaMenuDiv, 'Main Menu|Home Solutions'); const otherOptionsDiv = document.createElement('div'); @@ -96,7 +97,7 @@ function wrapDivsInMegaMenu() { otherOptionsDiv.appendChild(bottomLinks.firstElementChild); } - const loginModal = document.querySelector('.mega-menu > div:first-child'); + const loginModal = document.querySelector('.mega-menu-websites > div:first-child'); nav.appendChild(loginModal); } @@ -174,20 +175,20 @@ function renderDesktopHeader(block, nav) { const bottomLinks = document.querySelector('.bottom-links'); bottomLinks.removeChild(bottomLinks.lastElementChild); - const megaMenu = document.querySelector('.mega-menu'); + const megaMenu = document.querySelector('.mega-menu-websites'); let isOverHomeSolutions = false; let isOverMegaMenu = false; const showMegaMenu = () => { megaMenu.style.display = 'flex'; setTimeout(() => { - megaMenu.classList.add('mega-menu-show'); + megaMenu.classList.add('mega-menu-websites-show'); }, 10); }; const hideMegaMenu = () => { if (!isOverHomeSolutions && !isOverMegaMenu) { - megaMenu.classList.remove('mega-menu-show'); + megaMenu.classList.remove('mega-menu-websites-show'); homeSolutions.classList.remove('home-solutions-link-hover'); } }; @@ -244,7 +245,7 @@ function handleMenuClick() { }); // Select the first child of mega-menu and all div children of other-options - const megaMenuFirstChild = document.querySelector('.mega-menu').firstElementChild; + const megaMenuFirstChild = document.querySelector('.mega-menu-websites').firstElementChild; const otherOptionsChildren = Array.from(document.querySelector('.other-options').children); const navDivs = [megaMenuFirstChild].concat(otherOptionsChildren); @@ -363,12 +364,8 @@ function renderMobileHeader(nav) { headerBlock.appendChild(optionsWrapper); } -export default async function decorate(block) { +async function runDefaultHeaderLogic(block) { const hero = document.querySelector('.hero'); - const isErrorPage = window.isErrorPage || false; - - // Check if the page isn't an error page and if the hero doesn't exist - if (!hero && !isErrorPage) return; if (hero && hero.classList.contains('black-background')) { const header = document.querySelector('header'); @@ -385,6 +382,74 @@ export default async function decorate(block) { if (resp.ok) { const html = await resp.text(); + if (html.includes('aem-banner')) { + let domain = getDomain(); + if (domain === 'en-us') { + domain = 'en'; + } else { + domain = domain.split('-').join('_'); + } + + const aemHeaderLink = window.location.hostname.includes('.hlx.') + || window.location.hostname.includes('localhost') + ? 'https://stage.bitdefender.com' + : ''; + + // TODO: this needs to be updated to also bring the language bar in the future !!! + const aemHeaderFetch = await fetch(`${aemHeaderLink}/content/experience-fragments/bitdefender/language_master/${domain}/header-navigation/mega-menu/master/jcr:content/root/mega_menu.html`); + if (!aemHeaderFetch.ok) { + return; + } + const aemHeaderHtml = await aemHeaderFetch.text(); + + const nav = document.createElement('div'); + const shadowRoot = nav.attachShadow({ mode: 'open' }); + + const contentDiv = document.createElement('div'); + contentDiv.style.display = 'none'; + contentDiv.classList.add('mega-menu'); + contentDiv.classList.add('default-content-wrapper'); + contentDiv.innerHTML = aemHeaderHtml; + const cssFile = contentDiv.querySelector('link[rel="stylesheet"]'); + if (cssFile) { + cssFile.href = '/_src/scripts/vendor/mega-menu/mega-menu.css'; + cssFile.as = 'style'; + + // wait for the css to load before displaying the content + // this is to avoid the content being displayed without the styles + cssFile.onload = () => { + contentDiv.style.display = 'block'; + }; + shadowRoot.appendChild(contentDiv); + } + + const newScriptFile = document.createElement('script'); + newScriptFile.src = '/_src/scripts/vendor/mega-menu/mega-menu.js'; + + const shadowRootScriptTag = shadowRoot.querySelector('script'); + if (shadowRootScriptTag) { + shadowRootScriptTag.replaceWith(newScriptFile); + } + + const navHeader = shadowRoot.querySelector('header'); + if (navHeader) { + navHeader.style.height = 'auto'; + } + + const body = document.querySelector('body'); + body.style.maxWidth = 'initial'; + + const header = document.querySelector('header'); + if (header) { + header.remove(); + } + + document.querySelector('body').prepend(nav); + + adobeMcAppendVisitorId(shadowRoot); + return; + } + const nav = document.createElement('nav'); nav.id = 'nav'; nav.innerHTML = html; @@ -446,6 +511,64 @@ export default async function decorate(block) { } } }); +} + +async function runLandingPageHeaderLogic(block) { + // fetch nav content + const navPath = getMetadata('nav') || '/nav'; + const resp = await fetch(`${navPath}.plain.html`); + const html = await resp.text(); + + block.classList.add('lp-header', 'py-3', 'default-content-wrapper'); + const headerWrapper = block.closest('header'); + + headerWrapper.id = 'header-ferrari'; + headerWrapper.classList.add('header-spurs', 'dark'); + block.innerHTML = html; + + const lpHeader = block.closest('.lp-header'); + lpHeader.addEventListener('click', () => { + lpHeader.classList.toggle('active', !lpHeader.classList.contains('active')); + }); +} + +async function runQuizPageHeaderLogic(block) { + // fetch nav content + const navPath = getMetadata('nav') || '/nav'; + const resp = await fetch(`${navPath}.plain.html`); + const html = await resp.text(); + + block.classList.add('quiz', 'py-3', 'default-content-wrapper'); + const headerWrapper = block.closest('header'); + + headerWrapper.classList.add('dark'); + block.innerHTML = html; + + decorateIcons(block); +} + +/** + * applies header factory based on header variation + * @param {String} headerMetadata The header variation: landingpage' or none + * @param {Element} header The header element + */ +function applyHeaderFactorySetup(headerMetadata, header) { + switch (headerMetadata) { + case 'landingpage': + runLandingPageHeaderLogic(header); + break; + case 'quiz': + runQuizPageHeaderLogic(header); + break; + default: + runDefaultHeaderLogic(header); + break; + } +} + +export default async function decorate(block) { + const headerMetadata = getMetadata('header-type'); + block.parentNode.classList.add(headerMetadata || 'default'); - adobeMcAppendVisitorId('header'); + applyHeaderFactorySetup(headerMetadata, block); } diff --git a/_src/blocks/hero-aem/hero-aem.css b/_src/blocks/hero-aem/hero-aem.css new file mode 100644 index 000000000..069f45473 --- /dev/null +++ b/_src/blocks/hero-aem/hero-aem.css @@ -0,0 +1,514 @@ +/* stylelint-disable */ +.hero-aem-container.hero-vsb { + overflow: unset !important; +} + +.hero-aem-container .hero-aem p:first-of-type:has(a) { + margin: 0; + font-size: 16px; +} +.hero-aem-container .hero-aem >p:first-of-type { + margin: 0; + margin-bottom: 20px; +} + + +.hero-aem-container .hero-aem p:first-of-type a { + margin: 0; + margin-bottom: 20px; +} +.hero-aem-container .hero-aem h1 { + color: #006DFF; + font-size: 38px; + font-weight: normal; + margin-top: 10px; + line-height: 1.1; + margin-bottom: 20px; +} +.hero-aem-container .hero-aem h2 { + margin-top: 0; + font-size: 24px; + font-weight: normal; + line-height: 1.1; +} +.hero-aem-container .hero-aem .hero-aem__mobile-image img { + border-top-left-radius: 20px; + border-top-right-radius: 20px; + width: 100%; + height: fit-content; + position: relative; + top: 6px; +} +.hero-aem-container .hero-aem .hero-aem__desktop-image { + display: none; +} +.hero-aem-container .hero-aem .hero-aem__card-text { + padding: 27px; + font-size: 20px; + background-color: #F7F7F7; + border-bottom-left-radius: 20px; + border-bottom-right-radius: 20px; +} + +.hero-aem-container .hero-aem .hero-aem__card-text picture img { + width: auto; + max-height: 60px; +} + +.hero-aem-container .hero-aem .hero-aem__card-text p:has(picture) { + text-align: center; +} + +.hero-aem-container .hero-aem .hero-aem__breadcrumb { + border-spacing: 0; + font-size: 12px; + margin-bottom: 5px; + align-self: flex-start; +} + +.hero-aem-container .hero-aem .hero-aem__breadcrumb a { + color: #202020; + text-decoration: none; +} + +.hero-aem-container .hero-aem .hero-aem__breadcrumb a:hover { + text-decoration: underline; +} + +.hero-aem-container .hero-aem p.button-container { + text-align: center; +} +.hero-aem-container .hero-aem p.button-container .button.primary { + width: 100%; +} +.hero-aem-container .hero-aem .prod-oldprice { + font-size: 16px; + text-decoration: line-through; +} +.hero-aem-container .hero-aem .prod-save { + color: #1C7928; + font-weight: bold; + font-size: 16px; + margin-left: 8px; +} +.hero-aem-container .hero-aem .prod-newprice { + font-size: 40px; + font-weight: bold; +} +.hero-aem-container .hero-aem .newprice-container { + line-height: 1; +} +.hero-aem-container .hero-aem .newprice-container sup { + position: relative; + top: -7px; +} +.hero-aem-container .aem-two-cards { + margin-top: 20px; +} +.hero-aem-container .aem-two-cards h2 { + font-size: 36px; + font-weight: bold; + line-height: 1.1; +} +.hero-aem-container .aem-two-cards_card { + border-radius: 20px; + background-color: #F7F7F7; + padding: 1.5rem; + display: flex; + flex-direction: column; + width: 100%; +} +.hero-aem-container .aem-two-cards_card .button-container { + margin-top: auto; +} +.hero-aem-container .aem-two-cards .aem-two-cards_card h2 { + color: #006DFF; + font-size: 24px; + font-weight: normal; + margin: 0; +} +.hero-aem-container .aem-two-cards .justify-space-between { + justify-content: space-between; +} + +.h-100 { + height: 100% !important; +} + +.hero-aem-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.hero-aem-container .button.primary { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.hero-aem-container .button.free-download { + color: #005ed9; + font-weight: bold; + background-color: transparent; + border: none; + margin: 0; + padding: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-decoration: none; +} + +.hero-aem-container .button.free-download:hover { + color: #0A53C5; + transform: translateX(10px); +} + +.hero-aem-container .button.free-download::after { + content: '\2192'; + width: 24px; + height: 24px; + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + margin-left: 2px; +} + +.hero-aem-container .button.free-download:hover::after { + transform: translateX(5px); +} + +/* this would ideally be the sales tax included text */ +.hero-aem__card-text p:last-child { + font-size: 14px; +} + +.hero-aem__card-text p:last-child a { + color: inherit; + margin-left: 8px; + font-weight: normal; +} + +.hero-aem-container .hero-aem p em a { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #006DFF; + background-color: transparent; + border: 2px solid #006DFF; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + transition: all .2s cubic-bezier(.4,0,.2,1); +} + +.hero-aem-container .hero-aem p em a:hover { + color: white; + background-color: #006DFF; +} + +.hero-aem-container .hero-aem p em a:active { + background-color: #0D499B; +} + +.hero-aem-container .hero-aem p strong em a { + color: black; + text-decoration: underline; +} + +.hero-aem__pill { + font-size: 14px; + font-weight: 500; + line-height: 1.1; + color: #fff; + background-color: #006DFF; + border-radius: 20px; + padding: 5px 13px; + display: inline-block; + margin-right: 10px; + margin-top: 0px; +} + +.hero-aem__underPriceText { + font-size: 14px; +} + +.hero-aem-container .aem-two-cards p a { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.hero-aem-container .aem-two-cards p:has(a) { + margin-top: auto; +} + +.hero-aem-container .aem-two-cards h2 { + font-size: 36px; + font-weight: bold; +} +.hero-aem-container .aem-two-cards .aem-two-cards_card h2 { + color: #006DFF; + font-size: 24px; + font-weight: normal; + margin: 0; +} +.hero-aem-container .row { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 1.5rem; + + display: flex; + flex-wrap: wrap; + margin-top: calc(-1 * var(--bs-gutter-y)); + margin-right: calc(-.5 * var(--bs-gutter-x)); + margin-left: calc(-.5 * var(--bs-gutter-x)); +} +.hero-aem-container .row>* { + display: flex; + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--bs-gutter-x) * .5); + padding-left: calc(var(--bs-gutter-x) * .5); + margin-top: var(--bs-gutter-y); + box-sizing: border-box; +} + + +.hero-aem-container .col-12 { + flex: 0 0 auto; + width: 100%; +} + + +@media (max-width: 767px) { + .hero-aem-container.hero-vsb { + padding-bottom: 0; + } + + .hero-aem-container.hero-vsb .hero-aem { + padding: 0 15px; + } + + .hero-aem-container.hero-vsb .hero-aem__card__desktop { + max-height: unset!important; + } + + .hero-aem-container.hero-vsb .hero-aem .hero-aem__card-text { + padding: 0; + background-color: transparent; + border-radius: 20px; + } + + .hero-aem-container.hero-vsb .hero-aem p.button-container { + text-align: left; + } + + .hero-aem-container.hero-vsb .hero-aem p.button-container .button.primary { + margin: 0; + max-width: 290px; + } + + .hero-aem-container.hero-vsb .hero-aem p.button-container .button.primary span { + text-align: center; + display: block; + width: 100%; + } + + .hero-aem-container.hero-vsb .hero-aem h1 { + color: #006DFF; + font-size: 29px; + } +} + +@media (min-width: 768px) { + .hero-aem-container .hero-aem { + display: flex; + flex-wrap: wrap; + } + .hero-aem-container .hero-aem .hero-aem__mobile-image { + display: none; + } + .hero-aem-container .hero-aem .hero-aem__desktop-image { + display: block; + height: 100%; + position: relative; + } + + .hero-aem-container .hero-aem .hero-aem__desktop-image::after { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: linear-gradient(to left, rgba(247, 247, 247, 0), #F7F7F7); + } + + .hero-aem-container .hero-aem .hero-aem__desktop-image img { + height: 100%; + max-width: 800px; + width: 100%; + object-fit: cover; + border-top-right-radius: 20px; + border-bottom-right-radius: 20px; + } + .hero-aem-container .hero-aem .hero-aem__card-text { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + background-color: initial; + padding: 0; + } + + .hero-aem-container .hero-aem .hero-aem__card-text p:has(picture) { + text-align: left; + } + + .hero-aem-container .hero-aem .hero-aem__card__desktop { + background-color: #F7F7F7; + border-bottom-left-radius: 20px; + border-top-left-radius: 20px; + } + + .hero-aem-container .hero-aem .hero-aem__card__desktop--center { + display: flex; + align-items: center; + } + .hero-aem-container .hero-aem .hero-aem__card__desktop > div { + padding: 24px 0px 24px 56px; + } + .hero-aem-container .hero-aem p.button-container { + text-align: left; + display: inline-block; + } + .hero-aem-container .hero-aem p.button-container .button.primary { + width: auto; + } + + .hero-aem-container .col-md-6 { + flex: 0 0 auto; + width: 50%; + } + + .hero-aem-container .col-md-4 { + flex: 0 0 auto; + width: 33.33%; + } + + .hero-aem-container .col-md-3 { + flex: 0 0 auto; + width: 24%; + } + + .hero-aem-container .aem-two-cards h2 + p { + font-size: 18px; + } + + .hero-aem-container .hero-aem p:has(a) { + display: inline-block; + } + + .hero-aem-container .hero-aem p:has(em) { + margin-left: 10px; + } +} + +@media (max-width: 992px) { + .hero-aem-container.hero-vsb .hero-aem h1 { + font-size: 32px; + } +} + +@media (min-width: 992px) { + .hero-aem-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + .hero-aem-container .col-lg-6 { + flex: 0 0 auto; + width: 49%; + } + .hero-aem-container .col-lg-5 { + flex: 0 0 auto; + width: 41.66%; + } + .hero-aem-container .col-lg-3 { + flex: 1 0 auto; + width: 24%; + } + .hero-aem-container .col-lg-2 { + flex: 0 0 auto; + width: 16.66%; + } +} + +@media (min-width: 1200px) { + .hero-aem-container .col-lg-6 { + flex: 0 0 auto; + width: 49%; + } + + .hero-aem-container .col-lg-3 { + flex: 0 0 auto; + width: 24%; + } +} + +@media (min-width: 1200px) { + .hero-aem-container.we-container { + max-width: 1350px; + padding-left: 20px; + padding-right: 20px; + } + + .hero-aem-container .hero-aem .hero-aem__desktop-image img { + max-height: 600px; + } +} diff --git a/_src/blocks/hero-aem/hero-aem.js b/_src/blocks/hero-aem/hero-aem.js new file mode 100644 index 000000000..e402b0764 --- /dev/null +++ b/_src/blocks/hero-aem/hero-aem.js @@ -0,0 +1,265 @@ +/* eslint-disable prefer-const */ +/* eslint-disable no-undef */ +/* eslint-disable max-len */ +let dataLayerProducts = []; +async function createPricesElement(storeOBJ, conditionText, saveText, prodName, prodUsers, prodYears, buylink, send2datalayer) { + const storeProduct = await storeOBJ.getProducts([new ProductInfo(prodName, 'consumer')]); + const storeOption = storeProduct[prodName].getOption(prodUsers, prodYears); + const price = storeOption.getPrice(); + const discountedPrice = storeOption.getDiscountedPrice(); + const discount = storeOption.getDiscount('valueWithCurrency'); + const buyLink = await storeOption.getStoreUrl(); + + let product = { + ID: storeOption.getAvangateId(), + name: storeOption.getName(), + devices: storeOption.getDevices(), + subscription: storeOption.getSubscription('months'), + version: storeOption.getSubscription('months') === 1 ? 'monthly' : 'yearly', + basePrice: storeOption.getPrice('value'), + discountValue: storeOption.getDiscount('value'), + discountRate: storeOption.getDiscount('percentage'), + currency: storeOption.getCurrency(), + priceWithTax: storeOption.getDiscountedPrice('value') || storeOption.getPrice('value'), + }; + dataLayerProducts.push(product); + + const priceElement = document.createElement('div'); + priceElement.classList.add('hero-aem__prices'); + priceElement.innerHTML = ` + ${!send2datalayer ? '

Yearly - individual

' : ''} +
+
+ ${price} + ${saveText} ${discount} +
+
+ ${discountedPrice} + ${conditionText || ''} +
+
+

Protection for 5 PCs, Macs, tablets, or smartphones.
Windows® | macOS® | Android™ | iOS®

`; + if (buylink) { + buylink.href = buyLink; + } + return priceElement; +} + +function createCardElementContainer(elements, mobileImage) { + const cardElementContainer = document.createElement('div'); + cardElementContainer.classList.add('hero-aem__card'); + + const cardElementText = document.createElement('div'); + cardElementText.classList.add('hero-aem__card-text'); + + elements.forEach((sibling) => { + if (mobileImage && sibling.contains(mobileImage)) { + cardElementContainer.appendChild(sibling); + } else { + cardElementText.appendChild(sibling); + } + }); + + cardElementContainer.appendChild(cardElementText); + + return cardElementContainer; +} + +function getOperatingSystem(userAgent) { + const systems = [ + ['Windows NT 10.0', 'Windows 10'], + ['Windows NT 6.2', 'Windows 8'], + ['Windows NT 6.1', 'Windows 7'], + ['Windows NT 6.0', 'Windows Vista'], + ['Windows NT 5.1', 'Windows XP'], + ['Windows NT 5.0', 'Windows 2000'], + ['X11', 'X11'], + ['Linux', 'Linux'], + ['Android', 'Android'], + ['iPhone', 'iOS'], + ['iPod', 'iOS'], + ['iPad', 'iOS'], + ['Mac', 'MacOS'], + ]; + + return systems.find(([substr]) => userAgent.includes(substr))?.[1] || 'Unknown'; +} + +function openUrlForOs(urlMacos, urlWindows, urlAndroid, urlIos, selector) { + // Get user's operating system + const { userAgent } = navigator; + const userOS = getOperatingSystem(userAgent); + // Open the appropriate URL based on the OS + let openUrl; + switch (userOS) { + case 'MacOS': + openUrl = urlMacos; + break; + case 'Windows 10': + case 'Windows 8': + case 'Windows 7': + case 'Windows Vista': + case 'Windows XP': + case 'Windows 2000': + openUrl = urlWindows; + break; + case 'Android': + openUrl = urlAndroid; + break; + case 'iOS': + openUrl = urlIos; + break; + default: + openUrl = null; // Fallback or 'Unknown' case + } + if (openUrl) { + selector.href = openUrl; + } +} + +// Function to dispatch 'shadowDomLoaded' event +function dispatchShadowDomLoadedEvent() { + const event = new CustomEvent('shadowDomLoaded', { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + window.dispatchEvent(event); +} + +export default function decorate(block, options) { + const { + product, conditionText, saveText, MacOS, Windows, Android, IOS, mainProduct, + alignContent, height, type, send2datalayer, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + let blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + if (type) blockParent.classList.add(type); + } + + let [richText, mainDesktopImage, richTextCard, columnsCard] = block.children; + + // Configuration for new elements + richText.classList.add('hero-aem__card__desktop', 'col-md-6'); + if (alignContent === 'center') { + richText.classList.add('hero-aem__card__desktop--center'); + } + + if (height) { + // eslint-disable-next-line array-callback-return + Array.from(block.children).map((child) => { + child.style.maxHeight = `${height}px`; + }); + } + mainDesktopImage.classList.add('col-md-6'); + mainDesktopImage.children[0].classList.add('h-100'); + + let mobileImage = block.querySelector('.hero-aem__card__desktop div > p > picture'); + if (mobileImage) { + mobileImage.classList.add('hero-aem__mobile-image'); + } else { + mobileImage = ''; + } + + // Get all the siblings after h1 + const cardElements = Array.from(block.querySelectorAll('h1 ~ *')); + // Put the siblings in a new div and append it to the block + const cardElementContainer = createCardElementContainer(cardElements, mobileImage); + + // Append the container after h1 + block.querySelector('h1').after(cardElementContainer); + + const desktopImage = block.querySelector('.hero-aem > div > div > picture'); + desktopImage.classList.add('hero-aem__desktop-image'); + + if (product && options?.store) { + const [prodName, prodUsers, prodYears] = product.split('/'); + + const buyLink = block.querySelector('a[href*="buylink"]'); + createPricesElement(options.store, conditionText, saveText, prodName, prodUsers, prodYears, buyLink, send2datalayer) + .then((pricesBox) => { + // dataLayer push with all the products + if (options && send2datalayer) { + window.adobeDataLayer.push({ + event: 'product loaded', + product: { + [mainProduct === 'false' ? 'all' : 'info']: dataLayerProducts, + }, + }); + } + + // If buyLink exists, apply styles and insert pricesBox + if (buyLink) { + buyLink.classList.add('button', 'primary'); + buyLink.parentNode.parentNode.insertBefore(pricesBox, buyLink.parentNode); + dispatchShadowDomLoadedEvent(); + return; + } + + // If buyLink does not exist, apply styles to simpleLink + const simpleLink = block.querySelector('.hero-aem__card-text a'); + if (simpleLink) { + simpleLink.classList.add('button', 'primary'); + simpleLink.parentNode.parentNode.insertBefore(pricesBox, simpleLink.parentNode); + } + + dispatchShadowDomLoadedEvent(); + }); + } else { + // If there is no product, just add the button class and dispatch the event + const simpleLink = block.querySelector('.hero-aem__card-text a'); + if (simpleLink) { + simpleLink.classList.add('button', 'primary'); + } + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + } + + let breadcrumbTable = block.querySelector('table'); + + if (breadcrumbTable && breadcrumbTable.textContent.includes('breadcrumb')) { + breadcrumbTable.classList.add('hero-aem__breadcrumb'); + // delete the first row + breadcrumbTable.deleteRow(0); + } + + let freeDownloadButton = block.querySelector('a[href*="#free-download"]'); + if (freeDownloadButton) { + freeDownloadButton.classList.add('button', 'free-download'); + openUrlForOs(MacOS, Windows, Android, IOS, freeDownloadButton); + } + + if (columnsCard) { + const columnsCardChildren = Array.from(columnsCard.children); + const cardElement = document.createElement('div'); + cardElement.classList.add('aem-two-cards'); + // Determine the appropriate column width class based on the number of cards + const columnWidthMdClass = columnsCardChildren.length === 2 ? 'col-md-6' : 'col-md-4'; + const columnWidthLgClass = columnsCardChildren.length === 2 ? 'col-lg-3' : 'col-lg-3'; + + const columnCardsHtml = columnsCardChildren.map((col) => ` +
+
+ ${col.innerHTML} +
+
`).join(''); + + cardElement.innerHTML = ` +
+
+ ${richTextCard.innerHTML} +
+ ${columnCardsHtml} +
+ `; + + block.appendChild(cardElement); + richTextCard.innerHTML = ''; + columnsCardChildren.forEach((col) => col.remove()); + } +} diff --git a/solutions/blocks/hero/hero.css b/_src/blocks/hero/hero.css similarity index 74% rename from solutions/blocks/hero/hero.css rename to _src/blocks/hero/hero.css index 37ee4e0c4..e3ba878d5 100644 --- a/solutions/blocks/hero/hero.css +++ b/_src/blocks/hero/hero.css @@ -1,3 +1,5 @@ +/* stylelint-disable no-descending-specificity */ + /* block specific CSS goes here */ :root { /* hero font size */ @@ -21,9 +23,14 @@ --breadcrumbs-font-size-s: 12px; } +main .hero { + background-color: #F6F6F6; + position: relative; + padding: 0; + min-height: 300px; +} /* breadcrumbs */ - main .hero .hero-content .breadcrumb { font-weight: var(--font-weight-bold); color: #dedede; @@ -83,6 +90,28 @@ main .hero-container { margin: 0 auto; } +main .hero-container.blue-title .hero-content > div { + width: 100%; +} + +main .hero-container.blue-title .hero-content h1 { + --tw-text-opacity: 1; + color: rgb(0 110 255 / var(--tw-text-opacity)); +} + +main .hero-container.migration .hero-content h2 { + font-size: 22px; + font-weight: 500; + line-height: 1.25; + margin-top: 1em; + margin-bottom: 9px; +} + +main .hero-container.migration .hero-content p em { + font-size: 1.125rem; + font-style: normal; +} + main .hero .hero-content > div { width: 100%; } @@ -91,16 +120,41 @@ main .hero-container .hero-wrapper { padding: 0; } -main .hero { - position: relative; - padding: 0; - min-height: 300px; +main .hero.new2024design::after { + display: none; } main .hero.black-background { background-color: var(--dark-background-color); } +main .hero.new2024design * { + font-weight: normal; + font-family: "IBM Plex Sans", sans-serif; + color: white; +} + +main .hero.new2024design .hero-picture:last-of-type { + display: none; +} + +main .hero.new2024design strong { + font-weight: 600; +} + +main .hero-container.breadcrumb-hidden .breadcrumb a { + color: transparent; +} + +main .hero-container.breadcrumb-hidden .breadcrumb a::after { + color: transparent; +} + +main .hero.black-background::after { + content: none; + background-color: transparent; +} + main .hero.comparison { height: 600px; } @@ -121,6 +175,41 @@ main .hero .hero-content { position: relative; } +main .hero.new2024design { + max-width: 1200px; + margin: auto; +} + +main .hero.new2024design .hero-content:last-of-type { + padding: 0 2em; +} + +main .hero.new2024design .hero-picture { + padding: 0; + min-height: 0; +} + +main .hero.new2024design .hero-picture img { + padding: 0; + border-radius: 10px; + object-fit: contain; +} + +main .hero.new2024design h1 { + font-size: var(--hero-font-size-l); + margin: 0; +} + +main .hero.new2024design p { + font-size: 16px; +} + +main .hero.new2024design .hero-content.hero-content img { + padding: 0; + border-radius: 10px; + object-fit: contain; +} + main .hero .hero-content .right-col { display: flex; justify-content: center; @@ -128,6 +217,9 @@ main .hero .hero-content .right-col { } main .hero.black-background .hero-content { + padding: 17px var(--body-padding) 56px; + display: flex; + flex-direction: column; background: linear-gradient(90deg, #000 0%, #000 15%, #fff0 100%); } @@ -151,6 +243,11 @@ main .hero h2 { letter-spacing: .003em; } +main .hero.black-background h1 { + font-size: var(--hero-h1-font-size); + margin: 0 0 25px; +} + main .hero h2, main .hero h4 { padding: 0; @@ -211,7 +308,7 @@ main .hero p.button-container { gap: 2px; } -main .hero p.button-container.discount-bubble-container{ +main .hero p.button-container.discount-bubble-container { padding-top: 0; } @@ -231,12 +328,12 @@ main .hero a.button { margin: 8px 13px 0 0; } -main .hero a.button.modal { +main .hero a.button.modal, main .hero a.button.central { padding: 0 28px 0 0; min-width: unset; } -@media (min-width: 1400px){ +@media (min-width: 1400px) { main .hero a.button { min-width: 360px; justify-content: center; @@ -252,7 +349,6 @@ main .hero a.button span.button-text { font-weight: var(--font-weight-bold); } - main .hero .discount-bubble { background: #2cb43d; border-radius: 50%; @@ -377,11 +473,39 @@ main .hero .hero-awards li::after { content: none; } +@media(max-width: 989px) { + main .hero.new2024design { + background-color: #006FFF; + min-height: auto; + padding: 2em 0; + } + + main .hero.new2024design .hero-picture { + display: none; + } +} + +@media(max-width: 991px) { /* tablet */ + main .hero.new2024design .breadcrumb { + display: none; + } +} + @media(min-width: 767px) { /* tablet */ :root { --hero-h1-font-size: 42px; } + main .hero.new2024design h1 { + font-size: var(--hero-font-size-xl); + margin: 0; + } + + main .hero.new2024design * { + color: white; + background-color: transparent; + } + main .hero h2 { font-size: 20px; } @@ -394,9 +518,21 @@ main .hero .hero-awards li::after { margin: 0 9px; } + main .hero-container.blue-title .hero-content > div { + width: 630px; + } } @media (min-width: 990px) { /* desktop */ + main .hero.new2024design .hero-content:last-of-type { + min-height: 360px; + padding: 2em; + } + + main .hero.new2024design .hero-picture { + display: block; + height: 430px; + } main .hero .hero-content > div.left-col { width: 50%; @@ -419,9 +555,10 @@ main .hero .hero-awards li::after { main .hero .hero-picture { position: absolute; top: 0; - bottom: 0; + bottom: auto; left: 0; right: 0; + height: 100%; } main .hero p { @@ -443,6 +580,16 @@ main .hero .hero-awards li::after { flex-direction: row; } + main .hero.black-background .hero-content { + max-width: var(--section-desktop-max-width); + padding-left: var(--section-desktop-padding); + padding-right: var(--section-desktop-padding); + padding-top: 115px; + display: flex; + flex-direction: row; + min-height: unset; + } + main .hero a.button.primary { min-width: 360px; } @@ -516,4 +663,11 @@ main .hero .hero-awards li::after { padding-left: var(--section-large-desktop-padding); padding-right: var(--section-large-desktop-padding); } + + main .hero.black-background .hero-content { + max-width: var(--section-large-desktop-max-width); + padding-left: var(--section-large-desktop-padding); + padding-right: var(--section-large-desktop-padding); + } + } diff --git a/solutions/blocks/hero/hero.js b/_src/blocks/hero/hero.js similarity index 68% rename from solutions/blocks/hero/hero.js rename to _src/blocks/hero/hero.js index 09fd3c3fb..b7bdc84b0 100644 --- a/solutions/blocks/hero/hero.js +++ b/_src/blocks/hero/hero.js @@ -4,7 +4,7 @@ import { createNanoBlock, renderNanoBlocks, fetchProduct, -} from '../../scripts/utils.js'; +} from '../../scripts/utils/utils.js'; /** * Builds hero block and prepends to main in a new section. @@ -20,32 +20,39 @@ function buildHeroBlock(element) { const subSection = document.querySelector('div.hero div'); subSection.classList.add('hero-content'); - const breadcrumb = createTag('div', { class: 'breadcrumb' }); - document.querySelector('div.hero div div:first-child').prepend(breadcrumb); + const isHomePage = window.location.pathname.split('/').filter((item) => item).length === 1; + + if (!isHomePage) { + const breadcrumb = createTag('div', { class: 'breadcrumb' }); + document.querySelector('div.hero div div:first-child').prepend(breadcrumb); + } const pictureEl = document.createElement('div'); pictureEl.classList.add('hero-picture'); pictureEl.append(picture); - section.prepend(pictureEl); pictureParent.remove(); } } -createNanoBlock('discount', (code, variant) => { +createNanoBlock('discount', (code, label = 'Discount') => { + // code = "av/3/1" + const [product, unit, year] = code.split('/'); + const variant = `${unit}u-${year}y`; + const root = document.createElement('div'); root.classList.add('discount-bubble'); root.innerHTML = ` --% - Discount + ${label} `; - fetchProduct(code, variant) - .then((product) => { - if (product.discount) { + fetchProduct(product, variant) + .then((productResponse) => { + if (productResponse.discount) { const discount = Math.round( - (1 - (product.discount.discounted_price) / product.price) * 100, + (1 - (productResponse.discount.discounted_price) / productResponse.price) * 100, ); root.querySelector('.discount-bubble-0').textContent = `${discount}%`; } else { @@ -65,6 +72,11 @@ createNanoBlock('discount', (code, variant) => { * @param {Element} block The hero block element */ export default async function decorate(block) { + const { + // this defines wether the modals automatically refresh or not in the hero banner + stopAutomaticModalRefresh, + } = block.closest('.section').dataset; + buildHeroBlock(block); // Eager load images to improve LCP [...block.querySelectorAll('img')].forEach((el) => el.setAttribute('loading', 'eager')); @@ -94,5 +106,12 @@ export default async function decorate(block) { sibling = sibling.previousElementSibling; } } + + // set the modal buttons in the hero banner to not refresh the modal on click + if (stopAutomaticModalRefresh === 'true') { + block.querySelectorAll('a.modal.button').forEach((modalButton) => { + modalButton.setAttribute('data-stop-automatic-modal-refresh', true); + }); + } } } diff --git a/solutions/blocks/image-columns/image-columns.css b/_src/blocks/image-columns/image-columns.css similarity index 85% rename from solutions/blocks/image-columns/image-columns.css rename to _src/blocks/image-columns/image-columns.css index 4ac2bc5cc..f0f074fc0 100644 --- a/solutions/blocks/image-columns/image-columns.css +++ b/_src/blocks/image-columns/image-columns.css @@ -1,3 +1,5 @@ +/* stylelint-disable no-descending-specificity */ +/* stylelint-disable selector-class-pattern */ .image-columns-container ul { padding-left: 0; } @@ -35,6 +37,10 @@ justify-items: center; } +.image-columns.text_smaller > div > .image-columns-txt-col { + flex: 0 1 45%; +} + .image-columns > div > .image-columns-txt-col { flex: 0 1 45%; } @@ -89,6 +95,10 @@ margin-top: 0; } +.image-columns.trusted > div > .image-columns-txt-col { + flex: 0 1 25%; +} + @media (min-width: 992px) { .image-columns > div > .image-columns-txt-col h3 { margin-bottom: 26px; @@ -131,3 +141,9 @@ order: unset; } } + +@media (min-width: 1600px) { /* large desktop */ + .image-columns-wrapper { + max-width: var(--section-large-desktop-max-width); + } +} diff --git a/solutions/blocks/image-columns/image-columns.js b/_src/blocks/image-columns/image-columns.js similarity index 100% rename from solutions/blocks/image-columns/image-columns.js rename to _src/blocks/image-columns/image-columns.js diff --git a/_src/blocks/marquee/marquee.css b/_src/blocks/marquee/marquee.css new file mode 100644 index 000000000..01ed88103 --- /dev/null +++ b/_src/blocks/marquee/marquee.css @@ -0,0 +1,69 @@ +/* stylelint-disable custom-property-pattern */ +.marquee-container.section { + padding: 0; + position: relative; + overflow: unset; + max-width: 100%; +} + +.marquee-container .marquee.block { + height: 150px; + display: flex; + flex-direction: column; + width: 100%; +} + +.marquee-container .title { + font: normal normal 600 12px/15px "IBM Plex Sans", sans-serif; + letter-spacing: 0; +} + +.marquee-container .marquee-content { + display: flex; + animation: scrolling 10s linear infinite; + + --translateX: 100%; + + height: 100%; +} + +.marquee-container .marquee-item { + flex: 0 0 85px; + margin: 0 20px; +} + +.marquee-container .marquee-item img { + display: block; + width: 100%; + object-fit: contain; +} + +.marquee-container .outer-wrapper { + width: 100%; + height: 100%; + overflow: hidden; +} + +@keyframes scrolling { + from { transform: translateX(0); } + to { transform: translateX(calc(var(--translateX) * -1)); } +} + +@media (min-width: 990px) { + .marquee-container .marquee.block { + height: 120px; + } + + .marquee-container .title { + font: normal normal 600 18px/23px "IBM Plex Sans", sans-serif; + position: absolute; + top: -45px; + z-index: 1; + } +} + +@media (min-width: 1600px) { + .marquee-container .title { + margin-left: -25px + } +} diff --git a/_src/blocks/marquee/marquee.js b/_src/blocks/marquee/marquee.js new file mode 100644 index 000000000..8bacc8c1e --- /dev/null +++ b/_src/blocks/marquee/marquee.js @@ -0,0 +1,83 @@ +import { debounce, getDatasetFromSection } from '../../scripts/utils/utils.js'; +import { isView } from '../../scripts/scripts.js'; + +export default async function decorate(block) { + const defaultBackgroundColor = '#004299'; + const SLIDE_SIZE_ENUM = { + MOBILE: 85 + 20 * 2, + TABLET_UP: 85 + 20 * 2, + }; + + const SPEED_ANIMATION = 0.6; + + const [title, ...initialSlideList] = [...block.children]; + + function getCurrentViewportSlideSize() { + return isView('mobile') ? SLIDE_SIZE_ENUM.MOBILE : SLIDE_SIZE_ENUM.TABLET_UP; + } + function calculateSlideListBasedOnScreenWidth() { + const result = { + duplicatedSlides: null, + slidesToShift: null, + }; + + const currentViewportSlideSize = getCurrentViewportSlideSize(); + const clientWidth = window.innerWidth; + const spaceToFillMore = clientWidth - initialSlideList.length * currentViewportSlideSize; // ok + if (spaceToFillMore < 0) { + result.duplicatedSlides = initialSlideList.concat(initialSlideList); + result.slidesToShift = initialSlideList.length; + + return result; + } + // fill space + const fullWidthSlidesToFill = parseInt(spaceToFillMore / currentViewportSlideSize, 10); + const hasPartialSlideToFill = clientWidth % currentViewportSlideSize !== 0; + + result.duplicatedSlides = Array(fullWidthSlidesToFill) + .fill(initialSlideList).flatMap((slide) => slide); + + if (!hasPartialSlideToFill) { + result.duplicatedSlides = result.duplicatedSlides.concat(result.duplicatedSlides); + result.slidesToShift = result.duplicatedSlides.length; + + return result; + } + + // need to apply the patch here + result.duplicatedSlides = result.duplicatedSlides.concat(initialSlideList); + result.slidesToShift = result.duplicatedSlides.length; + result.duplicatedSlides = result.duplicatedSlides.concat(result.duplicatedSlides); + + return result; + } + + function updateTranslation(slidesToShift) { + const content = block.querySelector('.marquee-content'); + content.style.animationDuration = `${slidesToShift / SPEED_ANIMATION}s`; + content.style.setProperty('--translateX', `${getCurrentViewportSlideSize() * slidesToShift}px`); + } + + function render() { + const blockDataset = getDatasetFromSection(block); + const { background_color: backgroundColor } = blockDataset; + block.style.background = backgroundColor || defaultBackgroundColor; + + const { duplicatedSlides, slidesToShift } = calculateSlideListBasedOnScreenWidth(); + + block.innerHTML = ` +
${title.textContent}
+
+
+ ${duplicatedSlides.map((slide) => `
${slide.querySelector('picture').outerHTML}
`).join('')} +
+
+ `; + + updateTranslation(slidesToShift); + } + + render(); + + window.addEventListener('resize', debounce(render, 250)); +} diff --git a/_src/blocks/money-back/money-back.css b/_src/blocks/money-back/money-back.css new file mode 100644 index 000000000..9ac08a531 --- /dev/null +++ b/_src/blocks/money-back/money-back.css @@ -0,0 +1,289 @@ +.money-back-wrapper { + text-align: center; +} + +@media (min-width: 992px) { /* desktop */ + .money-back-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +@media (min-width: 1600px) { /* large desktop */ + .money-back-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +.money-back.block { + background-color: #EDF9FF; + border-radius: 20px; +} + +.creator-money-back .money-back.block { + background-color: transparent; +} + +.money-back.block.background-white { + background-color: white; +} + +.money-back-container h3 { + font: normal normal bold 32px/37px var(--body-font-family); + text-align: center; + margin-bottom: 56px; +} + +.money-back-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.money-back-container .icon svg { + width: auto; + height: 32px; + padding-right: 2px; +} + +.creator-money-back.money-back-container .icon svg { + width: auto; + height: 60px; + padding-right: 2px; +} + +.money-back > ul { + list-style: none; + margin: 0; + padding: 0; + display: inline-block; + } + +.creator-money-back .money-back > ul { + display: flex; + } + +.money-back > ul > li { + display: inline-block; + padding: 8px; + margin: 0 37px; + text-align: center; + width: 268px; + vertical-align: top; + font: normal normal normal 14px/16px var(--body-font-family); + } + + .creator-money-back .money-back > ul > li { + background: #F5F5F7; + border-radius: 20px; + padding: 60px 68px; + flex: 1; + width: auto; + text-align: left; + margin: 0 30px; + vertical-align: top; + font: normal normal normal 20px/23px Arial, sans-serif; + } + + .money-back > ul > li h6 { + font: normal normal bold 18px/16px var(--body-font-family); + } + + .money-back > ul > li p { + font: normal normal normal 14px/16px var(--body-font-family); + } + + .creator-money-back .money-back > ul > li h4 { + font: normal normal bold 32px/38px "IBM Plex Sans", sans-serif; + } + + .creator-money-back .money-back > ul > li p { + font: normal normal normal 20px/26px Arial, sans-serif; + } + + .money-back > ul > li p:first-of-type { + margin-bottom: 0; + } + + .creator-money-back .money-back > ul > li p:first-of-type { + margin: 0; + } + + .money-back > ul > li a { + font: normal normal normal 14px/16px var(--body-font-family); + margin-bottom: 0; + margin-top: 20px; + text-decoration: none; + color: #006EFF; + display: block; + } + + .money-back > ul > li strong { + display: inline-block; + font: normal normal bold 18px/16px var(--body-font-family); + padding-bottom: 11px; + } + + .money-back .default-content-wrapper { + text-align: center; + } + + .money-back > ul > li p.button-container { + margin-top: 0; + } + + .money-back a.button { + font: normal normal normal 14px/16px var(--body-font-family); + margin-top: 20px; + padding: 0; + background: transparent; + border: none; + color: #006EFF; + } + + .money-back a.button:hover { + text-decoration: underline; + color: #006EFF; + background: transparent; + } + + .money-back a.button span.button-text { + transition: none; + } + + .money-back a.button:hover span.button-text { + transform: none; + } + + .money-back a.button::after { + content: ''; + width: 0; + height: 0; + margin: 0; + transition: none; + } + + .creator-money-back .money-back > ul > li a { + min-width: 230px; + height: 48px; + padding: 10px 10px 10px 25px; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 40px; + justify-content: center; + font: normal normal 500 18px / 24px Roboto, sans-serif; + color: white; + } + + .creator-money-back .money-back > ul > li a:hover { + color: white; + background-color: var(--button-background-color); + text-decoration: none; + } + + .creator-money-back .money-back a.button span.button-text { + transition: transform .2s cubic-bezier(.4,0,.2,1); + } + + .creator-money-back .money-back > ul > li a.button:hover span.button-text { + transform: translate(-10px, 0); + } + + .creator-money-back .money-back > ul > li a:active { + color: white; + background-color: var(--button-background-color); + border: 0; + } + + .creator-money-back .money-back a.button::after { + content: ''; + width: 24px; + height: 24px; + margin-left: -10px; + transition: all .2s cubic-bezier(.4,0,.2,1); + } + + .money-back .icon { + height: 32px; + margin-bottom: 9px; + fill: #006EFF; + display: flex; + } + + .creator-money-back .money-back .icon { + height: 60px; + margin-bottom: 23px; + fill: #006DFF; + display: flex; + } + + .money-back img { + height: 55px; + margin-bottom: 9px; + fill: #006EFF; + } + + .creator-money-back .money-back img { + height: 60px; + fill: #006df7; + display: flex; + } + +@media (max-width: 991px) { /* mobile/tablet */ + .money-back-wrapper { + padding: var(--body-padding); + } + + .money-back > ul { + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + grid-gap: 14px; + flex-direction: column; + } + + .money-back > ul > li { + margin: 0; + } + + .money-back-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (max-width: 1259px) { + .creator-money-back .money-back > ul > li { + margin-bottom: 40px; + } +} + +@media (min-width: 1200px) { + .money-back-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .money-back-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (max-width: 991px) { + .creator-money-back .money-back > ul > li { + margin: 0; + padding: 24px; + } + + .creator-money-back .money-back > ul > li p.button-container { + text-align: center; + } +} \ No newline at end of file diff --git a/_src/blocks/money-back/money-back.js b/_src/blocks/money-back/money-back.js new file mode 100644 index 000000000..e4fbe7ba9 --- /dev/null +++ b/_src/blocks/money-back/money-back.js @@ -0,0 +1,23 @@ +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + const ul = document.createElement('ul'); + [...block.children].forEach((row) => { + const li = document.createElement('li'); + li.innerHTML = row.innerHTML; + + ul.append(li); + }); + + block.textContent = ''; + block.append(ul); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/new-prod-boxes-vsb/new-prod-boxes-vsb.css b/_src/blocks/new-prod-boxes-vsb/new-prod-boxes-vsb.css new file mode 100644 index 000000000..6ad0d2b88 --- /dev/null +++ b/_src/blocks/new-prod-boxes-vsb/new-prod-boxes-vsb.css @@ -0,0 +1,624 @@ +/* stylelint-disable */ +.new-prod-boxes-vsb-container { + padding-bottom: 0; + font-family: 'Arial', sans-serif; + margin: clamp(10px, 25px, 15px) 0; +} + +.new-prod-boxes-vsb-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-left: auto; + margin-right: auto; + margin-top: 1em !important; +} + +.new-prod-boxes-vsb-container .default-content-wrapper p:has(> a) { + text-align: center; +} + +.new-prod-boxes-vsb-container .price_box { + min-height: 64px; + margin-top: 20px; +} + +.new-prod-boxes-vsb-container .default-content-wrapper h2 { + text-align: center; + font-size: 32px; + line-height: 37px; + max-width: 550px; + margin: auto; + margin-bottom: 20px; +} +.new-prod-boxes-vsb-container .default-content-wrapper p { + text-align: center; + font-size: 14px; + line-height: 17px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb { + margin: 0 auto; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box { + flex: 1; + max-width: 410px; + margin: 8px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box { + position: relative; + height: 100%; + background-color: #F6F6F6; + border-radius: 20px; + padding: 25px; + margin: 0 auto; + display: flex; + flex-direction: column; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .greenTag2 { + height: 30px; + max-width: 350px; + width: 86%; + font-family: Arial, sans-serif; + color: white; + text-align: center; + background-color: #1C7928; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + padding-top: 7px; + position: absolute; + top: -39px; + left: 7%; + box-sizing: content-box; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box h2 { + font-weight: bold; + font-size: 24px; + line-height: 26px; + font-family: Arial, sans-serif; + margin-top: 10px; + margin-bottom: 4px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box h2 a { + transition: all 0.5s ease; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box h2 a:hover { + text-decoration: none; + transition: all 0.5s ease; +} + +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box h3 { + font-size: 22px; + line-height: 25px; + font-family: "IBM Plex Sans", Arial, sans-serif; + margin-top: 10px; + margin-bottom: 4px; + font-weight: normal; + max-width: 340px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .blueTag { + font-size: var(--body-font-size-xs); + font-family: Arial, sans-serif; + color: white; + text-align: center; + background-color: #026DFF; + display: inline-block; + border-radius: 20px; + padding: 6px 16px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .blueTag div { + display: flex; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .blueTag img { + height: 14px; + margin-right: 5px; + margin-top: -5px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .subtitle { + font-size: clamp(10px, 14px, 14px); + font-family: Arial, sans-serif; + margin-bottom: 0; + line-height: 1.25; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .subtitle.fixed_height { + min-height: 80px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb.subtitle-bigger .prod_box .inner_prod_box .subtitle { + font-size: clamp(10px, 16px, 16px); + max-height: 60px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb.add-margin-top { + margin-top: 82px; +} + +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .richTextArea { + line-height: 17px; + margin-top: 10px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box hr { + border: 1px solid #D1D1D1; + margin: 10px 0; +} + +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box hr:first-of-type { + margin-bottom: 0; +} + +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box hr:last-of-type { + margin-bottom: 10px; +} + +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .save_price_box { + display: flex; + justify-content: left; + align-items: center; + margin-bottom: 8px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .save_price_box .prod-oldprice { + font-size: var(--heading-font-size-xs); + line-height: var(--heading-font-size-xs); + text-decoration: line-through; + margin-right: 10px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .save_price_box .prod-percent { + font-size: 13px; + line-height: 15px; + color: white; + background-color: #68BA68; + border-radius: 11px; + padding: 4px 10px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .prices_box { + display: flex; + justify-content: left; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .prices_box .prod-newprice { + font-size: var(--heading-font-size-xl); + line-height: var(--heading-font-size-xl); +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .prices_box sup { + margin: 15px 0 0 5px; + font-size: var(--heading-font-size-s); + line-height: var(--heading-font-size-s); +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .billed { + font-size: 12px; + font-family: Arial, sans-serif; + line-height: 13px; + margin: 7px 0; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .buy-btn a.red-buy-button { + width: 100%; + text-transform: none; + font-size: 14px; + line-height: 14px; + font-weight: 500 !important; + padding: 10px 1% !important; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .undeBuyLink { + font-size: 12px; + font-family: Arial, sans-serif; + line-height: 13px; + margin: 7px 0; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists { + font-family: Arial, sans-serif; + color: transparent; + display: flex; + flex-grow: 1; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists p { + margin: 0; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists u { + font-size: var(--body-font-size-xs); + text-decoration: none; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists ul { + margin: 0; + margin-bottom: -5px; + padding: 0; + color: black; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists ul li:first-of-type { + font-size: 16px; + line-height: 18px; + text-decoration: none; + list-style-type: none; + font-weight: bold; + font-family: Arial, sans-serif; + margin-bottom: 0.5rem; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists ul li:first-of-type.has_arrow::before { + content: ""; + margin: 0 5px 20px 0; + background: url("https://bitdefender.com/pages/icons/arrow-left-blue.png") no-repeat center transparent; + width: 20px; + height: 20px; + background-size: 15px 12px; + float: left; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists ul li:first-of-type.has_arrow_right .arrow-right { + background: url("https://bitdefender.com/icons/arrow-right-solid.svg") no-repeat center transparent; + width: 20px; + height: 20px; + background-size: 15px 12px; + position: relative; + top: 4px; + display: inline-flex; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) { + font-size: 14px; + line-height: 17px; + margin-bottom: 8px; + list-style-type: none; + background: url("https://bitdefender.com/icons/circle-check-sharp-solid.svg") top 2px left no-repeat transparent; + padding-left: 22px; + background-size: 13px; + position: relative; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) > span:last-of-type { + position: absolute; + background-color: white; + padding: 10px; + border-radius: 10px; + margin-bottom: 28px; + left: 0; + bottom: 0; + z-index: 1; + font-size: 12px; + box-shadow: 4px 4px 7px -8px #000; + display: none; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) > span:last-of-type::before { + content: ""; + position: absolute; + left: 17px; + bottom: -20px; + border-width: 10px; + border-style: solid; + border-color: white transparent transparent; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type):hover > span:last-of-type { + display: block; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) u { + font-size: 14px; + font-weight: bold; + color: white; + border-radius: 20px; + padding: 2px 21px 2px 7px; + background: url("https://bitdefender.com/pages/images/icons/individual.svg") center right 6px no-repeat #026DFF; + background-size: auto 12px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box .benefitsLists ul:nth-of-type(2) { + min-height: 5em; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box.hasGreenTag { + margin-top: 45px; +} +.new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box.hasGreenTag .inner_prod_box { + box-shadow: 0 3px 7px 0 #C1C1C1; +} + +.new-prod-boxes-vsb-container .prod-oldprice { + font-size: 16px; + text-decoration: line-through; +} +.new-prod-boxes-vsb-container .prod-save { + color: #1C7928; + font-weight: bold; +} +.new-prod-boxes-vsb-container .prod-newprice { + font-size: 40px; + font-weight: bold; +} +.new-prod-boxes-vsb-container .newprice-container { + line-height: 1; +} +.new-prod-boxes-vsb-container .newprice-container sup { + position: relative; + top: -20px; +} + +.new-prod-boxes-vsb-container .button.primary { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: block; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.new-prod-boxes-vsb-container .new-prod-boxes-vsb.smallerbuttons .button.primary { + display: inline-block; + min-width: 144px; +} + +.new-prod-boxes-vsb-container .button.primary.no-arrow::after { + content: none; +} + +.new-prod-boxes-vsb-container .button.primary:hover { + color: white; + background-color: #B10304; + border-color: #B10304; +} + +.new-prod-boxes-vsb-container .button.primary:active { + background-color: #920A0A; + border-color: #920A0A; +} + +.new-prod-boxes-vsb-container p em a { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: block; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #006EFF; + background-color: transparent; + border: 2px solid #006EFF; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.new-prod-boxes-vsb-container .new-prod-boxes-vsb.smallerbuttons p em a { + display: inline-block; + min-width: 144px; +} + +.new-prod-boxes-vsb-container p em a:hover { + color: white; + background-color: #006DFF; +} + +.new-prod-boxes-vsb-container p em a:active { + background-color: #0D499B; +} + +.new-prod-boxes-vsb-container .icon svg { + width: 12px; + height: 14px; + padding-right: 2px; + fill: #fff; +} + +.new-prod-boxes-vsb-container .blue-pill { + background-color: #026DFF; + padding: 2.5px 6.7px; + border-radius: 20px; + color: white; + font-style: normal; + font-size: 11px; + letter-spacing: 0px; + font-weight: bold; + display: inline-flex; + justify-content: center; +} + +.new-prod-boxes-vsb-container .blue-pill .icon { + position: relative; + top: 1px; + margin-left: 1px; +} + +.new-prod-boxes-vsb-container .blue-pill svg { + width: 9px; + height: 9px; +} + +.switchBox { + text-align: center; + padding-bottom: 75px; +} + +.switch { + position: relative; + display: inline-flex; + align-items: center; + width: 302px; + height: 44px; + background-color: #016DFF; + border-radius: 22px; +} + +.switch input { + display: none; +} + +.slider { + position: absolute; + content: ""; + height: 40px; + width: 150px; + left: 2px; + bottom: 2px; + background-color: white; + border-radius: 20px; + transition: all 0.4s; +} + +.switch input:checked + .slider { + transform: translateX(149px); +} + +.label { + font-family: Arial, Helvetica, sans-serif; + width: 50%; + text-align: center; + font-weight: bold; + line-height: 34px; + font-size: 16px; + color: white; + transition: color 0.4s; +} + +.label.right { + z-index: 10; + color: black; +} + +.label.left { + z-index: 10; +} + +.switch input:checked ~ .label.right { + transition: color 0.4s; + color: white !important; +} + +.switch input ~ .label .icon { + position: relative; + margin-right: 10px; + top: 2px; +} + +.switch input ~ .label .icon svg { + width: 14px; + height: 16px; +} + +.switch input ~ .label.right .icon svg { + fill: #026DFF; +} + +.switch input:checked ~ .label.right .icon svg { + fill: white; +} + +.switch input:checked ~ .label.left { + transition: color 0.4s; + color: black; +} + +.switch input:checked ~ .label.left .icon svg { + fill: #026DFF; +} + +.prod-box.individual-box { + transition: all 0.4s; +} + +.prod_box.family-box { + display: none; + transition: all 0.4s; +} + +.plan-switcher { + display: flex; + align-items: center; + font-weight: bold; + margin-bottom: 24px; + margin-top: 16px; +} + +.plan-switcher input[type=radio] { + position: absolute; + opacity: 0; +} + +.plan-switcher .radio-label { + margin-right: 8px; +} + +.plan-switcher .radio-label::before { + content: ""; + background: #f4f4f4; + color: #006DFF; + border-radius: 100%; + border: 2px solid #006DFF; + display: inline-block; + width: 1.2rem; + height: 1.2rem; + position: relative; + margin-right: 9px; + vertical-align: top; + cursor: pointer; + text-align: center; + transition: all 250ms ease; +} + +.plan-switcher input[type=radio]:checked + .radio-label:before { + background-color: #3197EE; + box-shadow: inset 0 0 0 4px #f4f4f4; +} +.plan-switcher input[type=radio]:focus + .radio-label:before { + outline: none; + border-color: #3197EE; +} + +@media (max-width: 768px) { + .new-prod-boxes-vsb-container.we-container { + margin-top: 10px; + } + .new-prod-boxes-vsb-container .default-content-wrapper h2 { + text-align: left; + border-top: 1px solid #cbc8c8; + padding-top: 30px; + } + .new-prod-boxes-vsb-container .default-content-wrapper p { + text-align: left; + font-size: 14px; + line-height: 18px; + } + .new-prod-boxes-vsb-container .default-content-wrapper p br { + display: none; + } + .new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box .inner_prod_box hr { + border: 0 none; + } +} + +@media (min-width: 768px) { + .new-prod-boxes-vsb-container .new-prod-boxes-vsb { + flex-direction: row; + padding-bottom: 60px; + align-items: initial; + } + + .new-prod-boxes-vsb-container .new-prod-boxes-vsb .prod_box.hasGreenTag { + margin: 8px; + } +} + +@media (min-width: 992px) { + .new-prod-boxes-vsb-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .new-prod-boxes-vsb-container.we-container { + max-width: 1290px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/new-prod-boxes-vsb/new-prod-boxes-vsb.js b/_src/blocks/new-prod-boxes-vsb/new-prod-boxes-vsb.js new file mode 100644 index 000000000..4ad307986 --- /dev/null +++ b/_src/blocks/new-prod-boxes-vsb/new-prod-boxes-vsb.js @@ -0,0 +1,380 @@ +/* eslint-disable prefer-const */ +/* eslint-disable no-undef */ +/* eslint-disable max-len */ +let dataLayerProducts = []; +async function createPricesElement(storeOBJ, hideProducts, conditionText, saveText, prodName, prodUsers, prodYears, buylink, billed) { + if (hideProducts === 'true') { + return document.createElement('div'); + } + + const storeProduct = await storeOBJ.getProducts([new ProductInfo(prodName, 'consumer')]); + const storeOption = storeProduct[prodName].getOption(prodUsers, prodYears); + const price = storeOption.getPrice(); + const discountedPrice = storeOption.getDiscountedPrice(); + const discount = storeOption.getDiscount('valueWithCurrency'); + const buyLink = await storeOption.getStoreUrl(); + + let product = { + ID: storeOption.getAvangateId(), + name: storeOption.getName(), + devices: storeOption.getDevices(), + subscription: storeOption.getSubscription('months'), + version: storeOption.getSubscription('months') === 1 ? 'monthly' : 'yearly', + basePrice: storeOption.getPrice('value'), + discountValue: storeOption.getDiscount('value'), + discountRate: storeOption.getDiscount('percentage'), + currency: storeOption.getCurrency(), + priceWithTax: storeOption.getDiscountedPrice('value') || storeOption.getPrice('value'), + }; + dataLayerProducts.push(product); + const priceElement = document.createElement('div'); + priceElement.classList.add('hero-aem__prices'); + priceElement.innerHTML = ` +
+
+ ${price} + ${saveText} ${discount} +
+
+ ${discountedPrice} + ${conditionText || ''} +
+
+ ${billed ? `
${billed.innerHTML}
` : ''} + ${buylink.text}`; + buylink.remove(); + return priceElement; +} + +export default async function decorate(block, options) { + const { + // eslint-disable-next-line no-unused-vars + products, familyProducts, monthlyProducts, priceType, pid, mainProduct, + hideProducts, addRichTextZone, margintop, + } = block.closest('.section').dataset; + // if options exists, this means the component is being called from aem + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + } + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + + if (margintop) { + blockParent.style.marginTop = `${margintop}px`; + } + + let defaultContentWrapperElements = block.closest('.section').querySelector('.default-content-wrapper')?.children; + let individualSwitchText; + let familySwitchText; + if (defaultContentWrapperElements) { + [...defaultContentWrapperElements].forEach((element) => { + if (element.innerHTML.includes('<slider-1 ')) { + element.innerHTML = element.innerHTML.replace('<slider-1 ', ''); + individualSwitchText = element.innerHTML; + element.remove(); + } + if (element.innerHTML.includes('<slider-2 ')) { + element.innerHTML = element.innerHTML.replace('<slider-2 ', ''); + familySwitchText = element.innerHTML; + element.remove(); + } + }); + } + + let switchBox = document.createElement('div'); + if (individualSwitchText && familySwitchText) { + switchBox.classList.add('switchBox'); + switchBox.innerHTML = ` + + `; + + // Get the checkbox inside the switchBox + let switchCheckbox = switchBox.querySelector('#switchCheckbox'); + // Add an event listener to the checkbox + switchCheckbox.addEventListener('change', () => { + if (switchCheckbox.checked) { + let familyBoxes = block.querySelectorAll('.family-box'); + familyBoxes.forEach((box) => { + box.style.display = 'block'; + }); + + let individualBoxes = block.querySelectorAll('.individual-box'); + individualBoxes.forEach((box) => { + box.style.display = 'none'; + }); + } else { + let familyBoxes = block.querySelectorAll('.family-box'); + familyBoxes.forEach((box) => { + box.style.display = 'none'; + }); + + let individualBoxes = block.querySelectorAll('.individual-box'); + individualBoxes.forEach((box) => { + box.style.display = 'block'; + }); + } + }); + } + + const productsAsList = products && products.split(','); + const familyProductsAsList = familyProducts && familyProducts.split(','); + const combinedProducts = productsAsList.concat(familyProductsAsList); + const monthlyPricesAsList = monthlyProducts && monthlyProducts.split(','); + let monthlyPriceBoxes = {}; + let yearlyPricesBoxes = {}; + if (combinedProducts.length) { + await Promise.all([...block.children].map(async (prod, key) => { + // eslint-disable-next-line no-unused-vars + const [greenTag, title, blueTag, subtitle, radioButtons, richTextZone, billed, buyLink, undeBuyLink, benefitsLists, richText] = [...prod.querySelectorAll('div > div > table > tbody > tr')]; + const onSelectorClass = 'tsmd-10-1'; + const [prodName, prodUsers, prodYears] = combinedProducts[key].split('/'); + const [prodMonthlyName, prodMonthlyUsers, prodMonthlyYears] = monthlyPricesAsList ? monthlyPricesAsList[key].split('/') : []; + const featuresSet = benefitsLists.querySelectorAll('table'); + const featureList = Array.from(featuresSet).map((table) => { + const trList = Array.from(table.querySelectorAll('tr')); + const liString = trList.map((tr) => { + const tdList = Array.from(tr.querySelectorAll('td')); + // Extract the content of the first to be placed outside the
  • + let firstTdContent = tdList.length > 0 && tdList[0].textContent.trim() !== '' ? `${tdList[0].innerHTML}` : ''; + // Extract the content of the second (if present) inside a + const secondTdContent = tdList.length > 1 && tdList[1].textContent.trim() !== '' ? `${tdList[1].innerHTML}` : ''; + // Create the
  • combining the first and second td content + let liClass = ''; + if (firstTdContent === '') { + liClass += 'd-none'; + } + + if (firstTdContent.indexOf('?pill') !== -1) { + let pillText = firstTdContent.match(/\?pill (\w+)/); + let iconElement = firstTdContent.match(/(.*?)<\/span>/); + if (pillText) { + let icon = tdList[0].querySelector('span'); + const pillElement = document.createElement('span'); + pillElement.classList.add('blue-pill'); + pillElement.innerHTML = `${pillText[1]}${iconElement ? iconElement[0] : ''}`; + firstTdContent = firstTdContent.replace(pillText[0], `${pillElement.outerHTML}`); + if (icon) { + let count = 0; + firstTdContent = firstTdContent.replace(new RegExp(icon.outerHTML, 'g'), (match) => { + count += 1; + return (count === 2) ? '' : match; + }); + } + } + } + if (firstTdContent.indexOf('?info') !== -1) { + let pillText = firstTdContent.match(/\?info/); + let iconElement = firstTdContent.match(/(.*?)<\/span>/); + if (pillText) { + let icon = tdList[0].querySelector('span'); + const pillElement = document.createElement('span'); + pillElement.classList.add('info-pill'); + pillElement.innerHTML = `${iconElement ? iconElement[0] : ''}`; + firstTdContent = firstTdContent.replace(pillText[0], `${pillElement.outerHTML}`); + if (icon) { + let count = 0; + firstTdContent = firstTdContent.replace(new RegExp(icon.outerHTML, 'g'), (match) => { + count += 1; + return (count === 2) ? '' : match; + }); + } + } + } + // < reffers to '<' character + if (firstTdContent.indexOf('<pill') !== -1 || firstTdContent.indexOf('<') !== -1) { + liClass += ' has_arrow'; + firstTdContent = firstTdContent.replace('<-', ''); + } + + // < reffers to '<' character + if (firstTdContent.indexOf('<-') !== -1 || firstTdContent.indexOf('<') !== -1) { + liClass += ' has_arrow'; + firstTdContent = firstTdContent.replace('<-', ''); + } + + // > reffers to '>' character + if (firstTdContent.indexOf('->') !== -1 || firstTdContent.indexOf('>') !== -1) { + liClass += ' has_arrow_right'; + firstTdContent = firstTdContent.replace('->', ''); + } + + const liContent = `
  • ${firstTdContent}${secondTdContent}
  • `; + + return liContent; + }).join(' '); + + return `
      ${liString}
    `; + }); + + if (title.innerHTML.indexOf('href') !== -1) { + title.innerHTML = `${title.querySelector('tr a').innerHTML}`; + } + + const buyLinkSelector = prod.querySelector('a[href*="#buylink"]'); + if (buyLinkSelector) { + buyLinkSelector.classList.add('button', 'primary'); + } + if (richText) { + richText.querySelectorAll('a').forEach((link) => { + link.classList.add('button', 'primary'); + }); + } + + let planSwitcher = document.createElement('div'); + if (radioButtons && monthlyProducts) { + let leftRadio = radioButtons.querySelector('td:first-child')?.textContent; + let rightRadio = radioButtons.querySelector('td:last-child')?.textContent; + planSwitcher.classList.add('plan-switcher'); + planSwitcher.innerHTML = ` + +
    + + `; + } + // create the prices element based on where the component is being called from, aem of www-websites + if (options) { + await createPricesElement(options.store, hideProducts, '', 'Save', prodName, prodUsers, prodYears, buyLinkSelector, billed) + .then((pricesBox) => { + yearlyPricesBoxes[`${key}-yearly-${prodName.trim()}`] = pricesBox; + // buyLink.parentNode.parentNode.insertBefore(pricesBox, buyLink.parentNode); + prod.outerHTML = ` +
    +
    + ${greenTag.innerText.trim() ? `
    ${greenTag.innerText.trim()}
    ` : ''} + ${title.innerText.trim() ? `${title.tagName === 'h3' ? `${title.innerHTML}` : `

    ${title.innerHTML}

    `}` : ''} + ${blueTag.innerText.trim() ? `
    ${blueTag.innerHTML.trim()}
    ` : ''} + ${subtitle.innerText.trim() ? `

    ${subtitle.querySelector('td').innerHTML.trim()}

    ` : ''} + + ${radioButtons ? planSwitcher.outerHTML : ''} + ${addRichTextZone === 'true' ? `${richTextZone ? `
    ${richTextZone.innerHTML}
    ` : ''}` : ''} + ${hideProducts === 'true' ? '' : ` + ${pricesBox.outerHTML} + + ${buyLink.outerHTML} + + ${undeBuyLink.innerText.trim() ? `` : ''}`} +
    + ${benefitsLists.innerText.trim() ? `
    ${featureList}
    ` : ''} + ${richText ? `
    ${richText.outerHTML}
    ` : ''} +
    +
    `; + }); + if (monthlyProducts) { + const montlyPriceBox = await createPricesElement(options.store, hideProducts, '', 'Save', prodMonthlyName, prodMonthlyUsers, prodMonthlyYears, buyLinkSelector, billed); + monthlyPriceBoxes[`${key}-monthly-${prodMonthlyName.trim()}`] = montlyPriceBox; + } + } else { + const { fetchProduct } = await import('../../scripts/utils/utils.js'); + let oldPrice; + let newPrice; + let discountPercentage; + let priceElement = document.createElement('div'); + buyLink.querySelector('a').classList.add('button', 'primary', 'no-arrow'); + block.children[key].outerHTML = ` +
    +
    + ${greenTag.innerText.trim() ? `
    ${greenTag.innerText.trim()}
    ` : ''} + ${title.innerText.trim() ? `

    ${title.innerHTML}

    ` : ''} + ${blueTag.innerText.trim() ? `
    ${blueTag.innerHTML.trim()}
    ` : ''} + ${subtitle.innerText.trim() ? `

    ${subtitle.innerText.trim()}

    ` : ''} +
    + ${hideProducts === 'true' ? '' : ` +
    + ${billed ? `
    ${billed.innerHTML.replace('0', ``)}
    ` : ''} + + ${buyLink.innerHTML} + + ${undeBuyLink.innerText.trim() ? `` : ''}`} +
    + ${benefitsLists.innerText.trim() ? `
    ${featureList}
    ` : ''} + ${richText ? `
    ${richText.outerHTML}
    ` : ''} +
    +
    `; + if (hideProducts !== 'true') { + fetchProduct(prodName, `${prodUsers}u-${prodYears}y`, pid) + .then((product) => { + discountPercentage = Math.round( + (1 - (product.discount.discounted_price) / product.price) * 100, + ); + oldPrice = product.price; + newPrice = product.discount.discounted_price; + let currencyLabel = product.currency_label; + priceElement.classList.add('hero-aem__prices'); + priceElement.innerHTML = ` +
    +
    + ${oldPrice}${currencyLabel} + Save ${discountPercentage}% +
    +
    + ${newPrice}${currencyLabel} + +
    +
    `; + block.children[key].querySelector('.price_box').appendChild(priceElement); + }) + .catch((err) => { + // eslint-disable-next-line no-console + console.error(err); + }); + } + } + })); + } else { + block.innerHTML = ` +
    + add some products +
    `; + } + + if (monthlyProducts) { + [...block.children].forEach((prod) => { + let planSwitcher = prod.querySelector('.plan-switcher'); + planSwitcher.querySelectorAll('input[type="radio"]').forEach((radio) => { + radio.addEventListener('input', (event) => { + let planType = event.target.value.split('-')[1]; + let priceBox = prod.querySelector('.hero-aem__prices'); + if (planType === 'monthly') { + priceBox.innerHTML = ''; + priceBox.appendChild(monthlyPriceBoxes[event.target.value]); + } else { + priceBox.innerHTML = ''; + priceBox.appendChild(yearlyPricesBoxes[event.target.value]); + } + }); + }); + }); + } + + if (individualSwitchText && familySwitchText) { + block.parentNode.insertBefore(switchBox, block); + } + + // dataLayer push with all the products + if (options && dataLayerProducts.length && hideProducts !== 'true') { + window.adobeDataLayer.push({ + event: 'product loaded', + product: { + [mainProduct === 'false' ? 'all' : 'info']: dataLayerProducts, + }, + }); + } + + window.hj = window.hj || function initHotjar(...args) { + (hj.q = hj.q || []).push(...args); + }; + hj('event', 'new-prod-boxes-vsb'); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/new-prod-boxes/new-prod-boxes.css b/_src/blocks/new-prod-boxes/new-prod-boxes.css new file mode 100644 index 000000000..2efb459c8 --- /dev/null +++ b/_src/blocks/new-prod-boxes/new-prod-boxes.css @@ -0,0 +1,738 @@ +/* stylelint-disable */ +.new-prod-boxes-container.remove-first > div.default-content-wrapper:first-of-type { + display: none; +} + +.creators .new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box { + border: 1px solid #ECECEC; +} + +.creators .new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .undeBuyLink { + text-align: center; + font-weight: bold; +} + +.new-prod-boxes-container { + padding-bottom: 0; + font-family: 'Arial', sans-serif; + margin: clamp(10px, 25px, 15px) 0; +} + +.new-prod-boxes-container div.default-content-wrapper:last-of-type { + padding: 0; +} + +.new-prod-boxes-container div.default-content-wrapper:last-of-type * { + font: normal normal normal 12px/14px Arial; + color: black; +} + +.new-prod-boxes-container div.default-content-wrapper:last-of-type a { + text-decoration: underline; +} + +.new-prod-boxes-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.new-prod-boxes-container .default-content-wrapper p:has(> a) { + text-align: center; + font-size: 16px; +} + +.new-prod-boxes-container .default-content-wrapper p:has(> a) a { + text-align: center; + font-size: 16px; + color: #005ed9; + text-decoration: none; +} + +.new-prod-boxes-container .default-content-wrapper p:has(> a) a:hover { + color: #00439c; + text-decoration: underline; +} + +.new-prod-boxes-container .default-content-wrapper h2 { + text-align: center; + font-size: 32px; + line-height: 37px; + max-width: 550px; + margin: auto; + margin-bottom: 20px; +} + +.new-prod-boxes-container .new-prod-boxes { + margin: 0 auto; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box { + flex: 1; + max-width: 410px; + margin: 8px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box { + position: relative; + height: 100%; + background-color: #F6F6F6; + border-radius: 20px; + padding: 25px; + margin: 0 auto; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .greenTag2 { + height: 30px; + max-width: 350px; + width: 86%; + font-family: Arial, sans-serif; + color: white; + text-align: center; + background-color: #1C7928; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + padding-top: 7px; + position: absolute; + top: -39px; + left: 7%; + box-sizing: content-box; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box h4 { + font-weight: bold; + font-size: 22px; + line-height: 26px; + font-family: Arial, sans-serif; + margin-top: 0; + margin-bottom: 4px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box h4 a { + transition: all 0.5s ease; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box h4 a:hover { + text-decoration: none; + transition: all 0.5s ease; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTag { + font-size: var(--body-font-size-xs); + font-family: Arial, sans-serif; + color: white; + text-align: center; + background-color: #026DFF; + display: inline-block; + border-radius: 20px; + padding: 6px 16px; + margin-bottom: 10px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTag div { + display: flex; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTag img { + height: 14px; + margin-right: 5px; + margin-top: -5px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .subtitle { + font-size: clamp(10px, 14px, 14px); + font-family: Arial, sans-serif; + margin-bottom: 0; + line-height: 1.25; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .subtitle.fixed_height { + min-height: 80px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box hr { + border: 1px solid #D1D1D1; + margin: 10px 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box hr:first-of-type { + margin-bottom: 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box hr:last-of-type { + margin-bottom: 10px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .save_price_box { + display: flex; + justify-content: left; + align-items: center; + margin-bottom: 8px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .save_price_box .prod-oldprice { + font-size: var(--heading-font-size-xs); + line-height: var(--heading-font-size-xs); + text-decoration: line-through; + margin-right: 10px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .save_price_box .prod-percent { + font-size: 13px; + line-height: 15px; + color: white; + background-color: #68BA68; + border-radius: 11px; + padding: 4px 10px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .prices_box { + display: flex; + justify-content: left; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .prices_box .prod-newprice { + font-size: var(--heading-font-size-xl); + line-height: var(--heading-font-size-xl); +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .prices_box sup { + margin: 15px 0 0 5px; + font-size: var(--heading-font-size-s); + line-height: var(--heading-font-size-s); +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .billed { + font-size: 12px; + font-family: Arial, sans-serif; + line-height: 13px; + margin: 7px 0 20px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .buy-btn a.red-buy-button { + width: 100%; + text-transform: none; + font-size: 14px; + line-height: 14px; + font-weight: 500 !important; + padding: 10px 1% !important; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .undeBuyLink { + font-size: 12px; + font-family: Arial, sans-serif; + line-height: 13px; + margin: 10px 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists { + font-family: Arial, sans-serif; + color: transparent; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists p { + margin: 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists u { + font-size: var(--body-font-size-xs); + text-decoration: none; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul { + margin: 0; + margin-bottom: -5px; + padding: 0; + color: black; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li { + padding-left: 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:first-of-type { + font-size: 16px; + line-height: 18px; + text-decoration: none; + list-style-type: none; + font-weight: bold; + font-family: Arial, sans-serif; + margin-bottom: 0.5rem; +} + +.new-prod-boxes-container { + .new-prod-boxes { + .prod_box { + .inner_prod_box { + .benefitsLists { + ul { + &.checkmark-list { + background-color: #E7E7E7; + padding: 13px 48px 16px 10px; + filter: grayscale(1); + border-radius: 8px; + margin-bottom: 8px; + li { + &:first-of-type { + display: flex; + align-items: center; + font-size: 14px; + + .checkmark { + appearance: none; + -webkit-appearance: none; + display: grid; + width: 18px; + height: 18px; + padding: 0; + border: 1px solid #FFFFFF; + border-radius: 1px; + margin-right: 16px; + transition: cubic-bezier(0.075, 0.82, 0.165, 1); + + &::after { + content: ""; + width: 18px; + height: 18px; + clip-path: polygon(17% 54%, 28% 43%, 38% 54%, 70% 22%, 81% 33%, 38% 75%, 17% 54%); + transform: scale(0); + background-color: white; + } + &:checked { + background: #016DFF 0% 0% no-repeat padding-box; + -webkit-box-shadow: 0px 0px 5px 0px rgba(1,109,255,1); + -moz-box-shadow: 0px 0px 5px 0px rgba(1,109,255,1); + box-shadow: 0px 0px 5px 0px rgba(1,109,255,1); + } + &:checked::after { + transform: scale(1); + } + } + } + } + + &.checked { + filter: grayscale(0); + background-color: #EAF5EC; + } + } + } + } + + .add-on-product { + transition: all 0.4s; + } + } + } + } +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:first-of-type.has_arrow::before { + content: ""; + margin: 0 5px 20px 0; + background: url("https://bitdefender.com/pages/icons/arrow-left-blue.png") no-repeat center transparent; + width: 20px; + height: 20px; + background-size: 15px 12px; + float: left; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:first-of-type.has_arrow_right .arrow-right { + background: url("https://bitdefender.com/icons/arrow-right-solid.svg") no-repeat center transparent; + width: 20px; + height: 20px; + background-size: 15px 12px; + position: relative; + top: 4px; + display: inline-flex; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) { + font-size: 14px; + line-height: 17px; + margin-bottom: 8px; + list-style-type: none; + background: url("https://bitdefender.com/icons/circle-check-sharp-solid.svg") top 2px left no-repeat transparent; + padding-left: 22px; + background-size: 13px; + position: relative; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) .white-pill-content { + position: absolute; + background-color: white; + padding: 10px; + border-radius: 10px; + margin-bottom: 28px; + left: 0; + bottom: 0; + z-index: 1; + font-size: 12px; + box-shadow: 4px 4px 7px -8px #000; + display: none; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) .white-pill-content::before { + content: ""; + position: absolute; + left: 17px; + bottom: -20px; + border-width: 10px; + border-style: solid; + border-color: white transparent transparent; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type):hover .white-pill-content{ + display: block; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) u { + font-size: 14px; + font-weight: bold; + color: white; + border-radius: 20px; + padding: 2px 21px 2px 7px; + background: url("https://bitdefender.com/pages/images/icons/individual.svg") center right 6px no-repeat #026DFF; + background-size: auto 12px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul:nth-of-type(2) { + min-height: 5em; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box.hasGreenTag { + margin-top: 45px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box.hasGreenTag .inner_prod_box { + box-shadow: 0 3px 7px 0 #C1C1C1; +} + +.new-prod-boxes-container .prod-oldprice { + font-size: 16px; + text-decoration: line-through; +} + +.new-prod-boxes-container .prod-save { + color: #1C7928; + font-weight: bold; +} + +.new-prod-boxes-container .prod-newprice { + font-size: 40px; + font-weight: bold; +} +.new-prod-boxes-container .prod-newprice .per-m { + font-size: 20px; + top: -12px; +} +.new-prod-boxes-container .newprice-container { + line-height: 1; +} + +.new-prod-boxes-container .newprice-container sup { + position: relative; + top: -20px; +} + +.new-prod-boxes-container .button.primary { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: block; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.new-prod-boxes-container .new-prod-boxes.smallerbuttons .button.primary { + display: inline-block; + min-width: 144px; +} + +.new-prod-boxes-container .button.primary.no-arrow::after { + content: none; +} + +.new-prod-boxes-container .button.primary:hover { + color: white; + background-color: #B10304; + border-color: #B10304; +} + +.new-prod-boxes-container .button.primary:active { + background-color: #920A0A; + border-color: #920A0A; +} + +.new-prod-boxes-container p em a { + font-size: 16px !important; + font-style: normal !important; + font-weight: 500 !important; + -webkit-font-smoothing: antialiased !important; + display: block !important; + align-items: center !important; + box-sizing: border-box !important; + text-decoration: none !important; + padding: 10px 26px 8px 28px !important; + text-align: center !important; + cursor: pointer !important; + color: #006EFF !important; + background-color: transparent !important; + border: 2px solid #006EFF !important; + white-space: nowrap !important; + overflow: hidden !important; + text-overflow: ellipsis !important; + border-radius: 8px !important; + height: fit-content !important; +} + +.new-prod-boxes-container .new-prod-boxes.smallerbuttons p em a { + display: inline-block; + min-width: 144px; +} + +.new-prod-boxes-container p em a:hover { + color: white !important; + background-color: #006DFF !important; +} + +.new-prod-boxes-container p em a:active { + background-color: #0D499B !important; +} + +.new-prod-boxes-container .icon { + width: 12px; + height: 14px; + margin: 0 5px 0 0; +} + +.new-prod-boxes-container .icon svg { + width: 12px; + height: 14px; + margin-left: -1px; + fill: #fff; +} + +.new-prod-boxes-container .blue-pill { + background-color: #026DFF; + padding: 2.5px 6.7px; + border-radius: 20px; + color: white; + font-style: normal; + font-size: 11px; + letter-spacing: 0px; + font-weight: bold; + display: inline-flex; + justify-content: center; +} + +.new-prod-boxes-container .blue-pill .icon { + position: relative; + top: 1px; + margin-left: 1px; +} + +.new-prod-boxes-container .blue-pill svg { + width: 9px; + height: 9px; +} + +.switchBox { + text-align: center; + padding-bottom: 35px; +} + +.switchBox .switch { + position: relative; + display: inline-flex; + align-items: center; + width: 302px; + height: 44px; + background-color: #016DFF; + border-radius: 22px; +} + +.switchBox .switch input { + display: none; +} + +.switchBox .slider { + position: absolute; + content: ""; + height: 40px; + width: 150px; + left: 2px; + bottom: 2px; + background-color: white; + border-radius: 20px; + transition: all 0.4s; +} + +.switchBox .switch input:checked + .slider { + transform: translateX(149px); +} + +.switchBox .label { + font-family: Arial, Helvetica, sans-serif; + width: 50%; + text-align: center; + font-weight: bold; + line-height: 34px; + font-size: 16px; + color: white; + transition: color 0.4s; + cursor: pointer; +} + +.switchBox .label.right { + z-index: 10; + color: black; +} + +.switchBox .label.left { + z-index: 10; +} + +.switchBox .switch input:checked ~ .label.right { + transition: color 0.4s; + color: white !important; +} + +.switchBox .switch input ~ .label .icon { + position: relative; + margin-right: 10px; + top: 2px; +} + +.switchBox .switch input ~ .label .icon svg { + width: 14px; + height: 16px; +} + +.switchBox .switch input ~ .label.right .icon svg { + fill: #026DFF; +} + +.switchBox .switch input:checked ~ .label.right .icon svg { + fill: white; +} + +.switchBox .switch input:checked ~ .label.left { + transition: color 0.4s; + color: black; +} + +.switchBox .switch input:checked ~ .label.left .icon svg { + fill: #026DFF; +} + +.prod-box.individual-box { + transition: all 0.4s; +} + +.prod_box.family-box { + display: none; + transition: all 0.4s; +} + +.hero-aem__prices { + margin-top: 20px; +} + +.plan-switcher { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; + font-weight: bold; + margin-bottom: 24px; + margin-top: 16px; +} + +.plan-switcher input[type=radio] { + position: absolute; + opacity: 0; +} + +.plan-switcher .radio-label { + margin-right: 8px; +} + +.plan-switcher .radio-label::before { + content: ""; + background: #f4f4f4; + color: #006DFF; + border-radius: 100%; + border: 2px solid #006DFF; + display: inline-block; + width: 1.2rem; + height: 1.2rem; + position: relative; + margin-right: 9px; + vertical-align: top; + cursor: pointer; + text-align: center; + transition: all 250ms ease; +} + +.plan-switcher input[type=radio]:checked+.radio-label:before { + background-color: #3197EE; + box-shadow: inset 0 0 0 4px #f4f4f4; +} + +.plan-switcher input[type=radio]:focus+.radio-label:before { + outline: none; + border-color: #3197EE; +} + +@media (min-width: 768px) { + .creators .new-prod-boxes-container .new-prod-boxes { + padding-bottom: 10px; + } + + .new-prod-boxes-container .new-prod-boxes { + flex-direction: row; + padding-bottom: 60px; + align-items: initial; + margin-top: 37px; + } + + .new-prod-boxes-container .new-prod-boxes .prod_box.hasGreenTag { + margin: 8px; + } +} + +@media (min-width: 992px) { + .new-prod-boxes-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .new-prod-boxes-container.we-container { + padding-left: 20px; + padding-right: 20px; + } +} \ No newline at end of file diff --git a/_src/blocks/new-prod-boxes/new-prod-boxes.js b/_src/blocks/new-prod-boxes/new-prod-boxes.js new file mode 100644 index 000000000..e614fe4d4 --- /dev/null +++ b/_src/blocks/new-prod-boxes/new-prod-boxes.js @@ -0,0 +1,654 @@ +/* eslint-disable prefer-const */ +/* eslint-disable no-undef */ +/* eslint-disable max-len */ +import { getMetadata, getBuyLinkCountryPrefix, matchHeights } from '../../scripts/utils/utils.js'; + +let dataLayerProducts = []; +async function createPricesElement(storeOBJ, conditionText, saveText, prodName, prodUsers, prodYears, buylink, billed, customLink) { + const storeProduct = await storeOBJ.getProducts([new ProductInfo(prodName, 'consumer')]); + const storeOption = storeProduct[prodName].getOption(prodUsers, prodYears); + const price = storeOption.getPrice(); + const discountedPrice = storeOption.getDiscountedPrice(); + const discount = storeOption.getDiscount('valueWithCurrency'); + const buyLink = await storeOption.getStoreUrl(); + + let product = { + ID: storeOption.getAvangateId(), + name: storeOption.getName(), + devices: storeOption.getDevices(), + subscription: storeOption.getSubscription('months'), + version: storeOption.getSubscription('months') === 1 ? 'monthly' : 'yearly', + basePrice: storeOption.getPrice('value'), + discountValue: storeOption.getDiscount('value'), + discountRate: storeOption.getDiscount('percentage'), + currency: storeOption.getCurrency(), + priceWithTax: storeOption.getDiscountedPrice('value') || storeOption.getPrice('value'), + }; + dataLayerProducts.push(product); + const priceElement = document.createElement('div'); + priceElement.classList.add('hero-aem__prices'); + priceElement.innerHTML = ` +
    +
    + ${price} + ${saveText} ${discount} +
    +
    + ${discountedPrice} + ${conditionText || ''} +
    +
    + ${billed ? `
    ${billed.innerHTML}
    ` : ''} + ${buylink.text}`; + buylink.remove(); + return priceElement; +} + +function dynamicBuyLink(buyLinkSelector, prodName, ProdUsers, prodYears, pid = null) { + if (!buyLinkSelector) { + return null; + } + + const url = new URL(window.location.href); + let buyLinkPid = pid; + if (!buyLinkPid) { + buyLinkPid = url.searchParams.get('pid') || getMetadata('pid'); + } + if (!buyLinkPid) { + buyLinkPid = ''; + } + + let buyLinkHref = new URL(`${getBuyLinkCountryPrefix()}/${prodName.trim()}/${ProdUsers}/${prodYears}/`); + if (buyLinkPid) { + buyLinkHref.searchParams.append('pid', buyLinkPid); + } + return buyLinkHref; +} +async function updateProductPrice(prodName, prodUsers, prodYears, saveText, pid = null, buyLinkSelector = null, billed = null, type = null, hideDecimals = null, perPrice = '') { + try { + const { fetchProduct, formatPrice } = await import('../../scripts/utils/utils.js'); + const product = await fetchProduct(prodName, `${prodUsers}u-${prodYears}y`, pid); + const { price, discount } = product; + const discountPercentage = Math.round((1 - discount.discounted_price / price) * 100); + let oldPrice = price; + let newPrice = discount.discounted_price; + // eslint-disable-next-line no-param-reassign + let updatedBuyLinkSelector = buyLinkSelector; + if (updatedBuyLinkSelector) { + updatedBuyLinkSelector.href = dynamicBuyLink(updatedBuyLinkSelector, prodName, prodUsers, prodYears, pid); + } + let priceElement = document.createElement('div'); + priceElement.classList.add('hero-aem__prices__box'); + + let newPriceBilled = ''; + let newPriceListed = ''; + let prodVersion = 'monthly'; + + if (!prodName.endsWith('m') && type === 'monthly') { + newPrice = `${(parseInt(newPrice, 10) / 12)}`; + prodVersion = 'yearly'; + } + + let adobeDataLayerProduct = { + ID: product.platform_product_id, + name: prodName.trim(), + devices: product.variation.dimension_value, + subscription: prodVersion, + version: prodVersion, + basePrice: price, + discountValue: discount.discounted_price, + discountRate: discountPercentage, + currency: product.currency_label, + priceWithTax: discount.discounted_price, + }; + dataLayerProducts.push(adobeDataLayerProduct); + + oldPrice = formatPrice(oldPrice, product.currency_iso, product.region_id).replace('.00', ''); + if (hideDecimals === 'true') { + newPriceBilled = formatPrice(product.discount.discounted_price, product.currency_iso, product.region_id).replace('.00', ''); + newPriceListed = formatPrice(newPrice, product.currency_iso, product.region_id).replace('.00', ''); + } else { + newPriceListed = formatPrice(newPrice, product.currency_iso, product.region_id); + } + + priceElement.innerHTML = ` +
    +
    + ${oldPrice} + ${saveText} ${discountPercentage}% +
    +
    + ${newPriceListed} ${perPrice && `${perPrice.textContent.replace('0', '')}`} +
    + ${billed ? `
    ${billed.innerHTML.replace('0', `${newPriceBilled}`)}
    ` : ''} + ${updatedBuyLinkSelector ? updatedBuyLinkSelector.text : ''} +
    `; + return priceElement; + } catch (err) { + // eslint-disable-next-line no-console + console.error('Error fetching product:', err); + } + return null; +} + +function calculateAddOnCost(selector1, selector2) { + if (!selector1 || !selector2) { + return null; + } + + // get only the number from the new price + const numberRegex = /\d+(\.\d+)?/; + const firstPriceString = selector1.textContent.match(numberRegex)[0]; + const firstPriceFloat = parseFloat(firstPriceString); + + const secondPriceString = selector2.textContent.match(numberRegex)[0]; + const secondPriceFloat = parseFloat(secondPriceString); + const correctPrice = parseInt(secondPriceFloat - firstPriceFloat, 10); + + return correctPrice; +} + +function createPlanSwitcher(radioButtons, cardNumber, prodName, prodMonthlyName, prodThirdRadioButtonName, variant = 'default') { + const planSwitcher = document.createElement('div'); + planSwitcher.classList.add('plan-switcher'); + planSwitcher.classList.toggle('addon', variant === 'addon'); + + let radioArray = ['yearly', 'monthly', '3-rd-button']; + if (variant === 'addon') { + radioArray = ['add-on-yearly', 'add-on-monthly']; + } + let prodNamesArray = [prodName, prodMonthlyName, prodThirdRadioButtonName]; + + Array.from(radioButtons.children).forEach((radio, idx) => { + let radioText = radio.textContent; + let plan = radioArray[idx]; + let productName = prodNamesArray[idx]; + let checked = idx === 0 ? 'checked' : ''; + let defaultCheck = radio.textContent.match(/\[checked\]/g); + if (defaultCheck) { + radioText = radioText.replace('[checked]', ''); + checked = 'checked'; + } + + if (productName) { + planSwitcher.innerHTML += ` + +
    + `; + } + }); + + return planSwitcher; +} + +export default async function decorate(block, options) { + const { + // eslint-disable-next-line no-unused-vars + products, familyProducts, monthlyProducts, priceType, pid, mainProduct, + addOnProducts, addOnMonthlyProducts, type, hideDecimals, thirdRadioButtonProducts, saveText, + } = block.closest('.section').dataset; + // if options exists, this means the component is being called from aem + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + } + + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + + let defaultContentWrapperElements = block.closest('.section').querySelector('.default-content-wrapper')?.children; + let individualSwitchText; + let familySwitchText; + if (defaultContentWrapperElements) { + [...defaultContentWrapperElements].forEach((element) => { + if (element.innerHTML.includes('<slider-1 ')) { + element.innerHTML = element.innerHTML.replace('<slider-1 ', ''); + individualSwitchText = element.innerHTML; + element.remove(); + } + if (element.innerHTML.includes('<slider-2 ')) { + element.innerHTML = element.innerHTML.replace('<slider-2 ', ''); + familySwitchText = element.innerHTML; + element.remove(); + } + }); + } + + let switchBox = document.createElement('div'); + if (individualSwitchText && familySwitchText) { + switchBox.classList.add('switchBox'); + switchBox.innerHTML = ` + + `; + + // Get the checkbox inside the switchBox + let switchCheckbox = switchBox.querySelector('#switchCheckbox'); + // Add an event listener to the checkbox + switchCheckbox.addEventListener('change', () => { + if (switchCheckbox.checked) { + let familyBoxes = block.querySelectorAll('.family-box'); + familyBoxes.forEach((box) => { + box.style.display = 'block'; + }); + + let individualBoxes = block.querySelectorAll('.individual-box'); + individualBoxes.forEach((box) => { + box.style.display = 'none'; + }); + } else { + let familyBoxes = block.querySelectorAll('.family-box'); + familyBoxes.forEach((box) => { + box.style.display = 'none'; + }); + + let individualBoxes = block.querySelectorAll('.individual-box'); + individualBoxes.forEach((box) => { + box.style.display = 'block'; + }); + } + }); + } + + const productsAsList = products && products.split(','); + const familyProductsAsList = familyProducts && familyProducts.split(','); + const combinedProducts = productsAsList.concat(familyProductsAsList); + const monthlyPricesAsList = monthlyProducts && monthlyProducts.split(','); + const thirdRadioButtonProductsAsList = thirdRadioButtonProducts && thirdRadioButtonProducts.split(','); + + let monthlyPriceBoxes = {}; + let yearlyPricesBoxes = {}; + let thirdRadioButtonProductsBoxes = {}; + + let yearlyAddOnPricesBoxes = {}; + let monthlyAddOnPricesBoxes = {}; + if (combinedProducts.length) { + await Promise.all([...block.children].map(async (prod, key) => { + // eslint-disable-next-line no-unused-vars + const mainTable = prod.querySelector('tbody'); + // eslint-disable-next-line no-unused-vars + const [greenTag, title, blueTag, subtitle, radioButtons, perPrice, billed, buyLink, undeBuyLink, benefitsLists, billed2, buyLink2] = [...mainTable.querySelectorAll(':scope > tr')]; + const [prodName, prodUsers, prodYears] = combinedProducts[key].split('/'); + const [prodMonthlyName, prodMonthlyUsers, prodMonthlyYears] = monthlyPricesAsList ? monthlyPricesAsList[key].split('/') : []; + const [prodThirdRadioButtonName, prodThirdRadioButtonUsers, prodThirdRadioButtonYears] = thirdRadioButtonProductsAsList ? thirdRadioButtonProductsAsList[key].split('/') : []; + let addOn = 0; + const addOnProductsAsList = addOnProducts && addOnProducts.split(','); + const addOnMonthlyProductsAsList = addOnMonthlyProducts && addOnMonthlyProducts.split(','); + const featuresSet = benefitsLists.querySelectorAll('table'); + const featureList = Array.from(featuresSet).map((table) => { + const trList = Array.from(table.querySelectorAll('tr')); + const liString = trList.map((tr) => { + const tdList = Array.from(tr.querySelectorAll('td')); + // Extract the content of the first to be placed outside the
  • + let firstTdContent = tdList.length > 0 && tdList[0].textContent.trim() !== '' ? `${tdList[0].innerHTML}` : ''; + // Extract the content of the second (if present) inside a + const secondTdContent = tdList.length > 1 && tdList[1].textContent.trim() !== '' ? `${tdList[1].innerHTML}` : ''; + // Create the
  • combining the first and second td content + let liClass = ''; + if (firstTdContent === '') { + liClass += 'd-none'; + } + + if (firstTdContent.indexOf('?pill') !== -1) { + let pillText = firstTdContent.match(/\?pill (\w+)/); + let iconElement = firstTdContent.match(/(.*?)<\/span>/); + if (pillText) { + let icon = tdList[0].querySelector('span'); + const pillElement = document.createElement('span'); + pillElement.classList.add('blue-pill'); + pillElement.innerHTML = `${pillText[1]}${iconElement ? iconElement[0] : ''}`; + firstTdContent = firstTdContent.replace(pillText[0], `${pillElement.outerHTML}`); + if (icon) { + let count = 0; + firstTdContent = firstTdContent.replace(new RegExp(icon.outerHTML, 'g'), (match) => { + count += 1; + return (count === 2) ? '' : match; + }); + } + } + } + // < reffers to '<' character + if (firstTdContent.indexOf('<pill') !== -1 || firstTdContent.indexOf('<') !== -1) { + liClass += ' has_arrow'; + firstTdContent = firstTdContent.replace('<-', ''); + } + + // < reffers to '<' character + if (firstTdContent.indexOf('<-') !== -1 || firstTdContent.indexOf('<') !== -1) { + liClass += ' has_arrow'; + firstTdContent = firstTdContent.replace('<-', ''); + } + + // > reffers to '>' character + if (firstTdContent.indexOf('->') !== -1 || firstTdContent.indexOf('>') !== -1) { + liClass += ' has_arrow_right'; + firstTdContent = firstTdContent.replace('->', ''); + } + + if (firstTdContent.indexOf('[checkmark]') !== -1) { + firstTdContent = firstTdContent.replace('[checkmark]', ''); + } + + if (firstTdContent.indexOf('[add-on]') !== -1) { + firstTdContent = firstTdContent.replace('[add-on]', ''); + addOn = 1; + } + + if (firstTdContent.indexOf('<<add-on-newprice>>') !== -1) { + firstTdContent = firstTdContent.replace('<<add-on-newprice>>', ''); + } + if (firstTdContent.indexOf('<<add-on-oldprice>>') !== -1) { + firstTdContent = firstTdContent.replace('<<add-on-oldprice>>', ''); + } + + if (firstTdContent.indexOf('<<add-on-percent-save>>') !== -1) { + firstTdContent = firstTdContent.replace('<<add-on-percent-save>>', ''); + } + + if (firstTdContent.indexOf('[[') !== -1) { + firstTdContent = firstTdContent.replace('[[', '('); + } + + if (firstTdContent.indexOf(']]') !== -1) { + firstTdContent = firstTdContent.replace(']]', ')'); + } + + const liContent = `
  • ${firstTdContent}${secondTdContent}
  • `; + return liContent; + }).join(' '); + + return `
      ${liString}
    `; + }); + + if (title.innerHTML.indexOf('href') !== -1) { + title.innerHTML = `${title.querySelector('tr a').innerHTML}`; + } + + let buyLinkSelector = prod.querySelector('a[href*="#buylink"]'); + let customLink = 0; + if (buyLinkSelector) { + buyLinkSelector.classList.add('button', 'primary'); + } else { + buyLinkSelector = buyLink.querySelector('a'); + customLink = 1; + } + + let planSwitcher = document.createElement('div'); + if (radioButtons && monthlyProducts) { + planSwitcher = createPlanSwitcher(radioButtons, key, prodName, prodMonthlyName, prodThirdRadioButtonName); + } + let planSwitcher2 = document.createElement('div'); + if (addOn && addOnProductsAsList && addOnMonthlyProductsAsList) { + // eslint-disable-next-line no-unused-vars + const [addOnProdName, addOnProdUsers, addOnProdYears] = addOnProductsAsList[key].split('/'); + // eslint-disable-next-line no-unused-vars + const [addOnProdMonthlyName, addOnProdMonthlyUsers, addOnProdMonthlyYears] = addOnMonthlyProductsAsList[key].split('/'); + planSwitcher2 = createPlanSwitcher(radioButtons, key, addOnProdName, addOnProdMonthlyName, null, 'addon'); + } + + let addOnPriceBox; + // create the prices element based on where the component is being called from, aem of www-websites + if (options) { + await createPricesElement(options.store, '', 'Save', prodName, prodUsers, prodYears, buyLinkSelector, billed, customLink) + .then((pricesBox) => { + yearlyPricesBoxes[`${key}-yearly-${prodName.trim()}`] = pricesBox; + prod.outerHTML = ` +
    +
    + ${greenTag.innerText.trim() ? `
    ${greenTag.innerText.trim()}
    ` : ''} + ${title.innerText.trim() ? `

    ${title.innerHTML}

    ` : ''} + ${blueTag.innerText.trim() ? `
    ${blueTag.innerHTML.trim()}
    ` : ''} + ${subtitle.innerText.trim() ? `

    ${subtitle.querySelector('td').innerHTML.trim()}

    ` : ''} + + ${radioButtons ? planSwitcher.outerHTML : ''} + + ${pricesBox.outerHTML} + + ${buyLink.outerHTML} + + ${undeBuyLink.innerText.trim() ? `` : ''} +
    + ${benefitsLists.innerText.trim() ? `
    ${featureList}
    ` : ''} +
    +
    `; + }); + if (monthlyProducts) { + const montlyPriceBox = await createPricesElement(options.store, '', 'Save', prodMonthlyName, prodMonthlyUsers, prodMonthlyYears, buyLinkSelector, billed); + monthlyPriceBoxes[`${key}-monthly-${prodMonthlyName.trim()}`] = montlyPriceBox; + } + } else { + buyLink.querySelector('a').classList.add('button', 'primary', 'no-arrow'); + buyLink2?.querySelector('a')?.classList.add('button', 'primary', 'no-arrow'); + + const prodBox = document.createElement('div'); + prodBox.innerHTML = ` +
    +
    + ${greenTag.innerText.trim() ? `
    ${greenTag.innerText.trim()}
    ` : ''} + ${title.innerText.trim() ? `

    ${title.innerHTML}

    ` : ''} + ${blueTag.innerText.trim() ? `
    ${blueTag.innerHTML.trim()}
    ` : ''} + ${subtitle.innerText.trim() ? `

    ${subtitle.innerText.trim()}

    ` : ''} +
    + ${radioButtons ? planSwitcher.outerHTML : ''} +
    + + ${undeBuyLink.innerText.trim() ? `` : ''} +
    + ${benefitsLists.innerText.trim() ? `
    ${featureList}
    ` : ''} + +
    +
    `; + + block.children[key].outerHTML = prodBox.innerHTML; + let priceBox = await updateProductPrice(prodName, prodUsers, prodYears, saveText, pid, buyLink.querySelector('a'), billed, type, hideDecimals, perPrice); + block.children[key].querySelector('.hero-aem__prices').appendChild(priceBox); + yearlyPricesBoxes[`${key}-yearly-${prodName.trim()}`] = priceBox; + + if (monthlyProducts) { + const montlyPriceBox = await updateProductPrice(prodMonthlyName, prodMonthlyUsers, prodMonthlyYears, saveText, pid, buyLink.querySelector('a'), billed, type, hideDecimals, perPrice); + monthlyPriceBoxes[`${key}-monthly-${prodMonthlyName.trim()}`] = montlyPriceBox; + } + + if (radioButtons.children.length === 3 && thirdRadioButtonProducts) { + const thirdRadioButtonBox = await updateProductPrice(prodThirdRadioButtonName, prodThirdRadioButtonUsers, prodThirdRadioButtonYears, saveText, pid, buyLink.querySelector('a'), billed, type, hideDecimals, perPrice); + thirdRadioButtonProductsBoxes[`${key}-3-rd-button-${prodThirdRadioButtonName.trim()}`] = thirdRadioButtonBox; + } + + if (addOn && addOnMonthlyProductsAsList) { + const [addOnProdMonthlyName, addOnProdMonthlyUsers, addOnProdMonthlyYears] = addOnMonthlyProductsAsList[key].split('/'); + let monthlyAddOnPriceBox = await updateProductPrice(addOnProdMonthlyName, addOnProdMonthlyUsers, addOnProdMonthlyYears, saveText, pid, buyLink2.querySelector('a'), billed2, type, hideDecimals, perPrice); + monthlyAddOnPricesBoxes[`${key}-add-on-monthly-${addOnProdMonthlyName.trim()}`] = monthlyAddOnPriceBox; + } + + if (addOn && addOnProductsAsList) { + const [addOnProdName, addOnProdUsers, addOnProdYears] = addOnProductsAsList[key].split('/'); + addOnPriceBox = await updateProductPrice(addOnProdName, addOnProdUsers, addOnProdYears, saveText, pid, buyLink2.querySelector('a'), billed2, type, hideDecimals, perPrice); + block.children[key].querySelector('.hero-aem__prices__addon').appendChild(addOnPriceBox); + yearlyAddOnPricesBoxes[`${key}-add-on-yearly-${addOnProdName.trim()}`] = addOnPriceBox; + } + } + + let checkmark = block.children[key].querySelector('.checkmark'); + if (checkmark) { + let checkmarkList = checkmark.closest('ul'); + checkmarkList.classList.add('checkmark-list'); + + let li = checkmark.closest('li'); + li.removeChild(checkmark); + + let checkBox = document.createElement('input'); + checkBox.setAttribute('type', 'checkbox'); + checkBox.classList.add('checkmark'); + + // rewrite the list element so flexbox can work + let newLi = document.createElement('li'); + newLi.innerHTML = ` + ${checkBox.outerHTML} +
    ${li.innerHTML}
    `; + li.replaceWith(newLi); + + let addOnNewPrice = newLi.querySelector('.add-on-newprice'); + let newPriceSelector = block.children[key].querySelector('.prod-newprice'); + let addOnPriceSelector = addOnPriceBox.querySelector('.prod-newprice'); + + const numberRegex = /\d+(\.\d+)?/; + const addOnCost = calculateAddOnCost(newPriceSelector, addOnPriceSelector); + + let addOnOldPrice = newLi.querySelector('.add-on-oldprice'); + let addOnPercentSave = newLi.querySelector('.add-on-percent-save'); + addOnNewPrice.textContent = addOnPriceBox.querySelector('.prod-newprice').textContent.replace(numberRegex, addOnCost); + addOnOldPrice.textContent = addOnPriceBox.querySelector('.prod-oldprice').textContent; + addOnPercentSave.textContent = addOnPriceBox.querySelector('.prod-save').textContent; + + let checkBoxSelector = newLi.querySelector('.checkmark'); + checkBoxSelector.addEventListener('change', () => { + if (checkBoxSelector.checked) { + checkmarkList.classList.add('checked'); + block.children[key].querySelector('.add-on-product').style.display = 'block'; + } else { + checkmarkList.classList.remove('checked'); + block.children[key].querySelector('.add-on-product').style.display = 'none'; + } + }); + } + })); + } else { + block.innerHTML = ` +
    + add some products +
    `; + } + + if (monthlyProducts) { + [...block.children].forEach((prod) => { + let planSwitcher = prod.querySelector('.plan-switcher'); + planSwitcher.querySelectorAll('input[type="radio"]').forEach((radio) => { + radio.addEventListener('input', (event) => { + let planType = event.target.value.split('-')[1]; + let priceBox = prod.querySelector('.hero-aem__prices'); + if (planType === 'monthly') { + priceBox.innerHTML = ''; + priceBox.appendChild(monthlyPriceBoxes[event.target.value]); + } else if (planType === '3') { + priceBox.innerHTML = ''; + priceBox.appendChild(thirdRadioButtonProductsBoxes[event.target.value]); + } else { + priceBox.innerHTML = ''; + priceBox.appendChild(yearlyPricesBoxes[event.target.value]); + } + }); + + if (radio.checked) { + radio.dispatchEvent(new Event('input')); + } + }); + }); + } + + if (addOnProducts && addOnMonthlyProducts) { + [...block.children].forEach((prod) => { + let planSwitcher = prod.querySelector('.plan-switcher.addon'); + planSwitcher?.querySelectorAll('input[type="radio"]').forEach((radio) => { + radio.addEventListener('input', (event) => { + let planType = event.target.value.split('-')[3]; + let priceBox = prod.querySelector('.hero-aem__prices__addon'); + if (planType === 'monthly') { + priceBox.innerHTML = ''; + priceBox.appendChild(monthlyAddOnPricesBoxes[event.target.value]); + } else { + priceBox.innerHTML = ''; + priceBox.appendChild(yearlyAddOnPricesBoxes[event.target.value]); + } + }); + + if (radio.checked) { + radio.dispatchEvent(new Event('input')); + let addOnPriceBox = prod.querySelector('.hero-aem__prices__addon'); + let priceBox = prod.querySelector('.hero-aem__prices'); + + let addOnPriceBoxNewPrice = addOnPriceBox.querySelector('.prod-newprice'); + let priceBoxNewPrice = priceBox.querySelector('.prod-newprice'); + let planSwitcherNewPrice = prod.querySelector('.add-on-newprice'); + + let addOnPriceBoxOldPrice = addOnPriceBox.querySelector('.prod-oldprice'); + let planSwitcherOldPrice = prod.querySelector('.add-on-oldprice'); + + let addOnPriceBoxDiscountPercentage = addOnPriceBox.querySelector('.prod-save'); + let planSwitcherDiscountPercentage = prod.querySelector('.add-on-percent-save'); + + const numberRegex = /\d+(\.\d+)?/; + const addOnCost = calculateAddOnCost(priceBoxNewPrice, addOnPriceBoxNewPrice); + + planSwitcherNewPrice.textContent = planSwitcherNewPrice.textContent.replace(numberRegex, addOnCost); + planSwitcherOldPrice.textContent = addOnPriceBoxOldPrice.textContent; + planSwitcherDiscountPercentage.textContent = addOnPriceBoxDiscountPercentage.textContent; + } + }); + }); + } + + if (individualSwitchText && familySwitchText) { + block.parentNode.insertBefore(switchBox, block); + } + + window.hj = window.hj || function initHotjar(...args) { + (hj.q = hj.q || []).push(...args); + }; + hj('event', 'new-prod-boxes'); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + + // decorate icons if the component is being called from www-websites + const isInLandingPages = window.location.href.includes('www-landing-pages') || window.location.href.includes('bitdefender.com/pages'); + if (!options && !isInLandingPages) { + const { decorateIcons } = await import('../../scripts/lib-franklin.js'); + decorateIcons(block.closest('.section')); + } + + if (isInLandingPages) { + const { decorateIcons } = await import('../../scripts/utils/utils.js'); + // eslint-disable-next-line import/no-unresolved + const { GLOBAL_EVENTS } = await import(`https://${window.location.hostname}/_src-lp/scripts/utils.js`); + const { sendAnalyticsPageLoadedEvent } = await import(`https://${window.location.hostname}/_src-lp/scripts/adobeDataLayer.js`); + decorateIcons(block.closest('.section')); + + document.addEventListener(GLOBAL_EVENTS.ADOBE_MC_LOADED, () => { + window.adobeDataLayer.push({ + event: 'campaign product', + product: { + [mainProduct === 'false' ? 'all' : 'info']: dataLayerProducts, + }, + }); + + sendAnalyticsPageLoadedEvent(true); + }); + } + + if (!isInLandingPages) { + // dataLayer push with all the products + window.adobeDataLayer.push({ + event: 'product loaded', + product: { + [mainProduct === 'false' ? 'all' : 'info']: dataLayerProducts, + }, + }); + } + + matchHeights(block, '.subtitle'); + matchHeights(block, 'h2'); + matchHeights(block, 'h4'); + matchHeights(block, '.plan-switcher'); +} diff --git a/_src/blocks/news-bar/news-bar.css b/_src/blocks/news-bar/news-bar.css new file mode 100644 index 000000000..6e9216116 --- /dev/null +++ b/_src/blocks/news-bar/news-bar.css @@ -0,0 +1,72 @@ +.news-bar { + text-align: center; + justify-content: center; + background-color: #006EFF; + color: white; + display: flex; + line-height: 1.2; + padding: 8px 0; + align-items: center; + + a { + color: white; + transition: all 1s ease; + text-decoration: underline; + } + + transition: all 1s ease; +} + +.news-bar-container.solutions { + .news-bar { + font-size: 16px; + line-height: 21px; + } + + a { + display: block; + font-size: 14px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 7px 29px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + width: fit-content; + margin: 10px auto 0; + transition: all 0.1s ease; + } + + a:hover { + background-color: #D80000; + border: 2px solid #D80000; + } +} + +@media screen and (min-width: 991px) { + .news-bar { + height: 44px; + } + + .news-bar-container.solutions { + .news-bar { + height: 61px; + + a { + display: inline-flex; + margin: 0 0 0 29px; + } + } + } +} \ No newline at end of file diff --git a/_src/blocks/news-bar/news-bar.js b/_src/blocks/news-bar/news-bar.js new file mode 100644 index 000000000..150c7db14 --- /dev/null +++ b/_src/blocks/news-bar/news-bar.js @@ -0,0 +1,37 @@ +export default function decorate(block, options) { + const { + solutions, hideDate, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + } + + if (solutions) { + block.closest('.section').classList.add('solutions'); + } + + const blockParent = block.closest('.section'); + setTimeout(() => { + const elementLink = block.querySelector('a'); + block.style.backgroundColor = '#E4F2FF'; + block.style.color = '#006EFF'; + if (elementLink && !blockParent.classList.contains('solutions')) elementLink.style.color = '#006EFF'; + }, 2000); + + if (hideDate) { + const currentDate = new Date(); + const hiddenDate = new Date(hideDate); + if (hiddenDate < currentDate) { + block.style.display = 'none'; + } + } + + setTimeout(() => { + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, + }); + }, 700); +} diff --git a/_src/blocks/particle-background/particle-background.css b/_src/blocks/particle-background/particle-background.css new file mode 100644 index 000000000..c83edcfc4 --- /dev/null +++ b/_src/blocks/particle-background/particle-background.css @@ -0,0 +1,71 @@ + +.particle-background { + position: relative; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: 400px; + border-radius: 25px; + color: white; + text-align: center; + overflow: hidden; + max-width: 1332px; + z-index: 1; + margin: 48px 0; +} + +.we-container { + margin: 0 auto; + padding: 0 20px; + max-width: 1290px; + position: relative; +} + +.particle-background #ts-particles { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + padding: 0; + margin: 0; +} + +.particle-background h2 { + font-size: clamp(1.5rem, 5vw, 2.5rem); + margin: 0 auto; + line-height: 42px; + max-width: 500px; +} + +.particle-background p { + font-size: 18px; +} + +.particle-background div { + z-index: 1; + padding: 24px; +} + +@media (max-width: 768px) { + .particle-background h2 { + line-height: 30px; + } +} + +@media (min-width: 991px) { /* mobile/tablet */ + .particle-background-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .particle-background-container.we-container { + max-width: 1290px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/particle-background/particle-background.js b/_src/blocks/particle-background/particle-background.js new file mode 100644 index 000000000..d6e7873bd --- /dev/null +++ b/_src/blocks/particle-background/particle-background.js @@ -0,0 +1,145 @@ +/* eslint-disable prefer-const */ +/* eslint-disable camelcase */ +// import * as all from '../../scripts/vendor/tsparticles/tsparticles.bundle.min.js'; +// eslint-disable-next-line no-unused-vars +// import { +// loadScript, +// } from '../../scripts/lib-franklin.js'; + +// eslint-disable-next-line no-unused-vars +function debounce(func, wait) { + let timeout; + return function executedFunction(...args) { + const later = () => { + clearTimeout(timeout); + func(...args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; +} + +function isView(viewport) { + const element = document.querySelectorAll(`[data-${viewport}-detector]`)[0]; + return !!(element && getComputedStyle(element).display !== 'none'); +} + +let tsParticles; +let loadAll; + +async function init(block, aemOptions) { + // eslint-disable-next-line import/no-unresolved + tsParticles = (await import('https://cdn.jsdelivr.net/npm/@tsparticles/engine@3.1.0/+esm')).tsParticles; + // eslint-disable-next-line import/no-unresolved + loadAll = (await import('https://cdn.jsdelivr.net/npm/@tsparticles/all@3.1.0/+esm')).loadAll; + const particleIdSelector = 'ts-particles'; + + const particleDiv = document.createElement('div'); + particleDiv.setAttribute('id', particleIdSelector); + + if (aemOptions) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } else { + block.parentElement.classList.add('we-container'); + } + + const particleBackground = block.parentElement.querySelector('.particle-background'); + particleBackground.prepend(particleDiv); + + async function loadParticles(options) { + await loadAll(tsParticles); + + await tsParticles.load({ id: particleIdSelector, options }); + // await loadScript('../../../_src/scripts/vendor/tsparticles/tsparticles.bundle.min.js'); + // await window.tsParticles.load({ id: particleIdSelector, options }); + // let script = document.createElement('script'); + // script.src = 'https://cdn.jsdelivr.net/npm/tsparticles@3.3.0/tsparticles.bundle.min.js'; + // script.src = 'https://dlp-fixes--www-websites--bitdefender.hlx.page/_src/scripts/vendor/tsparticles/tsparticles.bundle.min.js'; + // script.src = '../../../_src/scripts/vendor/tsparticles/tsparticles.bundle.min.js'; + // block.appendChild(script); + // script.onload = () => { + // console.log('tsParticles loaded'); + // // console.log('tsParticles', tsParticles); + // (async () => { + // // await loadFull(tsParticles); + // await window.tsParticles.load({ id: particleIdSelector, options }); + // })(); + // }; + } + const options = { + particles: { + number: { + value: 20, + }, + color: { + value: '#ffffff', + }, + links: { + enable: true, + distance: 200, + }, + shape: { + type: 'circle', + }, + opacity: { + value: 0.6, + }, + size: { + value: { + min: 2, + max: 4, + }, + }, + move: { + enable: true, + speed: 0.5, + }, + }, + background: { + color: '#016DFF', + }, + poisson: { + enable: true, + }, + fullScreen: { enable: false }, + }; + + await loadParticles(options); +} + +// eslint-disable-next-line no-unused-vars +async function checkForMobile() { + const isMobileView = isView('mobile'); + if (isMobileView && (!tsParticles && !loadAll)) { + return; + } + + if (isMobileView && tsParticles) { + const particles = tsParticles.domItem(0); + particles.pause(); + return; + } + + if (!isMobileView && (!tsParticles && !loadAll)) { + await init(); + return; + } + + const particles = tsParticles.domItem(0); + particles.play(); +} + +export default async function decorate(block, options) { + await init(block, options); + + // uncomment this line if you want the bubbles to stop moving on mobile + // window.addEventListener('resize', debounce(checkForMobile, 250)); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/percentage-vsb/percentage-vsb.css b/_src/blocks/percentage-vsb/percentage-vsb.css new file mode 100644 index 000000000..efabe30bc --- /dev/null +++ b/_src/blocks/percentage-vsb/percentage-vsb.css @@ -0,0 +1,109 @@ +/* stylelint-disable no-descending-specificity */ +.percentage-vsb-container { + display: flex; + justify-content: center; + font-family: 'IBM Plex Sans', sans-serif; +} + +.percentage-vsb-container.we-container{ + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.percentage-vsb-container a{ + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.percentage-vsb-container a:hover { + background-color: #d80000; + border: 2px solid #d80000; + cursor: pointer; +} + +.percentage-vsb-wrapper { + max-width: 630px; + display: flex; + flex-direction: column; + align-items: center; + +} + +.percentage-vsb-wrapper .columns-container{ + display:flex; + flex-direction: column; + gap:0; +} + +.percentage-vsb-wrapper .columns-container .col{ + width: 100%; + padding: 5px; +} + +.percentage-vsb-wrapper .title-class h2{ + font-size: 38px; + line-height: 40px; + margin-top: 1em; +} + +.percentage-vsb-wrapper .subtitle-class{ + font-size:18px; +} + +.percentage-vsb-wrapper .columns-container h4{ + font-size: 38px; + color: #F00F0F; + margin-top: 0; + margin-bottom: 9px; +} + +.percentage-vsb-wrapper .button-container{ + display: flex; + justify-content: center; + margin-top: 1em; +} + +@media (min-width: 768px) { + .percentage-vsb-wrapper .columns-container{ + display:flex; + flex-direction: row; + margin-top:35px; + margin-bottom: 42px; + gap:20px; + } + +.percentage-vsb-wrapper .columns-container .col{ + width: 33.33%; +} + +.percentage-vsb-wrapper .title-class h2{ + font-size:48px; + line-height: 55px; +} + +.percentage-vsb-wrapper .columns-container h4{ + font-size: 48px; + line-height: 55px; +} +} diff --git a/_src/blocks/percentage-vsb/percentage-vsb.js b/_src/blocks/percentage-vsb/percentage-vsb.js new file mode 100644 index 000000000..bb1fb553a --- /dev/null +++ b/_src/blocks/percentage-vsb/percentage-vsb.js @@ -0,0 +1,49 @@ +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + const [ + title, + subtitle, + button, + colTitle1, + colText1, + colTitle2, + colText2, + colTitle3, + colText3, + ] = block.children; + + title.classList.add('title-class'); + subtitle.classList.add('subtitle-class'); + const columnsContainer = document.createElement('div'); + columnsContainer.classList.add('columns-container'); + + const column1 = document.createElement('div'); + column1.appendChild(colTitle1); + column1.appendChild(colText1); + columnsContainer.appendChild(column1); + column1.classList.add('col'); + + const column2 = document.createElement('div'); + column2.appendChild(colTitle2); + column2.appendChild(colText2); + columnsContainer.appendChild(column2); + column2.classList.add('col'); + + const column3 = document.createElement('div'); + column3.appendChild(colTitle3); + column3.appendChild(colText3); + columnsContainer.appendChild(column3); + column3.classList.add('col'); + block.appendChild(columnsContainer); + button.classList.add('button-container'); + block.appendChild(button); + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/product-cards-ab/product-cards-ab.css b/_src/blocks/product-cards-ab/product-cards-ab.css new file mode 100644 index 000000000..3bbf67a42 --- /dev/null +++ b/_src/blocks/product-cards-ab/product-cards-ab.css @@ -0,0 +1,354 @@ +.product-cards-ab-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1300px; + --section-desktop-padding: 20px; + --section-large-desktop-max-width: 1332px; + --section-large-desktop-padding: 50px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); +} + +@media (min-width: 992px) { /* desktop */ + .product-cards-ab-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +@media (min-width: 1600px) { /* large desktop */ + .product-cards-ab-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +.product-cards-ab-wrapper { + background-color: #EDF9FF; + border-radius: 20px; +} + +.we-container { + margin: 0 auto; + max-width: 1292px; + position: relative; + padding-bottom: 64px; +} + +.product-cards-ab-container .icon svg { + width: 100%; + height: 100%; +} + +.product-cards-ab-container h2 { + font: normal normal bold 28px/32px var(--body-font-family); + text-align: center; + margin-bottom: 21px; +} + +.product-cards-ab-wrapper > div:first-of-type { + text-align: center; +} + +.product-cards-ab-wrapper > div:first-of-type h3 { + padding-top: 52px; + font: normal normal bold 40px/45px var(--body-font-family); + margin: 0; +} + +.product-cards-ab-wrapper > div:first-of-type h3 strong { + color: #006DFF; +} + +.product-cards-ab-wrapper > div:first-of-type h3 strong em { + color: #006DFF; + font-style: normal; +} + +.product-cards-ab-wrapper > div:first-of-type p { + font: normal normal normal 18px/21px var(--body-font-family); +} + +.product-cards-ab-wrapper > div:last-of-type { + text-align: center; + padding: 40px 0 57px; +} + +.product-cards-ab-wrapper > div:last-of-type p { + font: normal normal normal 12px/14px var(--body-font-family); +} + +.product-cards-ab-wrapper > div:last-of-type p .icon { + width: 14px; + height: 14px; + position: relative; + margin-right: 9px; + margin-bottom: 0; + top: 3px; + fill: #1C7928; + display: inline-block; +} + +.product-cards-ab-wrapper > div:last-of-type p a { + color: var(--text-color); + text-decoration: underline; +} + +.product-cards-ab-wrapper > div:last-of-type p a:hover { + color: var(--text-color); + text-decoration: none; +} + +.product-cards-ab.block { + display: grid; + justify-content: center; + align-items: center; + grid-template-columns: repeat(auto-fill, minmax(300px, 410px)); + grid-gap: 28px; + padding: 0 5px; +} + +.product-cards-ab.block > div { + padding: 28px; + background-color: white; + box-shadow: 0 3px 6px #00000029; + border: 3px solid #006DFF; + border-radius: 20px; +} + +.product-cards-ab.block .description { + position: relative; +} + +.product-cards-ab.block .description .icon { + width: 57px; + height: 37px; + position: absolute; + top: -48px; + right: 0; + fill: #006DFF; +} + +.product-cards-ab.block .product-info h2 { + font: normal normal bold 22px/24px var(--body-font-family); + margin-bottom: 14px; +} + +.product-cards-ab.block .product-info .protect { + font: normal normal normal 16px/32px var(--body-font-family); + border-bottom: 1px solid #D1D1D1; + padding-bottom: 14px; + margin-bottom: 14px; +} + +.product-cards-ab.block .product-info .description { + font: normal normal normal 12px/14px var(--body-font-family); +} + +.product-cards-ab.block .product-info .description strong { + color: #1D7928; + font-weight: bold; +} + +.product-cards-ab.block .product-info .buynow a { + font: normal normal bold 16px/20px var(--body-font-family); + margin-top: 24px; + padding: 14px 28px; + color: #fff; + background: #E72325; + border-radius: 10px; + display: block; + position: relative; + min-width: 180px; + text-align: center; + text-decoration: none; +} + +.product-cards-ab.block .product-info .buynow a:focus { + outline: 2px solid #48C1FF; + border-radius: 13px; + outline-offset: 2px; +} + +.product-cards-ab.block .product-info .buynow a:hover { + padding: 14px 28px; + background: #B10304; + color: #fff; +} + +.product-cards-ab.block .product-info .feature-list { + border-top: 1px solid #D1D1D1; + padding-top: 14px; + margin-top: 14px; +} + +.product-cards-ab.block .product-info .feature-list ul { + list-style: none; + margin: 0; + padding: 0; + display: inline-block; +} + +.product-cards-ab.block .product-info .feature-list ul li { + font: normal normal normal 14px/32px var(--body-font-family); + margin: 0; + padding: 0; +} + +.product-cards-ab.block .product-info .feature-list ul li .icon { + width: 16px; + height: 16px; + position: relative; + margin-right: 9px; + margin-bottom: 0; + top: 3px; + display: inline-block; +} + +.product-cards-ab.block .product-info .feature-list ul li .icon.icon-x-circle svg { + fill: #999; +} + +.product-cards-ab.block .product-info .feature-list ul li del { + color: #999; +} + +.product-cards-ab.block .price-area .tab-buttons button { + font: normal normal bold 16px/28px var(--body-font-family); + padding: 7px 14px; + margin-right: 7px; + margin-bottom: 24px; + color: #2B6CF6; + background: #fff; + border: 2px solid #ECF5FE; + border-radius: 8px; + display: inline-block; + position: relative; + text-align: center; + text-decoration: none; + cursor: pointer; +} + +.product-cards-ab.block .price-area .tab-buttons button:hover { + background: #2B6CF6; + color: #fff; + border: 2px solid #2B6CF6; +} + +.product-cards-ab.block .price-area .tab-buttons button.active { + background: #2B6CF6; + color: #fff; + border: 2px solid #2B6CF6; +} + +.product-cards-ab.block .price-area .tab-content { + margin-bottom: 8px; +} + +.product-cards-ab.block .price-area .tab-content .tab-panel { + display: none; +} + +.product-cards-ab.block .price-area .tab-content .tab-panel .prod-oldprice { + text-align: left; + text-decoration: line-through; + font: normal normal normal 16px/18px var(--body-font-family); +} + +.product-cards-ab.block .price-area .tab-content .tab-panel .prod-save { + text-align: left; + font: normal normal bold 12px/14px var(--body-font-family); + padding: 3px 9px; + background: #1C7928 0% 0% no-repeat padding-box; + border-radius: 22px; + color: #fff; +} + +.product-cards-ab.block .price-area .tab-content .tab-panel .prod-newprice { + text-align: left; + font: normal normal bold 40px/45px var(--body-font-family); + color: #006DFF; +} + +@media (max-width: 1600px) { + .product-cards-ab-container.we-container { + max-width:1200px; + padding: 0 50px 64px; + } +} + +@media (max-width: 992px) { + .product-cards-ab-container.we-container { + padding:0 20px 64px; + } +} + +@media (max-width: 370px) { + .product-cards-ab.block > div { + padding: 14px; + } + + .product-cards-ab.block { + grid-template-columns: 1fr; + } +} \ No newline at end of file diff --git a/_src/blocks/product-cards-ab/product-cards-ab.js b/_src/blocks/product-cards-ab/product-cards-ab.js new file mode 100644 index 000000000..efb23fee9 --- /dev/null +++ b/_src/blocks/product-cards-ab/product-cards-ab.js @@ -0,0 +1,217 @@ +/* eslint-disable indent */ +// import { decorateIcons } from '../../scripts/lib-franklin.js'; +// import { fetchProduct } from '../../scripts/utils/utils.js'; + +/* eslint-disable prefer-const */ +/* eslint-disable no-undef */ +/* eslint-disable max-len */ + +let adobeDataLayerArray = []; +export default async function decorate(block, options) { + const { + pid, offtext, yearly, monthly, firstyear, + } = block.closest('.section').dataset; + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + let blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + const firstRow = block.firstElementChild; + const lastRow = block.lastElementChild; + /* eslint-disable-next-line prefer-destructuring */ + const parentNode = block.parentNode; // Get the parent of the block + if (firstRow && parentNode) { + parentNode.insertBefore(firstRow, block); // Insert the first row before the block + } + if (lastRow && parentNode) { + parentNode.appendChild(lastRow); // Insert the last row after the block + } + const productCardsElement = parentNode.querySelector('.product-cards-ab'); // Get the container element + const tables = productCardsElement.querySelectorAll('table'); // Find all tables within the container + + let globalDiscountPercentage = 0; + + /* eslint-disable no-restricted-syntax */ + for (const table of tables) { + // Create a new div to replace the table + const productInfoDiv = document.createElement('div'); + productInfoDiv.classList.add('product-info'); + + // Process and replace table content: + const tableBody = table.querySelector('tbody'); // Get the table body + + // Handle remaining content (code, discount, buttons) + const heading = tableBody.querySelector('tr:first-child td').innerHTML; + const protect = tableBody.querySelector('tr:nth-child(2) td').innerHTML; + const productArea = tableBody.querySelector('tr:nth-child(3) td').innerHTML; + const code = tableBody.querySelector('tr:nth-child(4) td').innerHTML; + const buyNowButton = tableBody.querySelector('tr:nth-child(5) td').innerText; + const featureList = tableBody.querySelector('tr:nth-child(6) td').innerHTML; + + productInfoDiv.innerHTML = ` +

    ${heading}

    +
    ${protect}
    +
    ${productArea}
    +
    +
    +
    +
    +
    ${code}
    + +
    ${featureList}
    + `; + + // Replace the table with the new div structure + table.parentNode.replaceChild(productInfoDiv, table); + + const productsAsList = productArea.split(','); + const tabButtons = productInfoDiv.querySelector('.price-area .tab-buttons'); + const tabContent = productInfoDiv.querySelector('.price-area .tab-content'); + + // eslint-disable-next-line no-loop-func, no-await-in-loop + await Promise.all(productsAsList.map(async (prod) => { + const [prodName, prodUsers, prodYears] = prod.split('/'); + + const button = document.createElement('button'); + button.classList.add('tab-button'); + button.setAttribute('data-tab', `${prodName}`); + button.setAttribute('data-prodlink', `${prodName}/${prodUsers}/${prodYears}`); + // button.textContent = `${prodName}`; + tabButtons.appendChild(button); + + const { fetchProduct } = await import('../../scripts/utils/utils.js'); + let oldPrice; + let newPrice; + let discountPercentage; + + // build pid for link + let pidLink = ''; + if (pid.length) { + pidLink = `pid.${pid}`; + } + + const tab = document.createElement('div'); + tab.classList.add('tab-panel'); + tab.setAttribute('id', `${prodName}`); + const product = await fetchProduct(prodName, `${prodUsers}u-${prodYears}y`, pid); + try { + discountPercentage = Math.round( + (1 - (product.discount.discounted_price) / product.price) * 100, + ); + oldPrice = product.price; + newPrice = product.discount.discounted_price; + let currencyLabel = product.currency_label; + tab.innerHTML = ` +
    + ${currencyLabel}${oldPrice} + ${discountPercentage}% ${offtext} +
    +
    + ${currencyLabel}${newPrice}/ ${firstyear} +
    `; + tabContent.appendChild(tab); + // add discount value to component title, only if it's not a monthly subscription + // this is due to an a/b test and should be removed after the test is finished + if (discountPercentage > globalDiscountPercentage && prodName !== 'psm' && prodName !== 'pspm') { + globalDiscountPercentage = discountPercentage; + } + + // tabbed code + setTimeout(() => { + const tabButton = productInfoDiv.querySelectorAll('.tab-button'); + const tabPanel = productInfoDiv.querySelectorAll('.tab-panel'); + const buybutton = productInfoDiv.querySelector('.buy-button'); + + tabButton.forEach((buttonTab) => { + buttonTab.addEventListener('click', () => { + // Remove "active" class from all tab buttons + tabButton.forEach((tabB) => { + tabB.classList.remove('active'); + }); + + // Add "active" class to the clicked tab button + buttonTab.classList.add('active'); + + // Hide all tab panels + tabPanel.forEach((panel) => { + panel.style.display = 'none'; + }); + + // Show the selected tab panel + const tabId = buttonTab.getAttribute('data-tab'); + const selectedPanel = parentNode.querySelector(`#${tabId}`); + if (selectedPanel) { + selectedPanel.style.display = 'block'; + // replace href with correct buy link + const dataProdLink = buttonTab.dataset.prodlink; + buybutton.href = `/site/Store/buy/${dataProdLink}/${pidLink}`; + } + }); + + // Simulate click on the first tab button + if (tabButton.length > 0) { + tabButton[0].textContent = yearly; + tabButton[1].textContent = monthly; + tabButton[0].click(); + } + }); + }, 500); + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + } + + if (options) { + const storeProduct = await options.store.getProducts([new ProductInfo(prodName, 'consumer')]); + const storeOption = storeProduct[prodName].getOption(prodUsers, prodYears); + if (!storeOption.getName().includes('Monthly')) { + adobeDataLayerArray.push({ + info: { + ID: storeOption.getAvangateId(), + name: storeOption.getName(), + devices: storeOption.getDevices(), + subscription: storeOption.getSubscription('months'), + version: storeOption.getSubscription('months') === 1 ? 'monthly' : 'yearly', + basePrice: storeOption.getPrice('value'), + discountValue: storeOption.getDiscount('value'), + discountRate: storeOption.getDiscount('percentage'), + currency: storeOption.getCurrency(), + priceWithTax: storeOption.getDiscountedPrice('value') || storeOption.getPrice('value'), + }, + }); + } + } + })); + } + + const discountXX = parentNode.querySelector('.product-cards-ab-container h3 strong em'); + const xx = document.createElement('em'); + xx.innerHTML = `${globalDiscountPercentage}%`; + discountXX.replaceWith(xx); + + const elementsToRemove = block.querySelectorAll('.product_area'); + elementsToRemove.forEach((element) => { + element.remove(); + }); + + if (options) { + window.addEventListener('codeBaseFinishedRunning', () => { + window.adobeDataLayer.push({ + event: 'product loaded', + product: null, + }); + + window.adobeDataLayer.push({ + event: 'product loaded', + product: adobeDataLayerArray, + }); + }); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/solutions/blocks/product-comparison-table/product-comparison-table.css b/_src/blocks/product-comparison-table/product-comparison-table.css similarity index 78% rename from solutions/blocks/product-comparison-table/product-comparison-table.css rename to _src/blocks/product-comparison-table/product-comparison-table.css index 95caa7052..e7dc94017 100644 --- a/solutions/blocks/product-comparison-table/product-comparison-table.css +++ b/_src/blocks/product-comparison-table/product-comparison-table.css @@ -54,6 +54,8 @@ .product-comparison-header div[role="columnheader"]:not(:first-child) { border: 1px solid var(--first-table-cell-color); flex: 1; + display: flex; + flex-direction: column; } .product-comparison-header div[role="columnheader"]:not(:first-child).active { @@ -83,7 +85,7 @@ .product-comparison-price { padding-top: 0.9375rem; margin: 0.9375rem 0.625rem 0; - border-top: 1px solid var(--horizontal-separator-color); + border-top: 1px solid var(--horizontal-separator-color); } .current-price-container p{ @@ -107,12 +109,18 @@ div[role="cell"] .button-container , .product-comparison-header div[role="column margin-bottom: 0.3125rem; } +.section.product-comparison-table-container.migration p { + color: #7e7e7e; + font-size: 12px; +} + .product-comparison-header div[role="columnheader"] p:first-of-type { font-weight: var(--font-weight-bold); padding: 0; color: var(--product-comparison-text-color); text-align: center; font-size: var(--body-font-size-xs); + flex-grow: 1; } .product-comparison-header div[role="cell"] p:first-of-type { @@ -167,10 +175,9 @@ div[role="cell"] p:last-of-type.product-comparison-header-subtitle, .product-comparison-header div[role="columnheader"] h3 { margin: 3rem 0.625rem 0.25rem; font-size: var(--heading-font-size-s); - min-height: 4rem; } -.product-comparison-header div[role="columnheader"] .old-price-container p{ +.product-comparison-header div[role="columnheader"] .old-price-container p { font-size: var(--body-font-size-xxs); line-height: 1.2; color: var(--product-comparison-text-color); @@ -277,6 +284,31 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { border-right: 1px solid var(--background-color-light-sky-blue); } +@media (max-width: 580px) { + .product-comparison-table.with-fixed-width { + width: 100%; + } + + .product-comparison-price .current-price-container, .product-comparison-header div[role="columnheader"] h3 { + font-size: var(--body-font-size-xs); + } + + .product-comparison-header div[role="columnheader"] h3 { + margin: 10px 0 0; + } + + .product-comparison-header div[role="columnheader"] p { + min-height: 3rem; + } + + .product-comparison-header div[role="columnheader"] p.button-container.red a { + font-size: var(--body-font-size-xxs); + padding: 5px 0; + text-align: center; + width: 100%; + } +} + @media (min-width: 580px) { .product-comparison-table-wrapper { margin: 0 auto; @@ -334,7 +366,7 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { .product-comparison-header-subtitle { padding: 0 4rem; } - + .product-comparison-table div[role='cell'] { display: table-cell; @@ -353,14 +385,14 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { .product-comparison-table div[role='cell'] > div { display: flex; justify-content: center; - + } .collapsed.hidden-rows-wrapper { max-height: 0; transition: max-height .5s ease-in-out; overflow: hidden; - + } .expanded.hidden-rows-wrapper { @@ -467,4 +499,101 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { .display-price-below .product-comparison-price { border: none; +} + +.product-comparison-table.two-products { + width: 100%; +} + +@media (width <= 1202px) { + .product-comparison-table div[role='columnheader']:nth-child(1) > h2 { + font-size: var(--heading-font-size-l); + } + + .section.product-comparison-table-container.migration .old-price-box span { + font-size: 13px; + flex-direction: column; + display: flex !important; + } + + .section.product-comparison-table-container.migration .old-price-box span:first-of-type { + text-align: left; + } + + .section.product-comparison-table-container.migration h3 { + font-size: 21px !important; + margin-top: 1em !important; + } + + .section.product-comparison-table-container.migration .new-price-box .total-text { + font-size: 16px; + } + } + + .section.product-comparison-table-container.migration .product-comparison-price { + border: 0 none!important; +} + +.section.product-comparison-table-container.migration h3 { + font-family: roboto, sans-serif; + font-size: 24px !important; + color: black !important; + font-weight: 500; + line-height: 1.25; +} + +.section.product-comparison-table-container.migration .old-price-box { + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px dashed #dedede; + padding-bottom: 10px; +} + +.section.product-comparison-table-container.migration .old-price-box .savings { + display: block; + background: rgba(44, 180, 61, .2); + border-radius: 8px; + padding: 1px 9px 5px; + text-align: right; + color: #2cb43d; + font-size: 14px; + font-weight: 500; + line-height: 1.5; +} + +.section.product-comparison-table-container.migration .new-price-box { + display: flex; + justify-content: space-between; + align-items: center; + margin: 10px auto 0; + font-size: 24px; + font-weight: 700; + line-height: .9; + color: black; +} + +.section.product-comparison-table-container.migration .new-price-box .total-text { + display: block; + color: #3c3c3c; + display: inline-block; + font-size: 18px; + line-height: 1.25; + margin-right: auto; + padding: 0; + font-weight: normal; +} + +.section.product-comparison-table-container.migration p.button-container { + margin-bottom: 2em; +} + +.section.product-comparison-table-container.migration .product-comparison-price > p:last-of-type{ + text-align: right; + color: #3c3c3c; + display: block; + font-size: 10px; + font-weight: 400; + line-height: 2; + margin-bottom: 0; } \ No newline at end of file diff --git a/solutions/blocks/product-comparison-table/product-comparison-table.js b/_src/blocks/product-comparison-table/product-comparison-table.js similarity index 87% rename from solutions/blocks/product-comparison-table/product-comparison-table.js rename to _src/blocks/product-comparison-table/product-comparison-table.js index 42c9e0a23..f9d8bf5e9 100644 --- a/solutions/blocks/product-comparison-table/product-comparison-table.js +++ b/_src/blocks/product-comparison-table/product-comparison-table.js @@ -1,8 +1,10 @@ -import { createNanoBlock, renderNanoBlocks, fetchProduct } from '../../scripts/utils.js'; +import { + createNanoBlock, renderNanoBlocks, fetchProduct, matchHeights, +} from '../../scripts/utils/utils.js'; const fetchedProducts = []; -createNanoBlock('price-comparison', (code, variant, label) => { +createNanoBlock('priceComparison', (code, variant, label, block) => { const priceRoot = document.createElement('div'); priceRoot.classList.add('product-comparison-price'); const oldPriceElement = document.createElement('p'); @@ -21,9 +23,22 @@ createNanoBlock('price-comparison', (code, variant, label) => { fetchedProducts.push({ code, variant, product }); // eslint-disable-next-line camelcase const { price, discount: { discounted_price: discounted }, currency_iso: currency } = product; - oldPriceElement.innerHTML = `Old Price ${price} ${currency}`; - priceElement.innerHTML = `${discounted} ${currency}`; + const savings = price - discounted; + + oldPriceElement.innerHTML = `
    + Old Price ${price} ${currency} + Savings ${savings.toFixed(2)} ${currency} +
    `; + priceElement.innerHTML = `
    + Your total price: + ${discounted} ${currency} +
    `; priceAppliedOnTime.innerHTML = label; + + // update buy link + const currentProductIndex = fetchedProducts.length - 1; + const buyLink = block.querySelectorAll('.button-container a')[currentProductIndex]; + buyLink.href = fetchedProducts[currentProductIndex].product.buy_link; }) .catch((err) => { // eslint-disable-next-line no-console @@ -266,5 +281,13 @@ export default function decorate(block) { } extractTextFromStrongTagToParent(block); - renderNanoBlocks(block); + const headerList = [...block.children[0].children].slice(1); + const lastRowWithPrice = block.querySelector('.product-comparison-last-row-with-prices'); + [...headerList, lastRowWithPrice].forEach((item, idx) => { + if (item) { + renderNanoBlocks(item, undefined, idx, block); + } + }); + + matchHeights(block, 'h3'); } diff --git a/_src/blocks/products-sideview/products-sideview.css b/_src/blocks/products-sideview/products-sideview.css new file mode 100644 index 000000000..190a3cd44 --- /dev/null +++ b/_src/blocks/products-sideview/products-sideview.css @@ -0,0 +1,321 @@ +:root { + --tab-header-color-blue: #005ed9; + --tab-description-color-light-grey: #3c3c3c; + --tab-emphasis-color: #2cb43d; +} + +.products-sideview .features-wrapper { + background: #eff6ff; + padding: 30px; + border-radius: 0 0 20px 20px; +} + +.products-sideview .features-wrapper > p, +.products-sideview .pricing-wrapper > p { + font-size: 18px; + line-height: 1.5; + letter-spacing: .006em; + font-weight: var(--font-weight-regular); +} + +.products-sideview .pricing-wrapper { + background: #f6f6f6; + border-radius: 20px 20px 0 0; + padding: 30px; +} + +.products-sideview .pricing-wrapper > p:last-child { + text-align: center; +} + +.products-sideview p.button-container > a { + width: 100%; + justify-content: center; +} + +.products-sideview .price { + font-size: 32px; + font-weight: bold; + margin: 20px 0; +} + +.products-sideview .tag-blue { + background: var(--tab-header-color-blue); + color: white; + padding: 0 10px; + border-radius: 10px; + margin-left: 5px; + font-size: 14px; + line-height: 1; + font-weight: bolder; +} + +.products-sideview-radio { + display: flex; + align-items: center; + margin-left: -2px; + margin-top: 20px; + margin-bottom: 20px; +} + +.products-sideview-radio input { + width: 25px; + height: 25px; + margin: 0; +} + +.products-sideview-radio label { + margin-left: 5px; +} + +.products-sideview-radio input:nth-last-child(2) { + margin-left: 20px; +} + +.products-sideview-selector { + position: relative; +} + +.products-sideview-selector select { /* Remove default styling */ + appearance: none; + width: 100%; + border: 1px solid #ccc; + background-color: white; + padding: 10px; + font-size: 18px; + font-weight: bold; + border-radius: 5px; +} + +.products-sideview-selector::after { + content: ''; + background: url("/_src/icons/tabs_arrow.svg") no-repeat; + position: absolute; + top: 50%; + right: 10px; + transform: rotate(180deg) translateY(50%); + pointer-events: none; /* Prevent the arrow from blocking clicks */ + width: 15px; + height: 15px; +} + +.products-sideview li { + padding: 0; + margin: 0 0 10px; +} + + +.products-sideview .benefits-list > li { + position: relative; + padding-left: 25px; + margin: 0 0 5px; +} + +.products-sideview .benefits-list > li::before { + content: url("/_src/icons/checkmark-green-circle.svg"); + position: absolute; + left: 0; + top: 4px; + width: 18px; + height: 18px; +} + +.products-sideview-wrapper { + padding: 0 var(--body-padding); +} + +.products-sideview { + /* box-shadow: 0 3px 8px 0 var(--dark-shadow); */ + + /* border-radius: 8px; */ + + /* padding: 40px 15px 20px; */ +} + +.products-sideview > div { + display: flex; + flex-direction: column; + align-items: stretch; +} + +.products-sideview img { + width: 100%; +} + +.products-sideview > div > div { + position: relative; + order: 1; +} + +.products-sideview > div > div:last-child::after { + display: none; +} + +.products-sideview > div > .features-img-col { + order: 0; +} + +.products-sideview > div > .features-img-col img { + display: block; +} + +.products-sideview p.features-tabs-hidden { + display: none; +} + +.products-sideview ul { + padding: 0; +} + +.products-sideview .features-tabs li > a { + color: var(--tab-header-color-blue); + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + position: relative; + display: inline-block; + letter-spacing: .004em; + cursor: pointer; + text-decoration: none; + padding-left: 25px; +} + +.products-sideview .features-tabs li > a::after { + content: ""; + position: absolute; + left: 0; + top: 0; + display: inline-block; + width: 14px; + height: 8px; + margin: 9px 3px; + background: url("/_src/icons/tabs_arrow.svg") no-repeat; + background-size: 100%; + transform: rotate(180deg); + transition: all .3s linear; +} + +.products-sideview .features-tabs li > a.is-open::after { + transform: rotate(0) +} + +.products-sideview .features-tabs .features-tabs-content { + opacity: 0; + height: 0; + overflow: hidden; + margin-left: 25px; + transition: all 0.3s ease-in-out; +} + +.products-sideview .features-tabs .features-tabs-content.expanded { + opacity: 1; + height: auto; + transition: all 0.3s ease-in-out; + display: block; +} + +.products-sideview .features-tabs .features-tabs-content > p { + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-regular); + line-height: 1.6; +} + +@media (min-width: 480px) { + .products-sideview .features-tabs li > a { + font-size: 15px; + } +} + +@media (min-width: 768px) { + .products-sideview .features-wrapper { + border-radius: 0 20px 20px 0; + width: 50%; + } + + .products-sideview .pricing-wrapper { + border-radius: 20px 0 0 20px; /* desktop */ + width: 50% + } + + .products-sideview .pricing-wrapper h4 { + font-size: 26px; + line-height: 32.5px; + font-weight: 700; + } + + .products-sideview .features-wrapper h2 { + font-size: 38px; + line-height: 45.6px; + font-weight: 700; + } + + .features-tabs { + display: flex; + flex-wrap: wrap; + column-gap: 30px; + } + + .features-tabs > li { + position: relative; + } + + .products-sideview > div { + flex-flow: wrap; + } + + .products-sideview > div > div { + padding: 0 20px 20px; + } + + .products-sideview-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } + + .products-sideview > div > div:nth-child(2)::after { + display:none; + } +} + +@media (min-width: 993px) { + .products-sideview.features-3-cols > div > div { + width: calc(33.33% - 30px); + margin: 0 15px; + } + + .products-sideview.features-3-cols > div > div:nth-child(2)::after { + display:block; + } + + .products-sideview.features-2-cols > div > div:nth-child(2)::after { + display:none; + } +} + +@media (min-width: 1200px) { + .products-sideview .pricing-wrapper { + width: 33.33%; + } + + .products-sideview .features-wrapper { + width: 66.66%; + height: fit-content; + } + + .products-sideview .features-tabs > li { + width: calc(50% - 30px); + flex-shrink: 0; + margin-bottom: 25px; + } + + .products-sideview .features-tabs .features-tabs-content > p { + font-size: var(--body-font-size-xs); + } +} + +@media (min-width: 1600px) { /* large desktop */ + .products-sideview-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} diff --git a/_src/blocks/products-sideview/products-sideview.js b/_src/blocks/products-sideview/products-sideview.js new file mode 100644 index 000000000..ec0c3af8f --- /dev/null +++ b/_src/blocks/products-sideview/products-sideview.js @@ -0,0 +1,295 @@ +import { + createNanoBlock, + fetchProduct, + getBuyLinkCountryPrefix, + getDatasetFromSection, + getPidFromUrl, + renderNanoBlocks, +} from '../../scripts/utils/utils.js'; + +const state = { + firstProduct: null, + secondProduct: null, + currentProduct: null, + mode: 'm', // "m" or "y", + membersIndex: 0, +}; + +const MEMBERS_MAP = new Map([ + [0, 3], + [1, 5], + [2, 10], + [3, 25], +]); + +function expandItem(content) { + content.style.height = `${content.scrollHeight}px`; + const transitionEndCallback = () => { + content.removeEventListener('transitionend', transitionEndCallback); + content.style.height = 'auto'; + }; + content.addEventListener('transitionend', transitionEndCallback); + content.classList.add('expanded'); +} + +function collapseItem(content) { + content.style.height = `${content.scrollHeight}px`; + requestAnimationFrame(() => { + content.classList.remove('expanded'); + content.style.height = 0; + }); +} + +function eventListener(ul) { + return (event) => { + let target = null; + + // find ancestor a tag + if (event.target.tagName !== 'A') { + target = event.target.closest('a'); + } else { + target = event.target; + } + + // if the clicked node is not open then open it + if (!target.classList.contains('is-open')) { + target.classList.add('is-open'); + + // if the clicked node has children then toggle the expanded class + if (target.parentNode.children.length > 1) { + target.parentNode.querySelectorAll('.features-tabs-content').forEach((content) => { + expandItem(content); + }); + } + + // hid the other tabs + ul.querySelectorAll('li').forEach((collapsedLi) => { + if (collapsedLi !== target.parentNode) { + collapsedLi.children[0].classList.remove('is-open'); + collapsedLi.querySelectorAll('.features-tabs-content').forEach((content) => { + collapseItem(content); + }); + } + }); + } else { + target.classList.remove('is-open'); + // if the clicked node has children then toggle the expanded class + if (target.parentNode.children.length > 1) { + target.parentNode.querySelectorAll('.features-tabs-content').forEach((content) => { + collapseItem(content); + }); + } + } + }; +} + +function extractFeatures(col) { + const ul = document.createElement('ul'); + ul.classList.add('features-tabs'); + + // select all h4 tags as feature titles + col.querySelectorAll('h4').forEach((h4) => { + const li = document.createElement('li'); + ul.appendChild(li); + + const a = document.createElement('a'); + a.setAttribute('href', '#'); + + // register click event on a tag + + a.addEventListener('click', (event) => { + event.preventDefault(); + eventListener(ul)(event); + }); + + h4.childNodes.forEach((node) => { + if (node.nodeType === Node.TEXT_NODE) { + a.appendChild(document.createTextNode(node.textContent)); + } else { + a.appendChild(node); + } + }); + + a.classList.add('features-tabs-title'); + + li.appendChild(a); + + // all descendants of a that have class tag + a.querySelectorAll('.tag').forEach((tag) => { + li.appendChild(tag); + }); + + const content = document.createElement('div'); + content.classList.add('features-tabs-content'); + li.appendChild(content); + + // every oaragraph until next h4 + let nextElement = h4.nextElementSibling; + while (nextElement && nextElement.tagName !== 'H4') { + content.appendChild(nextElement); + nextElement = h4.nextElementSibling; + } + + ul.appendChild(li); + + h4.remove(); + }); + + return ul; +} + +function updateBuyLink(block) { + const buyLink = block.querySelector('.button-container > .button'); + const productCode = state.currentProduct.alias; + const dimension = MEMBERS_MAP.get(state.membersIndex); + const { years } = state.currentProduct.variation; + const pid = getPidFromUrl(); + + if (buyLink) { + buyLink.href = `${getBuyLinkCountryPrefix()}/${productCode}/${dimension}/${years}/${pid ? `pid.${pid}` : ''}`; + } +} + +function updatePrice(block) { + const isMonthly = state.mode === 'm'; + const priceEl = block.querySelector('.price'); + + (async () => { + const product = isMonthly + ? state.secondProduct + : state.firstProduct; + + state.currentProduct = product; + const variant = `${MEMBERS_MAP.get(state.membersIndex)}u-1y`; + const resp = await fetchProduct(product.alias, variant); + priceEl.textContent = `${resp.currency_label} ${resp.price}`; + })(); +} + +function renderPrice(block, firstProduct, secondProduct) { + const variant = '3u-1y'; + + const el = document.createElement('DIV'); + el.classList.add('price'); + + Promise.all([ + fetchProduct(firstProduct, variant), + fetchProduct(secondProduct, variant), + ]).then(([vsb, vsbm]) => { + state.firstProduct = vsb; + state.firstProduct.alias = firstProduct; + state.secondProduct = vsbm; + state.secondProduct.alias = secondProduct; + updatePrice(block); + updateBuyLink(block); + }); + + return el; +} + +function renderRadioGroup(block) { + const el = document.createElement('DIV'); + el.classList.add('products-sideview-radio'); + + el.innerHTML = ` + + + + + + `; + + const radioButtons = el.querySelectorAll('input[name="type"]'); + + radioButtons.forEach((radio) => { + radio.addEventListener('change', (event) => { + state.mode = event.target.value; + + updatePrice(block); + + // update buy link + updateBuyLink(block); + }); + }); + + return el; +} + +function updateBenefits(block) { + const blockDataset = getDatasetFromSection(block); + const ul = block.querySelector('ul'); + if (ul) { + ul.classList.add('benefits-list'); + try { + const benefitsList = blockDataset.benefits.split(',,').map((b) => JSON.parse(b)); + const currentBenefitSelection = benefitsList[state.membersIndex]; + ul.querySelectorAll('li').forEach((li, index) => { + const numberOfBenefitsTag = document.createElement('SPAN'); + numberOfBenefitsTag.textContent = `x${currentBenefitSelection[index]}`; + numberOfBenefitsTag.classList.add('tag-blue'); + + // Find the last span element within the li + const lastSpan = li.querySelector('span:last-of-type'); + + // Replace the last span element with the new one + if (lastSpan) { + li.replaceChild(numberOfBenefitsTag, lastSpan); + } else { + // If no span is found, just append the new one + li.append(numberOfBenefitsTag); + } + }); + } catch (e) { + // eslint-disable-next-line no-console + console.log("couldn't load the benefits"); + } + } +} + +function renderSelector(block, ...options) { + const el = document.createElement('div'); + el.classList.add('products-sideview-selector'); + + el.innerHTML = ` + + `; + + el.querySelector('select').addEventListener('change', (e) => { + const value = JSON.parse(e.target.value); + state.membersIndex = value; + // update benefits + updateBenefits(block); + + // update price + updatePrice(block); + + // update buy link + updateBuyLink(block); + }); + + return el; +} + +createNanoBlock('price', renderPrice); +createNanoBlock('monthlyYearly', renderRadioGroup); +createNanoBlock('selectMembers', renderSelector); + +export default function decorate(block) { + block.firstElementChild.classList.add('d-flex'); + block.firstElementChild.firstElementChild.classList.add('pricing-wrapper'); + block.firstElementChild.lastElementChild.classList.add('features-wrapper'); + + updateBenefits(block); + + renderNanoBlocks(block.firstElementChild, block); + + const cols = [...block.firstElementChild.children]; + block.classList.add(`features-${cols.length}-cols`); + + const col = block.children[0].children[1]; + col.appendChild(extractFeatures(col)); +} diff --git a/solutions/blocks/products/products.css b/_src/blocks/products/products.css similarity index 99% rename from solutions/blocks/products/products.css rename to _src/blocks/products/products.css index edb933227..93a5f17e3 100644 --- a/solutions/blocks/products/products.css +++ b/_src/blocks/products/products.css @@ -195,6 +195,7 @@ margin: 60px 0 25px; top: auto; right: auto; + display: none; } .products.compact .product-card .featured ~ p img { diff --git a/solutions/blocks/products/products.js b/_src/blocks/products/products.js similarity index 88% rename from solutions/blocks/products/products.js rename to _src/blocks/products/products.js index 91db3574e..cafa02b44 100644 --- a/solutions/blocks/products/products.js +++ b/_src/blocks/products/products.js @@ -3,10 +3,19 @@ import { renderNanoBlocks, fetchProduct, createTag, -} from '../../scripts/utils.js'; + generateProductBuyLink, +} from '../../scripts/utils/utils.js'; import { trackProduct } from '../../scripts/scripts.js'; +// all avaiable text variables +const TEXT_VARIABLES_MAPPING = [ + { + variable: 'percent', + getValue: (mv) => `${mv.model.discountRate}%`, + }, +]; + /** * Utility function to round prices and percentages * @param value value to round @@ -55,7 +64,7 @@ function toModel(productCode, variantId, v) { ? Math.floor(((v.price - v.discount.discounted_price) / v.price) * 100) : 0, currency: v.currency_label, - url: `https://www.bitdefender.com.au/site/Store/buy/${productCode}/${v.variation.dimension_value}/${v.variation.years}/`, + url: generateProductBuyLink(v, productCode), }; } @@ -191,7 +200,7 @@ function renderOldPrice(mv, text = '', monthly = '') { * @param monthly Show the monthly price if equal to 'monthly' * @returns Root node of the nanoblock */ -function renderPrice(mv, text = '', monthly = '') { +function renderPrice(mv, text = '', monthly = '', monthTranslation = 'mo') { // TODO simplify CSS const root = createTag( 'div', @@ -206,9 +215,9 @@ function renderPrice(mv, text = '', monthly = '') { mv.subscribe(() => { if (monthly.toLowerCase() === 'monthly') { if (mv.model.discountedPrice) { - priceElt.innerHTML = `${text} ${mv.model.discountedMonthlyPrice} ${mv.model.currency} /mo`; + priceElt.innerHTML = `${text} ${mv.model.discountedMonthlyPrice} ${mv.model.currency} /${monthTranslation}`; } else { - priceElt.innerHTML = `${text} ${mv.model.monthlyBasePrice} ${mv.model.currency} /mo`; + priceElt.innerHTML = `${text} ${mv.model.monthlyBasePrice} ${mv.model.currency} /${monthTranslation}`; } } else if (mv.model.discountedPrice) { priceElt.innerHTML = `${text} ${mv.model.discountedPrice} ${mv.model.currency}`; @@ -238,7 +247,6 @@ function renderHighlightSavings(mv, text = 'Save', percent = '') { }, '', ); - mv.subscribe(() => { if (mv.model.discountRate) { root.querySelector('span').innerText = (percent.toLowerCase() === 'percent') @@ -270,6 +278,35 @@ function renderHighlight(mv, text) { ); } +/** + * + * @param mv The modelview holding the state of the view + * @param {string} text Text of the featured nanoblock + * @return {string} Text with variables replaced + */ +const replaceVariablesInText = (mv, text) => { + let replacedText = text; + + // replace the percent variable with correct percentage of the produc + TEXT_VARIABLES_MAPPING.forEach((textVariableMapping) => { + replacedText = replacedText.replaceAll( + textVariableMapping.variable, + textVariableMapping.getValue(mv), + ); + }); + + return replacedText; +}; + +/** + * + * @param {string} text + * @return {boolean} wether the text contains variables or not + */ +const checkIfTextContainsVariables = (text) => TEXT_VARIABLES_MAPPING.some( + (textVariableMapping) => text.includes(textVariableMapping.variable), +); + /** * Nanoblock representing a text to Featured * @param mv The modelview holding the state of the view @@ -280,6 +317,15 @@ function renderFeatured(mv, text) { const root = document.createElement('div'); root.classList.add('featured'); root.innerText = text; + + if (checkIfTextContainsVariables(text)) { + root.classList.add('global-display-none'); + mv.subscribe(() => { + root.innerText = replaceVariablesInText(mv, root.innerText); + root.classList.remove('global-display-none'); + }); + } + return root; } @@ -364,19 +410,19 @@ createNanoBlock('lowestPrice', renderLowestPrice); * Main decorate function */ export default function decorate(block) { - [...block.children].forEach((row) => { + [...block.children].forEach((row, idxParent) => { [...(row.children)].forEach((col) => { col.classList.add('product-card'); block.appendChild(col); const mv = new ProductCard(col); - renderNanoBlocks(col, mv); + renderNanoBlocks(col, mv, idxParent); // listen to ProductCard change and update the buttons pointing to the store url mv.subscribe((card) => { col.querySelectorAll('.button-container a').forEach((link) => { - if (link && link.href.startsWith('https://www.bitdefender.com.au/site/Store/buy')) { + if (link && link.href.includes('/site/Store/buy/')) { link.href = card.url; } }); diff --git a/_src/blocks/questions-answers/questions-answers.css b/_src/blocks/questions-answers/questions-answers.css new file mode 100644 index 000000000..ff528f049 --- /dev/null +++ b/_src/blocks/questions-answers/questions-answers.css @@ -0,0 +1,187 @@ +.questions-answers-wrapper { + padding: var(--body-padding); +} + +@media (min-width: 992px) { /* desktop */ + .questions-answers-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +.qa-creators.questions-answers-container h3 { + text-align: center; + font: bold 60px/69px "IBM Plex Sans", sans-serif; + margin-bottom: 32px; +} + +.questions-answers-container h4 { + text-align: center; + font: normal normal bold 32px/28px var(--body-font-family); + margin-bottom: 32px; +} + +.qa-creators.questions-answers-container h4 { + text-align: center; + font: bold 24px/26px "IBM Plex Sans", sans-serif; + margin-bottom: 32px; +} + +.questions-answers-container .default-content-wrapper p { + font: italic normal normal 14px/16px var(--body-font-family); +} + +.questions-answers .questions-answers-item { + margin: 16px 0; + padding: 16px 16px 16px 40px; + background-color: #F4F8FF; + border-radius: 10px; + border-color: rgb(229 231 235); + border-width: 0; + display: flex; + flex-direction: column; + cursor: pointer; +} + +.questions-answers .questions-answers-item.expanded { + box-shadow: 0 3px 8px 0 rgb(0 0 0 / 10%); +} + +.questions-answers-item .question { + position: relative; + font: normal normal bold 18px/21px var(--body-font-family); + color: #000; + display: flex; + justify-content: space-between; + align-items: center; + padding-right: 25px; +} + +.qa-creators .questions-answers-item .question h4 { + position: relative; + font: normal normal bold 18px/21px var(--body-font-family); + color: #000; + display: flex; + justify-content: space-between; + align-items: center; + padding: 0; + margin: 0; + text-align: left; +} + +.questions-answers-item .question::before { + position: absolute; + font: normal normal normal 24px/11px var(--body-font-family); + content: url("/_src/icons/plus-sharp-regular.svg"); + width: 14px; + height: 16px; + display: block; + left: -24px; + bottom:0; + top:3px; + margin-right: 10px; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); +} + +.questions-answers-item.expanded .question { + color: #006EFF; +} + +.questions-answers-item.expanded .question::before { + font: normal normal normal 24px/11px var(--body-font-family); + top: 3px; + content: url("/_src/icons/minus-sharp-regular.svg"); + width: 14px; + height: 16px; + display: inline-block; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); +} + +.questions-answers-item .answer { + opacity: 0; + height: 0; + overflow: hidden; + transition: all 0.3s ease-in-out; +} + +.questions-answers-item .answer p { + font: normal normal normal 14px/16px var(--body-font-family); +} + +.questions-answers-item .answer p a { + color: #006EFF; +} + +.qa-creators.questions-answers-container .default-content-wrapper p { + font: bold 24px / 26px "IBM Plex Sans", sans-serif; + margin-bottom: 32px; + text-align: center; +} + +.questions-answers-item.expanded .answer { + opacity: 1; + height: auto; + transition: all 0.3s ease-in-out; +} + +.questions-answers-item.questions-answers-item-open .answer { + display: block; +} + +.questions-answers-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + margin: 0 auto; +} + +@media (max-width: 991px) { + .questions-answers-container h4 { + font: normal normal bold 29px / 28px var(--body-font-family); + margin: 0; + } + + .qa-creators.questions-answers-container h3 { + font-size: var(--heading-font-size-l); + line-height: 1.2; + font-family: "IBM Plex Sans", sans-serif; + font-weight: 300; + } + + .qa-creators.questions-answers-container h4 { + margin-bottom: 0; + font-weight: 300; + font-family: "IBM Plex Sans", sans-serif; + } +} + +@media (min-width: 992px) { /* desktop */ + .questions-answers-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .default-content-wrapper { + max-width: var(--section-desktop-max-width); + padding: 23px var(--section-desktop-padding); + border-radius: 0; + } +} + +@media (min-width: 1200px) { + .questions-answers-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .questions-answers-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/questions-answers/questions-answers.js b/_src/blocks/questions-answers/questions-answers.js new file mode 100644 index 000000000..b930ed02a --- /dev/null +++ b/_src/blocks/questions-answers/questions-answers.js @@ -0,0 +1,71 @@ +function expandItem(item) { + const [, content] = item.children; + content.style.height = `${content.scrollHeight}px`; + const transitionEndCallback = () => { + content.removeEventListener('transitionend', transitionEndCallback); + content.style.height = 'auto'; + }; + content.addEventListener('transitionend', transitionEndCallback); + item.classList.add('expanded'); +} + +function collapseItem(item) { + const [, content] = item.children; + content.style.height = `${content.scrollHeight}px`; + requestAnimationFrame(() => { + item.classList.remove('expanded'); + content.style.height = 0; + }); +} + +function handleAccordionItemClick(item, items) { + if (!item.classList.contains('expanded')) { + items.filter((i) => i.classList.contains('expanded')).forEach((i) => collapseItem(i)); + expandItem(item); + } else { + collapseItem(item); + } +} + +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + const items = Array.from(block.querySelectorAll(':scope > div')); + items.forEach((item) => { + item.classList.add('questions-answers-item'); + const [header, content] = item.children; + header.classList.add('question'); + + if (content) { + content.classList.add('answer'); + // check if .accordion-item-content has a

    + const p = content.querySelector('p'); + // if it doesn't, add a

    and move the content inside + if (!p) { + const newP = document.createElement('p'); + newP.innerHTML = content.innerHTML; + content.innerHTML = ''; + content.appendChild(newP); + } + } + + if ([...block.classList].includes('action-only-on-header')) { + header.addEventListener('click', handleAccordionItemClick.bind(null, header.parentElement, items)); + } else { + item.addEventListener('click', handleAccordionItemClick.bind(null, item, items)); + } + }); + + if (block.classList.contains('first-open')) { + items[0].classList.add('expanded'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/quiz-hero/quiz-hero.css b/_src/blocks/quiz-hero/quiz-hero.css new file mode 100644 index 000000000..acb18cbd4 --- /dev/null +++ b/_src/blocks/quiz-hero/quiz-hero.css @@ -0,0 +1,118 @@ +.quiz-hero-container.section { + padding: 0; +} + +.quiz-hero-container .quiz-hero-wrapper .block { + display: flex; + flex-direction: column; +} + +.quiz-hero-container h1 { + font: normal normal normal 32px/40px "IBM Plex Sans", sans-serif; +} + +.quiz-hero-container h2, +.quiz-hero-container h3, +.quiz-hero-container h4 { + font: normal normal normal 20px/23px Arial, sans-serif; +} + +.quiz-hero-container p, +.quiz-hero-container div { + font: normal normal normal 14px/18px Arial, sans-serif; +} + +.quiz-hero-container .rte-wrapper { + position: relative; + z-index: 4; + background-color: #006EFF; +} + +.quiz-hero-container .img-container { + width: 100%; + min-height: 250px; + height: 60vw; + position: relative; +} + +.quiz-hero-container .default-content-wrapper { + padding-top: 20px !important; + z-index: 4; + background-color: #006EFF; + color: white; +} + +.quiz-hero-container a.button:any-link { + border: solid white 2px !important; + background-color: white; + color: #006EFF; + margin-top: 15px; +} + +@media (min-width: 768px) { + .quiz-hero-container .img-container { + height: 470px; + } +} + +@media (min-width: 992px) { + .quiz-hero-container.section { + margin-top: 40px; + } + + .quiz-hero-container h1 { + font: normal normal normal 60px/66px "IBM Plex Sans", sans-serif; + } + + .quiz-hero-container h2, + .quiz-hero-container h3, + .quiz-hero-container h4 { + font: normal normal normal 32px/37px Arial, sans-serif; + } + + .quiz-hero-container p, + .quiz-hero-container div { + font: normal normal normal 18px/25px Arial, sans-serif; + } + + .quiz-hero-container { + height: 670px; + } + + .quiz-hero-container .quiz-hero-wrapper { + height: 100%; + } + + .quiz-hero-container .quiz-hero-wrapper .block { + height: 100%; + display: flex; + flex-direction: row; + } + + .quiz-hero-container .rte-wrapper { + width: 100%; + } + + .quiz-hero-container .img-container { + width: 100%; + height: 100%; + } + + .quiz-hero-container .default-content-wrapper { + padding-top: 0 !important; + order: unset; + position: absolute; + left: 0; + right: 0; + height: 100%; + display: flex; + align-items: center; + background-color: unset; + } + + .quiz-hero-container .default-content-wrapper > div { + width: 50%; + padding-right: 30px; + } +} + diff --git a/_src/blocks/quiz-hero/quiz-hero.js b/_src/blocks/quiz-hero/quiz-hero.js new file mode 100644 index 000000000..b1a6a50ae --- /dev/null +++ b/_src/blocks/quiz-hero/quiz-hero.js @@ -0,0 +1,15 @@ +import { adobeMcAppendVisitorId } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [rte, pictureEl] = [...block.children[0].children]; + + block.innerHTML = ` +

    +
    ${pictureEl.querySelector('picture').innerHTML}
    +
    + ${rte.outerHTML} +
    + `; + + adobeMcAppendVisitorId('header'); +} diff --git a/_src/blocks/quiz-result/quiz-result.css b/_src/blocks/quiz-result/quiz-result.css new file mode 100644 index 000000000..d6c45a82e --- /dev/null +++ b/_src/blocks/quiz-result/quiz-result.css @@ -0,0 +1,81 @@ +.quiz-result-container { + h3 { + font: normal normal bold 24px/27px Arial, sans-serif; + } + + h2 { + font: normal normal bold 32px/35px rial, sans-serif; + color: #006EFF; + } + + p, div { + font: normal normal normal 16px/18px rial, sans-serif; + } + + .results-wrapper { + position: relative; + box-shadow: 0 4px 13px 4px #0000003b; + border-radius: 20px; + padding: 10px 20px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + } + + .social-wrapper { + display: flex; + align-items: center; + font: normal normal bold 16px/18px rial, sans-serif; + color: #006EFF; + margin: 30px 0; + + a { + margin-left: 20px; + } + + .icon { + width: 20px; + height: 20px; + margin: 0; + } + } +} + +@media screen { + .quiz-result-container { + .results-wrapper { + background: url('/_src/images/quiz-results-bg.jpg') no-repeat; + } + } +} + +@media (min-width: 992px) { + .quiz-result-container { + .block > :first-child { + display: flex; + justify-content: center; + } + + h3 { + font: normal normal bold 24px/27px rial, sans-serif; + } + + h2 { + font: normal normal bold 42px/42px rial, sans-serif; + } + + p, div { + font: normal normal normal 18px/21px rial, sans-serif; + } + + .results-wrapper { + min-height: 600px; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + padding: 0 15%; + } + } +} diff --git a/_src/blocks/quiz-result/quiz-result.js b/_src/blocks/quiz-result/quiz-result.js new file mode 100644 index 000000000..df69fff77 --- /dev/null +++ b/_src/blocks/quiz-result/quiz-result.js @@ -0,0 +1,33 @@ +import { getDatasetFromSection } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const dataset = getDatasetFromSection(block); + + const { socialTitlePost } = dataset; + + block.classList.add('default-content-wrapper'); + block.children[0].children[0].classList.add('results-wrapper'); + block.children[0].children[0].lastElementChild.classList.add('social-wrapper'); + + const resultPageUrl = window.location.href; + + const socialWrapperEl = block.querySelector('.social-wrapper'); + [...socialWrapperEl.querySelectorAll('a')].forEach((anchor) => { + anchor.target = '_blank'; + anchor.rel = 'noopener noreferrer'; + + if (anchor.href.includes('twitter')) { + const twitterBaseUrl = 'https://twitter.com/intent/post?'; + const twitterText = `text=${encodeURIComponent(socialTitlePost)}`; + const twitterUrl = `&url=${encodeURIComponent(resultPageUrl)}`; + const fullTwitterUrl = twitterBaseUrl + twitterText + twitterUrl; + anchor.href = fullTwitterUrl; + } + if (anchor.href.includes('facebook')) { + const facebookBaseUrl = 'https://www.facebook.com/sharer/sharer.php?'; + const facebookUrl = `u=${encodeURIComponent(resultPageUrl)}`; + const fullFacebookUrl = facebookBaseUrl + facebookUrl; + anchor.href = fullFacebookUrl; + } + }); +} diff --git a/_src/blocks/quiz-stepper/quiz-stepper.css b/_src/blocks/quiz-stepper/quiz-stepper.css new file mode 100644 index 000000000..48b6731b1 --- /dev/null +++ b/_src/blocks/quiz-stepper/quiz-stepper.css @@ -0,0 +1,196 @@ +.quiz-stepper-container { + .block { + overflow: hidden; + padding-bottom: 200px; + } + + .slide-wrapper { + display: flex; + width: 100%; + transition: transform .250s ease-in-out; + padding: 5px 0; + } + + .form-wrapper { + width: 100%; + flex-shrink: 0; + margin-right: 60px; + } + + .step { + box-shadow: 0 3px 6px #00000029; + border-radius: 16px; + padding: 25px 30px calc(235px / 2 + 30px); + position: relative; + width: 100%; + flex-shrink: 0; + + fieldset { + legend { + text-align: left; + font: normal normal bold 18px/22px Arial, sans-serif; + color: #000; + margin-bottom: 20px; + } + + .error-message { + visibility: hidden; + color: red; + font-weight: 500; + } + + &.invalid { + .error-message { + visibility: visible; + } + } + } + + .img-container { + height: 235px; + border-radius: 30px; + overflow: hidden; + position: absolute; + bottom: calc(-235px / 2); + left: 25px; + right: 25px; + } + } + + .step-header { + display: flex; + align-items: center; + margin-bottom: 20px; + } + + .step-index { + padding: 3px 10px; + background: #E4F2FF 0% 0% no-repeat padding-box; + border-radius: 20px; + } + + .step-previous { + font: normal normal normal 12px/14px Arial, sans-serif; + color: #7E7E7E; + margin-left: auto; + position: relative; + display: flex; + align-items: center; + cursor: pointer; + + &::before { + content: ''; + display: block; + width: 20px; + height: 20px; + background: url('/_src/icons/arrow-right.svg') no-repeat; + opacity: 0.5; + transform: rotate(-180deg); + } + } + + .step-radio-wrapper { + display: flex; + align-items: flex-start; + margin-bottom: 13px; + cursor: pointer; + + input[type="radio"] { + display: block; + margin: 0; + padding: 0; + background-color: #fff; + font: inherit; + width: 16px; + height: 16px; + flex-shrink: 0; + } + + label { + font: normal normal normal 16px/18px Arial, sans-serif; + margin-left: 10px; + cursor: pointer; + } + + &.selected { + label { + font-weight: 600; + } + } + } + + .button-container.submit { + display: flex; + justify-content: center; + margin-top: 50px; + + .button { + background-color: #006EFF; + color: white; + border-radius: 5px; + padding: 16px; + width: 100%; + justify-content: center; + + &::after { + background-color: white; + } + } + } +} + +@media (min-width: 768px) { + .quiz-stepper-container { + .step { + height: 630px; + + .img-container { + height: 400px; + bottom: calc(-400px / 2); + } + } + } +} + +@media (min-width: 992px) { + .quiz-stepper-container { + .block { + padding-bottom: 0; + } + + .step { + height: unset; + width: calc(100% - 250px); + padding: 40px 40% 40px 40px; + + .img-container { + width: 500px; + height: 385px; + bottom: unset; + left: unset; + top: calc(50% - 385px / 2); + right: -250px; + } + + fieldset { + legend { + font: normal normal bold 22px/27px Arial, sans-serif; + margin-bottom: 30px; + } + + label { + font: normal normal normal 18px/21px Arial, sans-serif; + } + } + } + + .button-container.submit { + justify-content: flex-start; + margin-top: 30px; + + .button { + width: 60%; + } + } + } +} diff --git a/_src/blocks/quiz-stepper/quiz-stepper.js b/_src/blocks/quiz-stepper/quiz-stepper.js new file mode 100644 index 000000000..14d9a9718 --- /dev/null +++ b/_src/blocks/quiz-stepper/quiz-stepper.js @@ -0,0 +1,146 @@ +import { getDatasetFromSection } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const dataset = getDatasetFromSection(block); + + const { + questionLabel, nextButtonLabel, previousButtonLabel, seeResultsLabel, selectErrorLabel, + } = dataset; + + const state = { + score: 0, + currentStep: 0, + }; + + block.classList.add('default-content-wrapper'); + block.closest('.section').id = 'quiz-form'; + + const steps = [...block.children]; + + function renderStep(step, index) { + const stepTitle = step.children[0].children[0].textContent; + const stepOptions = [...step.children[0].children[1].children]; + const stepImage = step.children[1].children[0]; + const isFirstStep = index === 0; + const isLastStep = index === steps.length - 1; + + const fieldId = `question-${index}`; + + return ` +
    +
    +
    +
    ${questionLabel} ${index + 1}/${steps.length}:
    + ${!isFirstStep ? `${previousButtonLabel}` : ''} +
    + + +
    + ${stepTitle} + + + ${stepOptions.map((option, idx) => { + const value = option.querySelector('u') ? 1 : 0; + const forLabel = `${fieldId}-${idx}`; + + return ` +
    + + +
    + `; + }).join('')} +
    ${selectErrorLabel}
    +
    + +

    + ${!isLastStep ? nextButtonLabel : seeResultsLabel} +

    + +
    + ${stepImage.outerHTML} +
    +
    +
    + `; + } + + function moveToNextStep() { + state.currentStep += 1; + const slideWrapper = block.querySelector('.slide-wrapper'); + const offset = 60; + + const transformValue = `translateX(calc(-100% * ${state.currentStep} - (${offset}px * ${state.currentStep})))`; + slideWrapper.style.transform = transformValue; + } + + function moveToPreviousStep() { + state.currentStep -= 1; + const slideWrapper = block.querySelector('.slide-wrapper'); + const offset = 60; + + const transformValue = `translateX(calc(-100% * ${state.currentStep} - (${offset}px * ${state.currentStep})))`; + slideWrapper.style.transform = transformValue; + } + + function renderResults() { + block.style.transform = null; + + // get score + /* eslint-disable-next-line */ + const score = [...block.querySelectorAll('input[type="radio"]:checked')].map((inputEl) => inputEl.value).reduce((sc, value) => sc += Number(value), 0); + + const legendScore = Object.keys(dataset) + .filter((item) => item.includes('result_')) + .map((item) => ({ + template: item.split('result_')[1].split('_').join('-'), + interval: [...dataset[item].split('-')], + })); + + /* eslint-disable max-len */ + const foundLegend = legendScore.find(({ interval: [min, max] }) => Number(min) <= score && score <= Number(max)); + + const { origin, pathname } = window.location; + // redirect + window.location.replace(`${origin}${pathname}${foundLegend.template}`); + } + + function validateForm(e) { + e.preventDefault(); + + const formEl = e.target.closest('form'); + const selectedOption = formEl.querySelector('input[type="radio"]:checked'); + const isLastStep = state.currentStep === steps.length - 1; + + if (!selectedOption) { + formEl.querySelector('fieldset').classList.add('invalid'); + return; + } + + if (!isLastStep) { + moveToNextStep(); + return; + } + + renderResults(); + } + + block.innerHTML = ` +
    ${steps.map((step, index) => renderStep(step, index)).join('')}
    + `; + + block.querySelectorAll('form').forEach((form) => { + const radios = form.querySelectorAll('input[type="radio"]'); + + radios.forEach((radio) => { + radio.addEventListener('change', (event) => { + if (event.target.checked) { + form.querySelector('fieldset').classList.remove('invalid'); + } + }); + }); + + form.querySelectorAll('.button-container.submit').forEach((buttonEl) => buttonEl.addEventListener('click', validateForm)); + form.querySelectorAll('.step-previous').forEach((previousEl) => previousEl.addEventListener('click', moveToPreviousStep)); + }); +} diff --git a/solutions/blocks/quote-carousel/quote-carousel.css b/_src/blocks/quote-carousel/quote-carousel.css similarity index 100% rename from solutions/blocks/quote-carousel/quote-carousel.css rename to _src/blocks/quote-carousel/quote-carousel.css diff --git a/solutions/blocks/quote-carousel/quote-carousel.js b/_src/blocks/quote-carousel/quote-carousel.js similarity index 98% rename from solutions/blocks/quote-carousel/quote-carousel.js rename to _src/blocks/quote-carousel/quote-carousel.js index 350afa44d..e6c758b96 100644 --- a/solutions/blocks/quote-carousel/quote-carousel.js +++ b/_src/blocks/quote-carousel/quote-carousel.js @@ -1,4 +1,4 @@ -import { createTag } from '../../scripts/utils.js'; +import { createTag } from '../../scripts/utils/utils.js'; import { decorateIcons } from '../../scripts/lib-franklin.js'; const SLIDE_PREFIX = 'carousel-slide-'; diff --git a/solutions/blocks/quote/quote.css b/_src/blocks/quote/quote.css similarity index 100% rename from solutions/blocks/quote/quote.css rename to _src/blocks/quote/quote.css diff --git a/solutions/blocks/quote/quote.js b/_src/blocks/quote/quote.js similarity index 96% rename from solutions/blocks/quote/quote.js rename to _src/blocks/quote/quote.js index beba25c50..fd176c411 100644 --- a/solutions/blocks/quote/quote.js +++ b/_src/blocks/quote/quote.js @@ -1,4 +1,4 @@ -import { createTag } from '../../scripts/utils.js'; +import { createTag } from '../../scripts/utils/utils.js'; import { decorateIcons } from '../../scripts/lib-franklin.js'; function createQuote(item) { diff --git a/_src/blocks/round-card/round-card.css b/_src/blocks/round-card/round-card.css new file mode 100644 index 000000000..a5806dfb9 --- /dev/null +++ b/_src/blocks/round-card/round-card.css @@ -0,0 +1,87 @@ +main .section.round-card-container.mt-n60 { + padding-top: 0; + margin-top: -60px; +} + +.round-card-container .inner-wrapper { + display: flex; + background-color: #fff; + border-radius: 8px; + box-shadow: 0 3px 6px 0 rgb(0 0 0 / 8%); + position: relative; + overflow: hidden; + z-index: 2; + width: 100%; + margin: 10px 0; + padding: 40px 23px 2pc; +} + +/* first paragraph */ +.round-card-container .inner-wrapper > div:nth-child(2) > p:nth-child(3) { + margin-top: 40px; +} + +.round-card-container .inner-wrapper > div:last-child { + border-radius: 50%; + position: absolute; + right: -35px; + top: -60px; + width: 225px; + height: 225px; + overflow: hidden; +} + +.round-card-container img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform .3s ease-in-out,-webkit-transform .3s ease-in-out; + transform: scale(1); +} + +.round-card-container .inner-wrapper > a:first-child { + position: absolute; + top: 0; + left: 0; + z-index: 2; + width: 100%; + height: 100%; + text-indent: -999999px; +} + +.round-card-container .inner-wrapper > div:nth-child(2) > * { + max-width: 150px; +} + +@media(min-width: 767px) { + /* tablet */ + .round-card-container .inner-wrapper > div:nth-child(2) { + max-width: calc(100% - 280px); + } + + .round-card-container .inner-wrapper > div:nth-child(2) > * { + max-width: unset; + } + + .round-card-container .inner-wrapper p { + font-size: 18px; + } + + .round-card-container .inner-wrapper > div:last-child { + width: 285px; + height: 285px; + } + + .round-card-container .inner-wrapper > a:first-child:hover ~ div p.button-container > a::after { + transform: translateX(5px); + opacity: 1; + } + + .round-card-container .inner-wrapper > a:first-child:hover ~ div p.button-container > a span.button-text { + transform: translate(-10px, 0); + } + + .round-card-container .inner-wrapper > a:first-child:hover ~ div img { + transform: scale(1.1); + } +} diff --git a/_src/blocks/round-card/round-card.js b/_src/blocks/round-card/round-card.js new file mode 100644 index 000000000..3a4b35a2e --- /dev/null +++ b/_src/blocks/round-card/round-card.js @@ -0,0 +1,15 @@ +export default function decorate(block) { + const innerWrapper = block.children[0]; + innerWrapper.classList = 'inner-wrapper'; + + const originalAnchorEl = innerWrapper.children[0].lastElementChild.firstElementChild; + const newAnchorEl = originalAnchorEl.cloneNode(); + newAnchorEl.classList = ''; + innerWrapper.prepend(newAnchorEl); + + const defaultWrapper = document.createElement('div'); + defaultWrapper.classList = 'default-content-wrapper'; + + defaultWrapper.append(innerWrapper); + block.prepend(defaultWrapper); +} diff --git a/_src/blocks/solutions-cards-ab/solutions-cards-ab.css b/_src/blocks/solutions-cards-ab/solutions-cards-ab.css new file mode 100644 index 000000000..fe494a7e7 --- /dev/null +++ b/_src/blocks/solutions-cards-ab/solutions-cards-ab.css @@ -0,0 +1,353 @@ +.solutions-cards-ab-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1300px; + --section-desktop-padding: 20px; + --section-large-desktop-max-width: 1332px; + --section-large-desktop-padding: 50px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); +} + +@media (min-width: 992px) { + /* desktop */ + .solutions-cards-ab-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +@media (min-width: 1600px) { + /* large desktop */ + .solutions-cards-ab-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +.solutions-cards-ab-wrapper { + background-color: #EDF9FF; + border-radius: 20px; +} + +.solutions-cards-ab-container.we-container { + margin: 0 auto; + max-width: 1292px; + padding: 0 20px; + position: relative; +} + +.solutions-cards-ab-container .icon svg { + width: 100%; + height: 100%; +} + +.solutions-cards-ab-container h2 { + font: normal normal bold 28px/32px var(--body-font-family); + text-align: center; + margin-bottom: 21px; +} + +.solutions-cards-ab-wrapper > div:first-of-type { + text-align: center; +} + +.solutions-cards-ab-wrapper > div:first-of-type h3 { + padding-top: 52px; + font: normal normal bold 40px/45px var(--body-font-family); +} + +.solutions-cards-ab-wrapper > div:first-of-type h3 strong { + color: #006DFF; +} + +.solutions-cards-ab-wrapper > div:first-of-type h3 strong em { + color: #006DFF; + font-style: normal; +} + +.solutions-cards-ab-wrapper > div:first-of-type p { + font: normal normal normal 18px/21px var(--body-font-family); +} + +.solutions-cards-ab-wrapper > div:last-of-type { + text-align: center; + padding: 40px 0 57px; +} + +.solutions-cards-ab-wrapper > div:last-of-type p { + font: normal normal normal 12px/14px var(--body-font-family); +} + +.solutions-cards-ab-wrapper > div:last-of-type p .icon { + width: 14px; + height: 14px; + position: relative; + margin-right: 9px; + margin-bottom: 0; + top: 3px; + fill: #1C7928; + display: inline-block; +} + +.solutions-cards-ab-wrapper > div:last-of-type p a { + color: var(--text-color); + text-decoration: underline; +} + +.solutions-cards-ab-wrapper > div:last-of-type p a:hover { + color: var(--text-color); + text-decoration: none; +} + +.solutions-cards-ab.block { + display: grid; + justify-content: center; + align-items: center; + grid-template-columns: repeat(auto-fill, minmax(300px, 410px)); + grid-gap: 28px; + padding: 0 5px; +} + +.solutions-cards-ab.block > div { + padding: 28px; + background-color: white; + box-shadow: 0 3px 6px #00000029; + border: 3px solid #006DFF; + border-radius: 20px; +} + +.solutions-cards-ab.block .description { + position: relative; +} + +.solutions-cards-ab.block .description .icon { + width: 57px; + height: 37px; + position: absolute; + top: -48px; + right: 0; + fill: #006DFF; +} + +.solutions-cards-ab.block .product-info h2 { + font: normal normal bold 22px/24px var(--body-font-family); + margin-bottom: 14px; +} + +.solutions-cards-ab.block .product-info .protect { + font: normal normal normal 16px/32px var(--body-font-family); + border-bottom: 1px solid #D1D1D1; + padding-bottom: 14px; + margin-bottom: 14px; +} + +.solutions-cards-ab.block .product-info .description { + font: normal normal normal 12px/14px var(--body-font-family); +} + +.solutions-cards-ab.block .product-info .description strong { + color: #1D7928; + font-weight: bold; +} + +.solutions-cards-ab.block .product-info .buynow a { + font: normal normal bold 16px/20px var(--body-font-family); + margin-top: 24px; + padding: 14px 28px; + color: #fff; + background: #E72325; + + /* border: 2px solid #006EFF; */ + border-radius: 10px; + display: block; + position: relative; + min-width: 180px; + text-align: center; + text-decoration: none; +} + +.solutions-cards-ab.block .product-info .learnmore a { + font: normal normal bold 16px/20px var(--body-font-family); + margin-top: 8px; + padding: 14px 28px; + color: #000; + background: #fff; + border: 2px solid #000; + border-radius: 10px; + display: block; + position: relative; + min-width: 180px; + text-align: center; + text-decoration: none; +} + +.solutions-cards-ab.block .product-info .buynow a:focus { + outline: 2px solid #48C1FF; + border-radius: 13px; + outline-offset: 2px; +} + +.solutions-cards-ab.block .product-info .buynow a:hover { + padding: 14px 28px; + background: #B10304; + color: #fff; +} + +.solutions-cards-ab.block .product-info .learnmore a:focus { + outline: 2px solid #48C1FF; + border-radius: 13px; + outline-offset: 2px; +} + +.solutions-cards-ab.block .product-info .learnmore a:hover { + padding: 14px 28px; + background: #000; + color: #fff; +} + +.solutions-cards-ab.block .product-info .feature-list { + border-bottom: 1px solid #D1D1D1; + padding-bottom: 14px; + margin-bottom: 14px; +} + +.solutions-cards-ab.block .product-info .feature-list ul { + list-style: none; + margin: 0; + padding: 0; + display: inline-block; +} + +.solutions-cards-ab.block .product-info .feature-list ul li { + font: normal normal normal 14px/32px var(--body-font-family); + margin: 0; + padding: 0; +} + +.solutions-cards-ab.block .product-info .feature-list ul li .icon { + width: 16px; + height: 16px; + position: relative; + margin-right: 9px; + margin-bottom: 0; + top: 3px; + display: inline-block; +} + +.solutions-cards-ab.block .product-info .feature-list ul li .icon.icon-x-circle svg { + fill: #999; +} + +.solutions-cards-ab.block .product-info .feature-list ul li del { + color: #999; +} + +.solutions-cards-ab.block .price-area { + margin-bottom: 8px; +} + +.solutions-cards-ab.block .price-area .tab-panel .prod-oldprice { + text-align: left; + text-decoration: line-through; + font: normal normal normal 16px/18px var(--body-font-family); +} + +.solutions-cards-ab.block .price-area .tab-panel .prod-save { + text-align: left; + font: normal normal bold 12px/14px var(--body-font-family); + padding: 3px 9px; + background: #1C7928 0% 0% no-repeat padding-box; + border-radius: 22px; + color: #fff; +} + +.solutions-cards-ab.block .price-area .tab-panel .prod-newprice { + text-align: left; + font: normal normal bold 40px/45px var(--body-font-family); + color: #006DFF; +} + +@media (max-width: 1600px) { + .solutions-cards-ab-container.we-container { + max-width:1200px; + padding: 0 50px; + } +} + +@media (max-width: 992px) { + .solutions-cards-ab-container.we-container { + padding:0 20px; + } +} + +@media (max-width: 370px) { + .solutions-cards-ab.block > div { + padding: 14px; + } + + .solutions-cards-ab.block { + grid-template-columns: 1fr; + } +} + diff --git a/_src/blocks/solutions-cards-ab/solutions-cards-ab.js b/_src/blocks/solutions-cards-ab/solutions-cards-ab.js new file mode 100644 index 000000000..3d39fc51e --- /dev/null +++ b/_src/blocks/solutions-cards-ab/solutions-cards-ab.js @@ -0,0 +1,168 @@ +/* eslint-disable prefer-const */ +/* eslint-disable no-undef */ +/* eslint-disable max-len */ +let adobeDataLayerArray = []; +export default async function decorate(block, options) { + const { + // eslint-disable-next-line no-unused-vars + pid, offtext, firstyear, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + let blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const firstRow = block.firstElementChild; + const lastRow = block.lastElementChild; + /* eslint-disable-next-line prefer-destructuring */ + const parentNode = block.parentNode; // Get the parent of the block + if (firstRow && parentNode) { + parentNode.insertBefore(firstRow, block); // Insert the first row before the block + } + if (lastRow && parentNode) { + parentNode.appendChild(lastRow); // Insert the last row after the block + } + const productCardsElement = parentNode.querySelector('.solutions-cards-ab.block'); // Get the container element + const tables = productCardsElement.querySelectorAll('table'); // Find all tables within the container + + let globalDiscountPercentage = 0; + + /* eslint-disable no-restricted-syntax */ + for (const table of tables) { + // Create a new div to replace the table + const productInfoDiv = document.createElement('div'); + productInfoDiv.classList.add('product-info'); + + // Process and replace table content: + const tableBody = table.querySelector('tbody'); // Get the table body + + // Handle remaining content (code, discount, buttons) + const heading = tableBody.querySelector('tr:first-child td').innerHTML; + const protect = tableBody.querySelector('tr:nth-child(2) td').innerHTML; + const productArea = tableBody.querySelector('tr:nth-child(3) td').innerHTML; + const code = tableBody.querySelector('tr:nth-child(4) td').innerHTML; + const buyNowButton = tableBody.querySelector('tr:nth-child(5) td').innerText; + const featureList = tableBody.querySelector('tr:nth-child(6) td').innerHTML; + const learnMoreButton = tableBody.querySelector('tr:nth-child(7) td').innerHTML; + + productInfoDiv.innerHTML = ` +

    ${heading}

    +
    ${protect}
    +
    ${productArea}
    +
    ${featureList}
    +
    +
    ${code}
    + +
    ${learnMoreButton}
    + `; + + // Replace the table with the new div structure + table.parentNode.replaceChild(productInfoDiv, table); + + const productsAsList = productArea.split(','); + const tabContent = productInfoDiv.querySelector('.price-area'); + + // eslint-disable-next-line no-loop-func, no-await-in-loop + await Promise.all(productsAsList.map(async (prod) => { + const [prodName, prodUsers, prodYears] = prod.split('/'); + const { fetchProduct } = await import('../../scripts/utils/utils.js'); + + let oldPrice; + let newPrice; + let discountPercentage; + + // build pid for link + let pidLink = ''; + if (pid.length) { + pidLink = `pid.${pid}`; + } + + const tab = document.createElement('div'); + tab.classList.add('tab-panel'); + tab.setAttribute('id', `${prodName}`); + + const product = await fetchProduct(prodName, `${prodUsers}u-${prodYears}y`, pid); + discountPercentage = Math.round( + (1 - (product.discount.discounted_price) / product.price) * 100, + ); + oldPrice = product.price; + newPrice = product.discount.discounted_price; + let currencyLabel = product.currency_label; + tab.innerHTML = ` +
    + ${currencyLabel}${oldPrice} + ${discountPercentage}% ${offtext} +
    +
    + ${currencyLabel}${newPrice}/ ${firstyear} +
    `; + tabContent.appendChild(tab); + + // add discount value to component title + if (discountPercentage > globalDiscountPercentage) { + globalDiscountPercentage = discountPercentage; + } + + // replace href with correct buy link + const buybutton = productInfoDiv.querySelector('.buy-button'); + buybutton.href = `/site/Store/buy/${prodName}/${prodUsers}/${prodYears}/${pidLink}`; + + if (options) { + const storeProduct = await options.store.getProducts([new ProductInfo(prodName, 'consumer')]); + const storeOption = storeProduct[prodName].getOption(prodUsers, prodYears); + if (!storeOption.getName().includes('Monthly')) { + adobeDataLayerArray.push({ + info: { + ID: storeOption.getAvangateId(), + name: storeOption.getName(), + devices: storeOption.getDevices(), + subscription: storeOption.getSubscription('months'), + version: storeOption.getSubscription('months') === 1 ? 'monthly' : 'yearly', + basePrice: storeOption.getPrice('value'), + discountValue: storeOption.getDiscount('value'), + discountRate: storeOption.getDiscount('percentage'), + currency: storeOption.getCurrency(), + priceWithTax: storeOption.getDiscountedPrice('value') || storeOption.getPrice('value'), + }, + }); + } + } + })); + } + + const elementsToRemove = block.querySelectorAll('.product_area'); + elementsToRemove.forEach((element) => { + element.remove(); + }); + + if (options) { + window.addEventListener('codeBaseFinishedRunning', () => { + const allProducts = window.adobeDataLayer.find((productEvent) => productEvent.event === 'product all'); + if (allProducts) { + const allProductsJson = JSON.parse(JSON.stringify(allProducts)); + allProductsJson.all = allProductsJson.all.filter((product) => product.info.name !== 'Bitdefender Premium Security' && product.info.name !== 'Bitdefender Premium Security Plus'); + allProductsJson.all = allProductsJson.all.concat(adobeDataLayerArray); + + window.adobeDataLayer.push({ + all: null, + }); + + window.adobeDataLayer.push(allProductsJson); + } + }); + } + + const discountXX = parentNode.querySelector('.solutions-cards-ab-wrapper h3 strong em'); + const xx = document.createElement('em'); + xx.innerHTML = `${globalDiscountPercentage}%`; + discountXX.replaceWith(xx); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/spurs-hero/spurs-hero.css b/_src/blocks/spurs-hero/spurs-hero.css new file mode 100644 index 000000000..a0ab1b792 --- /dev/null +++ b/_src/blocks/spurs-hero/spurs-hero.css @@ -0,0 +1,181 @@ +.spurs-hero-container.section { + padding: 0; +} + +.spurs-hero-container .spurs-hero-wrapper .block { + display: flex; + flex-direction: column; +} + +.spurs-hero-container h1 { + font-size: 24px; + font-weight: 600; + line-height: 1.25; +} + +.spurs-hero-container.hero-ferrari h1 { + font-size: 29px; + line-height: 1.2; + font-weight: normal; +} + +.spurs-hero-container.hero-ferrari h2 { + font-size: 18px; + font-weight: normal; +} + +.spurs-hero-container p, +.spurs-hero-container div { + font-size: 16px; + font-weight: 500; + line-height: 1.6; +} + +.spurs-hero-container .rte-wrapper { + position: relative; + z-index: 4; + background-color: #006EFF; +} + +.spurs-hero-container .img-container { + display: none; + width: 100%; + height: 200px; + position: relative; +} + +.hero-ferrari .img-container { + display: block; + width: 100%; + height: 48vw; +} + +.spurs-hero-container .default-content-wrapper { + padding-top: 20px !important; + z-index: 4; + background-color: #006EFF; + color: white; +} + +.spurs-hero-container a.button:any-link { + border: solid white 2px !important; + background-color: white; + color: #006EFF; + margin-top: 15px; +} + +.spurs-hero-container .default-content-wrapper p.button-container a { + border: solid white 2px !important; + background-color: transparent; + color: white; + margin-top: 15px; +} + +.spurs-hero-container .default-content-wrapper p:not(.button-container):nth-last-child(2) { + position: relative; + margin-top: 80px; +} + +.spurs-hero-container .default-content-wrapper p:not(.button-container) img { + width: 90px; + position: absolute; + top: -45px; + left: 5px; +} + +.spurs-hero-container .default-content-wrapper p:not(.button-container) a { + background: white; + padding: 10px 16px 10px 100px; + font-size: 14px; + color: #006DFF; + font-weight: 600; + text-transform: none; + display: inline-block; + text-align: center; + border-radius: 8px; + transition: background-color 0.2s; + width: auto; + border-style: none; + cursor: pointer; +} + +@media (min-width: 992px) { + .spurs-hero-container h1 { + font-size: 40px; + font-weight: 300; + line-height: 1; + } + + .spurs-hero-container.hero-ferrari h1 { + font-size: 48px; + font-weight: 300; + line-height: 57px; + } + + .spurs-hero-container.hero-ferrari h2 { + font-size: 32px; + font-weight: 300; + } + + .spurs-hero-container p, + .spurs-hero-container div { + /* font: normal normal normal 18px/25px Arial; */ + font-size: 28px; + font-weight: 300; + line-height: 1.3; + } + + .spurs-hero-container { + height: 600px; + } + + .spurs-hero-container .spurs-hero-wrapper { + height: 100%; + } + + .spurs-hero-container .spurs-hero-wrapper .block { + height: 100%; + display: flex; + flex-direction: row; + } + + .spurs-hero-container .rte-wrapper { + width: 100%; + } + + .spurs-hero-container .default-content-wrapper { + padding-top: 0 !important; + order: unset; + position: absolute; + left: 0; + right: 0; + height: 100%; + display: flex; + align-items: center; + background-color: unset; + } + + .spurs-hero-container .default-content-wrapper > div { + width: 50%; + padding-top: 65px; + } + + .spurs-hero-container .img-container { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: #006EFF; + } + + .spurs-hero-container.hero-ferrari .img-container { + align-items: normal; + justify-content: left; + } + + .spurs-hero-container .img-container picture { + width: 90%; + } +} + diff --git a/_src/blocks/spurs-hero/spurs-hero.js b/_src/blocks/spurs-hero/spurs-hero.js new file mode 100644 index 000000000..cbbde9eee --- /dev/null +++ b/_src/blocks/spurs-hero/spurs-hero.js @@ -0,0 +1,24 @@ +import { adobeMcAppendVisitorId } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [rte, pictureEl] = [...block.children[0].children]; + + if (window.location.href.indexOf('scuderiaferrari') !== -1) { + block.closest('.section').classList.add('hero-ferrari'); + } + + block.innerHTML = ` +
    +
    ${pictureEl.querySelector('picture').outerHTML}
    +
    + ${rte.outerHTML} +
    + `; + + block.querySelectorAll('.button-container > a').forEach((anchorEl) => { + anchorEl.target = '_blank'; + anchorEl.rel = 'noopener noreferrer'; + }); + + adobeMcAppendVisitorId('header'); +} diff --git a/solutions/blocks/sticky-navigation/sticky-navigation.css b/_src/blocks/sticky-navigation/sticky-navigation.css similarity index 100% rename from solutions/blocks/sticky-navigation/sticky-navigation.css rename to _src/blocks/sticky-navigation/sticky-navigation.css diff --git a/solutions/blocks/sticky-navigation/sticky-navigation.js b/_src/blocks/sticky-navigation/sticky-navigation.js similarity index 100% rename from solutions/blocks/sticky-navigation/sticky-navigation.js rename to _src/blocks/sticky-navigation/sticky-navigation.js diff --git a/_src/blocks/system-requirements/system-requirements.css b/_src/blocks/system-requirements/system-requirements.css new file mode 100644 index 000000000..792e1831f --- /dev/null +++ b/_src/blocks/system-requirements/system-requirements.css @@ -0,0 +1,257 @@ +.system-requirements-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1290px; + --section-desktop-padding: 20px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); + + background-color: #f2f2f2; +} + +.system-requirements-wrapper { + padding: var(--body-padding); +} + +.default-content-wrapper { + width: 100%; + margin: 0 auto; + max-width: var(--body-max-width); + padding: var(--body-padding); + position: relative; +} + +.system-requirements-container h6 { + text-align: left; + font: normal normal bold 16px/18px var(--body-font-family); + margin: 0; +} + + +/* remove padding from userguide wrapper */ +.system-requirements-container :last-child { + padding-bottom: 1px; +} + +.system-requirements-container-userguides { + background-color: #f2f2f2; +} + +.system-requirements-container .default-content-wrapper p { + font: normal normal normal 12px/14px var(--body-font-family); +} + +.system-requirements-container .system-requirements-item { + padding: 8px 16px 8px 24px; + display: flex; + flex-direction: column; + cursor: pointer; +} + +.system-requirements-item .system { + position: relative; + font: normal normal bold 12px/14px var(--body-font-family); + color: #006EFF; + display: flex; + justify-content: space-between; + align-items: center; + padding-right: 25px; +} + +.system-requirements-item .system::before { + position: absolute; + font: normal normal normal 24px/11px var(--body-font-family); + content: url("/_src/icons/plus-sharp-regular.svg"); + width: 14px; + height: 16px; + display: block; + left: -24px; + bottom:0; + top:-1px; + margin-right: 10px; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); +} + +.system-requirements-item.expanded .system { + color: #006EFF; +} + +.system-requirements-item.expanded .system::before { + font: normal normal normal 24px/11px var(--body-font-family); + top: -1px; + content: url("/_src/icons/minus-sharp-regular.svg"); + width: 14px; + height: 16px; + display: inline-block; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); +} + +.system-requirements-item .requirement { + opacity: 0; + height: 0; + overflow: hidden; + transition: all 0.3s ease-in-out; +} + +.system-requirements-item .requirement > ul { + list-style: none; + margin: 0; + padding: 0; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + grid-gap: 24px; +} + +.system-requirements-item .requirement > ul > li { + font: normal normal normal 12px/14px var(--body-font-family); + list-style: none; + display: inline-block; + padding-left: 0; +} + +.system-requirements-item .requirement > ul > li > br { + display: block; + margin-bottom: 14px; + content: " "; +} + +.system-requirements-item .requirement > ul > li > br:first-of-type { + margin: 0; +} + +.system-requirements-item.expanded .requirement { + opacity: 1; + height: auto; + transition: all 0.3s ease-in-out; +} + +.system-requirements-item.system-requirements-open .requirement { + display: block; +} + +.system-requirements-container .default-content-wrapper p a { + font: normal normal normal 12px/14px var(--body-font-family); + padding: 0 30px 0 0; + color: #006EFF; + border: 0; + display: inline-block; + position: relative; +} + +.system-requirements-container .default-content-wrapper p a::before { + content: url("/_src/icons/book-sharp-regular.svg"); + margin-right: 10px; + width: 14px; + height: 16px; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); + display: inline-block; + position: relative; + top: 3px; +} + +.system-requirements-container .default-content-wrapper p a:hover { + color: #006EFF; + text-decoration: underline; +} + +.system-requirements-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + margin: 0 auto; +} + +@media (min-width: 992px) { /* desktop */ + .system-requirements-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } + + .system-requirements-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .default-content-wrapper { + max-width: var(--section-desktop-max-width); + padding: 23px var(--section-desktop-padding); + border-radius: 0; + } +} + +@media (min-width: 1200px) { + .system-requirements-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .system-requirements-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/system-requirements/system-requirements.js b/_src/blocks/system-requirements/system-requirements.js new file mode 100644 index 000000000..48b7ad480 --- /dev/null +++ b/_src/blocks/system-requirements/system-requirements.js @@ -0,0 +1,72 @@ +function expandItem(item) { + const [, content] = item.children; + content.style.height = `${content.scrollHeight}px`; + const transitionEndCallback = () => { + content.removeEventListener('transitionend', transitionEndCallback); + content.style.height = 'auto'; + }; + content.addEventListener('transitionend', transitionEndCallback); + item.classList.add('expanded'); +} + +function collapseItem(item) { + const [, content] = item.children; + content.style.height = `${content.scrollHeight}px`; + requestAnimationFrame(() => { + item.classList.remove('expanded'); + content.style.height = 0; + }); +} + +function handleAccordionItemClick(item, items) { + if (!item.classList.contains('expanded')) { + items.filter((i) => i.classList.contains('expanded')).forEach((i) => collapseItem(i)); + expandItem(item); + } else { + collapseItem(item); + } +} + +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + // const blockParent = block.closest('.section'); + // blockParent.classList.add('we-container'); + } + + const items = Array.from(block.querySelectorAll(':scope > div')); + items.forEach((item) => { + item.classList.add('system-requirements-item'); + const [header, content] = item.children; + header.classList.add('system'); + + if (content) { + content.classList.add('requirement'); + // check if .accordion-item-content has a

    + // const p = content.querySelector('ul li p'); + // // if it doesn't, add a

    and move the content inside + // if (!p) { + // const newP = document.createElement('p'); + // newP.innerHTML = content.querySelector('ul li').innerHTML; + // content.querySelector('ul li').innerHTML = ''; + // content.querySelector('ul li').appendChild(newP); + // } + } + + if ([...block.classList].includes('action-only-on-header')) { + header.addEventListener('click', handleAccordionItemClick.bind(null, header.parentElement, items)); + } else { + item.addEventListener('click', handleAccordionItemClick.bind(null, item, items)); + } + }); + + if (block.classList.contains('first-open')) { + items[0].classList.add('expanded'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/tabs-component/tabs-component.css b/_src/blocks/tabs-component/tabs-component.css new file mode 100644 index 000000000..1363f7209 --- /dev/null +++ b/_src/blocks/tabs-component/tabs-component.css @@ -0,0 +1,248 @@ +.tabs-component-container .tabs-component { + display: flex; + flex-direction: column; + align-items: center; + margin-top: 48px; +} + +.tabs-component-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.tabs-component-container .icon svg { + width: 12px; + height: 14px; + padding-right: 2px; + fill: #fff; +} + +.tabs-component-container h3 { + font: normal normal bold 24px/28px Arial, sans-serif; +} + +.tabs-component-container p { + font: normal normal normal 16px/24px Arial, sans-serif; +} + +.tabs-component-container span { + font: normal normal bold 16px/18px Arial, sans-serif; +} + +.tabs-component-container .title-class div { + max-width: 630px; + text-align: center; + margin-bottom: 27px; + font: normal normal bold 32px/37px Arial, sans-serif; +} + +.tabs-component-container .subtitle-class div { + max-width: 630px; + text-align: center; + margin-bottom: 67px; + font: normal normal normal 18px/26px Arial, sans-serif; +} + +.tabs-component-container .tabs-container { + display: flex; + justify-content: center; + margin-bottom: 40px; + flex-wrap: wrap; + border-bottom: 1px solid #E4F2FF; +} + +.tabs-component-container .card-container { + display: flex; + flex-direction: column-reverse; + align-items: center; + gap: 3%; +} + +.tabs-component-container .hide { + display: none; +} + +.tabs-component-container .tabs-container button { + background-color: white; + color: black; + border: 0; + font: normal normal bold 18px/21px Arial, sans-serif; + padding: 9px; + display: flex; + gap: 10px; + align-items: center; + position: relative; + cursor: pointer; +} + +.tabs-component-container a { + color: #006dff !important; + background-color: #fff !important; + border: 0 !important; +} + +.tabs-component-container a::after { + opacity: 1; + margin-left: 0; +} + +.tabs-component-container .tabs-container button a { + background-color: white; + border: 0; + font: normal normal bold 18px/21px Arial, sans-serif; + padding: 9px; + margin-bottom: 10px; + display: flex; + gap: 10px; + align-items: center; +} + +/* stylelint-disable-next-line no-descending-specificity */ +.tabs-component-container .card-container a { + overflow: visible; + padding-left: 0 !important; +} + +.tabs-component-container .card-container a .button-text { + transform: unset; +} + +.tabs-component-container .card-container a:hover { + color: #0A53C5; +} + +.tabs-component-container .card-container a::after { + content: '\2192'; + width: 24px; + height: 24px; + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + margin-left: 2px; + margin-bottom:2px; + mask: none !important; +} + +.tabs-component-container .card-container a:hover::after { + transform: translateX(5px); +} + +.tabs-component-container .tabs-container button::after { + background: #006eff; + border-radius: 0; + content: ""; + height: 4px; + position: absolute; + left: 0; + bottom: 0; + width: 0; + z-index: 1; +} + +.tabs-component-container .tabs-container button.selected::after { + transition: all 1s ease; + width: 100%; +} + +.tabs-component-container .left { + width: 80%; +} + +.tabs-component-container .left img { + border-radius: 20px; + width: auto; + max-width: 100%; + height: auto; +} + +.tabs-component-container .right { + width: 80%; + display: flex; + flex-direction: column; + justify-content: center; +} + +.tabs-component-container .right p { + font-size: 16px; +} + +.tabs-component-container .tabs-container button picture img { + width: 50px; + height: auto; +} + +.tabs-component-container button strong { + display: none; +} + +.tabs-component-container .tabs-container picture { + display: flex; + align-items: center; +} + +.tabs-component-container { + align-items: normal !important; +} + +@media (min-width: 768px) { + .tabs-component-container .tabs-container { + flex-wrap: nowrap; + } + + .tabs-component-container .left { + width: 60%; + } + + .tabs-component-container .right { + width: 60%; + } +} + +@media (min-width: 992px) { + .tabs-component-container .card-container { + flex-direction: row; + width: 830px; + } + + .tabs-component-container button strong { + display: block; + } + + .tabs-component-container .tabs-container button picture img { + width: 30px; + } + + .tabs-component-container .left { + width: 50%; + } + + .tabs-component-container .right { + width: 50%; + } + + .tabs-component-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .tabs-component-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .tabs-component-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/tabs-component/tabs-component.js b/_src/blocks/tabs-component/tabs-component.js new file mode 100644 index 000000000..b9ebc69f7 --- /dev/null +++ b/_src/blocks/tabs-component/tabs-component.js @@ -0,0 +1,83 @@ +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const parentSelector = block.closest('.section'); + // eslint-disable-next-line no-unused-vars + const metaData = parentSelector.dataset; + const [title, subtitle, tabsTitle, ...sections] = block.children; + + title.classList.add('title-class'); + subtitle.classList.add('subtitle-class'); + // Add class 'tabs-container' to the first div + tabsTitle.classList.add('tabs-container'); + + // Get the container for the buttons + const container = block.querySelector('.tabs-container'); + + // Check if the container exists + if (container) { + const divs = container.querySelectorAll('div'); + + // Loop through each div to create buttons + divs.forEach((div, index) => { + const button = document.createElement('button'); + if (index === 0) button.classList.add('selected'); + button.innerHTML = div.innerHTML; // Use innerHTML instead of textContent + button.addEventListener('click', () => { + // Remove 'selected' class from all buttons + const buttons = block.querySelectorAll('.tabs-container button'); + buttons.forEach((btn) => btn.classList.remove('selected')); + + // Add 'selected' class to the clicked button + button.classList.add('selected'); + + // Hide all card-container elements + const cardContainers = block.querySelectorAll('.card-container'); + cardContainers.forEach((card) => card.classList.add('hide')); + + // Show the corresponding card-container element based on the index + sections[index].classList.remove('hide'); + }); + + div.parentNode.replaceChild(button, div); + }); + } else { + // eslint-disable-next-line no-console + console.error('Container not found'); + } + + // click on the next element every 5 seconds + // setInterval(() => { + // const buttons = block.querySelectorAll('.tabs-container button'); + // const selectedButton = block.querySelector('.tabs-container button.selected'); + // const buttonIndex = Array.from(buttons).indexOf(selectedButton); + // const nextIndex = (buttonIndex + 1) % buttons.length; + // buttons[nextIndex].click(); + // }, 6000); + + // Add classes to each card-container and hide all but the first one + sections.forEach((element, index) => { + element.classList.add('card-container'); + if (index === 0) { + element.classList.add('show'); + } + if (index !== 0) { + element.classList.add('hide'); + } + + // Add classes to children divs + const photoDiv = element.querySelector('div:nth-child(1)'); + const textDiv = element.querySelector('div:nth-child(2)'); + photoDiv.classList.add('left'); + textDiv.classList.add('right'); + }); + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/solutions/blocks/tabs/tabs.css b/_src/blocks/tabs/tabs.css similarity index 100% rename from solutions/blocks/tabs/tabs.css rename to _src/blocks/tabs/tabs.css diff --git a/solutions/blocks/tabs/tabs.js b/_src/blocks/tabs/tabs.js similarity index 100% rename from solutions/blocks/tabs/tabs.js rename to _src/blocks/tabs/tabs.js diff --git a/_src/blocks/teaser-logos/teaser-logos.css b/_src/blocks/teaser-logos/teaser-logos.css new file mode 100644 index 000000000..a64d8f203 --- /dev/null +++ b/_src/blocks/teaser-logos/teaser-logos.css @@ -0,0 +1,89 @@ +/* stylelint-disable custom-property-pattern */ +.teaser-logos-container.section { + padding: 0; + background: #EFF6FF; +} + +.teaser-logos-container .main-wrapper { + display: flex; + height: 160px; +} + +.teaser-logos-container .default-content-wrapper { + display: flex; + padding-top: 0 !important; + height: 200px; +} + +.teaser-logos-container .main-wrapper .col, +.teaser-logos-container .default-content-wrapper .col { + display: flex; + justify-content: center; + position: relative; + width: 50%; +} + +.teaser-logos-container .main-wrapper .col { + background: #EFF6FF; +} + +.teaser-logos-container .main-wrapper .col:first-child::before { + content: ''; + display: block; + width: 0; + height: 0; + border-left: 50px solid transparent; + border-right: 50px solid transparent; + border-bottom: 170px solid var(--backgroundColor); + transform: rotate(180deg); + position: absolute; + right: -20px; + top: 0; + z-index: 2; +} + +.teaser-logos-container .main-wrapper .col:last-child::before { + content: ''; + display: block; + width: 0; + height: 0; + border-left: 50px solid transparent; + border-right: 50px solid transparent; + border-bottom: 170px solid var(--backgroundColor); + transform: rotate(0deg); + position: absolute; + left: -37.5px; + top: 0; + z-index: 1; +} + +.teaser-logos-container .default-content-wrapper .col .img-wrapper { + padding-top: 30px; + position: relative; + z-index: 3; + width: 100%; +} + +.teaser-logos-container .default-content-wrapper .col .img-wrapper img { + object-fit: cover; + width: 100%; +} + +@media screen and (min-width: 768px) { + .teaser-logos-container .main-wrapper { + height: 400px; + } + + .teaser-logos-container .main-wrapper .col:first-child::before, + .teaser-logos-container .main-wrapper .col:last-child::before { + border-bottom-width: 400px; + } + + .teaser-logos-container .default-content-wrapper .col .img-wrapper { + width: 50%; + height: 180px; + display: flex; + align-items: center; + } +} + diff --git a/_src/blocks/teaser-logos/teaser-logos.js b/_src/blocks/teaser-logos/teaser-logos.js new file mode 100644 index 000000000..3b78433f3 --- /dev/null +++ b/_src/blocks/teaser-logos/teaser-logos.js @@ -0,0 +1,11 @@ +export default async function decorate(block) { + const boxes = [...block.children[0].children]; + + block.innerHTML = ` +

    + ${boxes.map((box) => ` +
    ${box.innerHTML}
    + `).join('')} +
    + `; +} diff --git a/_src/blocks/terms/terms.css b/_src/blocks/terms/terms.css new file mode 100644 index 000000000..a12b4c276 --- /dev/null +++ b/_src/blocks/terms/terms.css @@ -0,0 +1,145 @@ +.terms-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1290px; + --section-desktop-padding: 20px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); + + background-color: #f2f2f2; +} + +@media (min-width: 992px) { /* desktop */ + .terms-wrapper { + max-width: var(--section-desktop-max-width); + padding: 15px var(--section-desktop-padding) 40px var(--section-desktop-padding); + margin: 0 auto; + } +} + +.terms-container h5 { + font-size: 16px; + font-weight: bold; + margin: 0; +} + +.terms-container h6 { + font-size: 16px; + font-weight: bold; + margin: 0; +} + +.terms-container .terms div, +.terms-container .terms div p { + font-size: 12px; +} + +.terms-container .terms div p strong { + font-weight: bold; + margin-top: 15px; +} + +.terms-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + margin: 0 auto; +} + +.terms.border-on-top { + border-top: 1px solid #dedede; + padding-top: 20px; +} + +@media (max-width: 992px) { /* mobile/tablet */ + .terms-wrapper { + padding: var(--body-padding); + } + + .terms-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .default-content-wrapper { + max-width: var(--section-desktop-max-width); + padding: 23px var(--section-desktop-padding); + border-radius: 0; + } +} + +@media (min-width: 1200px) { + .terms-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .terms-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/terms/terms.js b/_src/blocks/terms/terms.js new file mode 100644 index 000000000..fe60b0391 --- /dev/null +++ b/_src/blocks/terms/terms.js @@ -0,0 +1,15 @@ +export default async function decorate(block, options) { + block.closest('.section').id = 'tos'; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.terms-wrapper'); + blockParent.classList.add('we-container'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/testimonials-component/testimonials-component.css b/_src/blocks/testimonials-component/testimonials-component.css new file mode 100644 index 000000000..8f18b135c --- /dev/null +++ b/_src/blocks/testimonials-component/testimonials-component.css @@ -0,0 +1,172 @@ +.testimonials-component-container { + display: flex; + flex-direction: column; + align-items: center; + font: italic normal normal 14px/19px Arial, sans-serif; +} + +.testimonials-component-container h2 { + font: normal normal bold 32px/37px Arial, sans-serif; +} + +.testimonials-component-container .testimonials-component { + display: flex; + flex-direction: column; + align-items: center; + gap: 3%; +} + +.testimonials-component-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin: 15px auto; +} + +.testimonials-component-container .title-class { + text-align: center; + font: normal normal bold 32px/37px Arial, sans-serif; +} + +.testimonials-component-container .subtitle-class { + font: normal normal normal 18px/21px Arial, sans-serif; + margin-bottom: 40px; + text-align: center; + max-width: 90%; +} + +.testimonials-component-container .review-container { + display: flex; + align-items: flex-start; + flex: 1; + gap: 2%; + background: #edf9ff; + padding: 26px 23px; + border-radius: 16px; +} + +.testimonials-component-container.grey-bck .review-container { + background-color: #F6F6F6;; +} + +.testimonials-component-container hr { + margin-left: 0; + width: 24px; + margin-bottom: 8px; + border: 1px solid #00439c; +} + +.testimonials-component-container .review { + width: 90%; +} + +.testimonials-component-container .review p { + width: 90%; + margin-top: 0; +} + +.testimonials-component-container .review p:last-child { + font-style: normal; +} + +.testimonials-component-container.grey-bck .review p { + font-size: 14px; + font-style: normal; +} + +.testimonials-component-container .hide { + display: none; +} + +.testimonials-component-container .show { + display: flex; +} + +.testimonials-component-container .navigation-container { + display: flex; + justify-content: space-between; + gap: 3%; + max-width: 90%; + width: 100%; + margin-top: 20px; + align-items: center; +} + +.testimonials-component-container .buttons-container { + display: flex; + gap: 3%; +} + +.testimonials-component-container .next-button, +.testimonials-component-container .prev-button { + width: 45px; + height: 45px; + border: 0; + background-color: #edf9ff; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; +} + +.testimonials-component-container .prev-button { + margin-right: 10px; +} + +.testimonials-component-container .next-button:hover, +.prev-button:hover { + border: 1px solid #006eff; +} + +@media (min-width: 768px) { + .testimonials-component-container .title-class { + width: 715px; + } + + .testimonials-component-container .reviews-container { + display: flex; + flex-direction: column; + } +} + +@media (min-width: 990px) { + .testimonials-component-container .reviews-container { + display: flex; + flex-direction: row; + gap: 3%; + } + + .testimonials-component-container .hide { + display: flex; + } + + .testimonials-component-container .show { + display: flex; + } + + .testimonials-component-container .buttons-container { + display: none; + } + + .testimonials-component-container .navigation-container { + justify-content: center; + } + + .testimonials-component-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .testimonials-component-container .testimonials-component { + max-width: 1294px; + } + + .testimonials-component-container.we-container { + max-width: 1290px; + padding-left: 20px; + padding-right: 20px; + } +} \ No newline at end of file diff --git a/_src/blocks/testimonials-component/testimonials-component.js b/_src/blocks/testimonials-component/testimonials-component.js new file mode 100644 index 000000000..beaabf0b5 --- /dev/null +++ b/_src/blocks/testimonials-component/testimonials-component.js @@ -0,0 +1,110 @@ +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const parentSelector = block.closest('.section'); + // eslint-disable-next-line no-unused-vars + const metaData = parentSelector.dataset; + const [title, subtitle, source, ...reviews] = block.children; + + title.classList.add('title-class'); + subtitle.classList.add('subtitle-class'); + source.classList.add('source-class'); + + // Create a new div for reviews + const reviewsContainer = document.createElement('div'); + reviewsContainer.classList.add('reviews-container'); + + // Iterate over each review element + reviews.forEach((review, index) => { + review.classList.add('review'); + + // Create SVG element + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); + svg.setAttribute('viewBox', '0 0 448 512'); + svg.setAttribute('width', '32px'); // Set width to 32 pixels + svg.setAttribute('height', '32px'); // Set height to 32 pixels + svg.style.fill = '#006EFF'; // Set the SVG color to blue + svg.innerHTML = ''; + + // Create a container for the SVG and review content + const reviewContainer = document.createElement('div'); + reviewContainer.classList.add('review-container'); + if (index === 0) { + reviewContainer.classList.add('show'); + } else { + reviewContainer.classList.add('hide'); + } + + // Append SVG and review to the review container + reviewContainer.appendChild(svg); + reviewContainer.appendChild(review); + + // Append review container to the reviews container + reviewsContainer.appendChild(reviewContainer); + }); + + // Append the reviews container to the block + block.appendChild(reviewsContainer); + + // Create navigation buttons for the slider + const prevButton = document.createElement('button'); + // Set SVG icon for previous button with color #006EFF + prevButton.innerHTML = ''; + prevButton.classList.add('prev-button'); + prevButton.addEventListener('click', () => { + // eslint-disable-next-line no-use-before-define + navigateSlider(-1); + }); + + const nextButton = document.createElement('button'); + // Set SVG icon for next button with color #006EFF + nextButton.innerHTML = ` + +`; + nextButton.classList.add('next-button'); + nextButton.addEventListener('click', () => { + // eslint-disable-next-line no-use-before-define + navigateSlider(1); + }); + + // Create navigation container + const navigationContainer = document.createElement('div'); + navigationContainer.classList.add('navigation-container'); + block.appendChild(navigationContainer); + navigationContainer.appendChild(source); + // create buttons container + const buttonsContainer = document.createElement('div'); + buttonsContainer.classList.add('buttons-container'); + navigationContainer.appendChild(buttonsContainer); + // Append navigation buttons to the block + buttonsContainer.appendChild(prevButton); + buttonsContainer.appendChild(nextButton); + + // Slider navigation function + let currentIndex = 0; + const reviewsCount = reviews.length; + + function navigateSlider(direction) { + const currentReview = block.querySelector('.show'); + const nextIndex = (currentIndex + direction + reviewsCount) % reviewsCount; + const nextReview = reviewsContainer.children[nextIndex]; + + currentReview.classList.remove('show'); + currentReview.classList.add('hide'); + + nextReview.classList.remove('hide'); + nextReview.classList.add('show'); + + currentIndex = nextIndex; + } + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/thank-you/thank-you.css b/_src/blocks/thank-you/thank-you.css new file mode 100644 index 000000000..e5fa9623e --- /dev/null +++ b/_src/blocks/thank-you/thank-you.css @@ -0,0 +1,244 @@ +.thank-you-container { + .thank-you { + display: flex; + flex-direction: column; + flex: 0 1 50%; + font-family: Arial, Roboto, sans-serif; + + @media (min-width: 768px) { + & { + flex-direction: row; + } + } + + img { + max-width: 100%; + width: auto; + height: auto; + } + + .content-right { + padding-left: 20px; + display: flex; + align-items: end; + justify-content: center; + flex: 1 0 auto; + + + img { + max-width: 520px; + box-shadow: 0 35px 40px 0 #0000000F; + } + } + + .content-left { + max-width: 630px; + + >p:first-of-type { + color: #3782F9; + font-size: 18px; + line-height: clamp(15px, 5vw, 44px); + } + + h1 { + font-size: clamp(24px, 5vw, 53px); + font-weight: 400; + line-height: clamp(30px, 5vw, 77px); + + strong { + color: #006EFF; + font-weight: normal; + } + } + + .qr-content { + display: flex; + font-size: clamp(16px, 5vw, 20px); + align-items: center; + + img { + max-width: 170px; + height: auto; + box-shadow: 0 35px 40px 0 #0000000F; + } + } + } + + /* Importing from styles.css to be able to import in aem */ + p a { + font-family: var(--body-font-family); + font-size: var(--body-font-size-s); + font-style: normal; + font-weight: var(--font-weight-bold); + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: var(--button-link-color); + background-color: var(--button-background-color); + border: 2px solid var(--button-background-color); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + } + + p a::after { + content: ''; + width: 24px; + height: 24px; + /* stylelint-disable-next-line property-no-vendor-prefix */ + -webkit-mask:url('https::/bitdefender.com/_src/icons/arrow-right.svg'); + mask: url('https::/bitdefender.com/_src/icons/arrow-right.svg'); + background-color: var(--button-link-color); + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + opacity: 0; + margin-left: -10px; + } + + p a:hover, p a:focus { + background-color: var(--button-hover-background-color); + border: 2px solid var(--button-hover-background-color); + cursor: pointer; + } + + p a:hover::after { + transform: translateX(5px); + opacity: 1; + } + } + + &.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; + + + @media (min-width: 990px) { + & { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + } + + @media (min-width: 1200px) { + & { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } + } + + @media (min-width: 1600px) { + & { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } + } + } + + @media (min-width: 990px) { + margin-top: 120px; + margin-bottom: 120px; + } + + +} + +/* stylelint-disable-next-line no-duplicate-selectors */ +.thank-you-container { + /* colors */ + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + + /* fonts */ + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + + /* font weights */ + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + + /* body sizes */ + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + + /* heading sizes */ + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + + /* nav height */ + --nav-height: 63px; + --nav-height-desktop: 40px; + + /* body width */ + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1300px; + --section-desktop-padding: 20px; + --section-large-desktop-max-width: 1332px; + --section-large-desktop-padding: 50px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + + /* cta styles */ + --cta-background-light-blue: var(--background-light-blue) +} \ No newline at end of file diff --git a/_src/blocks/thank-you/thank-you.js b/_src/blocks/thank-you/thank-you.js new file mode 100644 index 000000000..fcb4a11f4 --- /dev/null +++ b/_src/blocks/thank-you/thank-you.js @@ -0,0 +1,43 @@ +// Function to dispatch 'shadowDomLoaded' event +function dispatchShadowDomLoadedEvent() { + const event = new CustomEvent('shadowDomLoaded', { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + window.dispatchEvent(event); +} + +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } else { + // eslint-disable-next-line no-param-reassign + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const [richTextPicture, richTextQR] = block.children; + const [richTextPictureText, richTextPicturePicture] = richTextPicture.children; + const [richTextQRText, richTextQRPicture] = richTextQR.children; + const html = ` +
    + ${richTextPictureText.innerHTML} +
    + ${richTextQRText.innerHTML} +
    + ${richTextQRPicture.innerHTML} +
    +
    +
    +
    + ${richTextPicturePicture.innerHTML} +
    + `; + + block.innerHTML = html; + + dispatchShadowDomLoadedEvent(); +} diff --git a/_src/blocks/trusted-hero/trusted-hero.css b/_src/blocks/trusted-hero/trusted-hero.css new file mode 100644 index 000000000..429f7098a --- /dev/null +++ b/_src/blocks/trusted-hero/trusted-hero.css @@ -0,0 +1,166 @@ +.trusted-hero-container.section { + padding: 0; + background: #EFF6FF; + color: black; +} + +.trusted-hero-container .trusted-hero-wrapper .block { + display: flex; + flex-direction: column; +} + +.trusted-hero-container h1, +.trusted-hero-container h2 { + font: normal normal normal 28px/32px var(--font-ibm); +} + +.trusted-hero-container h1 { + font-weight: 500; +} + +.trusted-hero-container .video-wrapper { + height: 200px; + position: relative; +} + +.trusted-hero-container .video-wrapper iframe { + width: 100%; + height: 100%; + object-fit: cover; + position: absolute; + left: 0; +} + +.trusted-hero-container .default-content-wrapper { + position: relative; + padding-top: 20px !important; + z-index: 4; + order: -1; + padding-bottom: 140px; +} + +.trusted-hero-container p.button-container:nth-last-child(1) { + position: absolute; + bottom: 0; + left: 1em; + right: 1em; +} + +.trusted-hero-container p.button-container:nth-last-child(2) { + position: absolute; + bottom: 60px; + left: 1em; + right: 1em; +} + +.trusted-hero-container p.button-container a { + background-color: transparent !important; + border: solid black 1px !important; + color: black; + width: 100%; + justify-content: center; + font-weight: 500 !important; +} + +.trusted-hero-container p.button-container:nth-last-child(2) a { + width: 100%; + justify-content: center; + font-weight: 400; + border: 1px solid var(--blue); +} + +.trusted-hero-container p.button-container a:hover { + background-color: var(--blue) !important; + border: 1px solid var(--blue) !important; + color: white; +} + +@media (min-width: 768px) { + /* .trusted-hero-container a.button:any-link:not(.modal, .primary) { */ + + /* width: unset; */ + + /* justify-content: unset; */ + + /* display: inline-flex; */ + + /* margin-right: 15px; */ + + /* } */ + .trusted-hero-container h1, + .trusted-hero-container h2 { + font: normal normal 500 29px / 33px var(--font-ibm); + } + + .trusted-hero-container h2 { + margin: 50px 0 0; + color: black; + } +} + +@media (min-width: 992px) { + .trusted-hero-container { + background: #EFF6FF; + color: black; + height: 670px; + } + + .trusted-hero-container h1 { + font: normal normal 500 47px / 48px var(--font-ibm); + } + + .trusted-hero-container .trusted-hero-wrapper { + height: 100%; + } + + .trusted-hero-container .trusted-hero-wrapper .block { + height: 100%; + display: flex; + flex-direction: row; + } + + .trusted-hero-container .rte-wrapper { + width: 100%; + } + + .trusted-hero-container .video-wrapper { + width: 100%; + height: 100%; + } + + .trusted-hero-container .default-content-wrapper { + padding-top: 0 !important; + order: unset; + position: absolute; + left: 0; + right: 0; + height: 100%; + display: flex; + align-items: center; + gap: 30px; + padding-bottom: unset; + } + + .trusted-hero-container .default-content-wrapper > .rte-wrapper { + width: 555px; + padding-right: 4em; + } + + .trusted-hero-container .default-content-wrapper > .video-wrapper { + width: 60%; + height: 385px; + } + + .trusted-hero-container .default-content-wrapper p.button-container { + position: unset; + display: inline-block; + } + + .trusted-hero-container a.button:any-link:not(.modal, .primary) { + width: unset; + justify-content: unset; + display: inline-flex; + margin-right: 15px; + } +} + diff --git a/_src/blocks/trusted-hero/trusted-hero.js b/_src/blocks/trusted-hero/trusted-hero.js new file mode 100644 index 000000000..18231b6ee --- /dev/null +++ b/_src/blocks/trusted-hero/trusted-hero.js @@ -0,0 +1,34 @@ +export default async function decorate(block) { + const [rte, videoUrl] = [...block.children]; + + const autoplay = false; + const url = new URL(videoUrl.textContent.trim()); + const usp = new URLSearchParams(url.search); + const suffix = autoplay ? '&muted=1&autoplay=1' : ''; + let vid = usp.get('v') ? encodeURIComponent(usp.get('v')) : ''; + const embed = url.pathname; + + if (url.origin.includes('youtu.be')) { + [, vid] = url.pathname.split('/'); + } + + block.innerHTML = ` +
    +
    ${rte.innerHTML}
    +
    + +
    +
    + `; + + block.querySelectorAll('.button-container > a').forEach((anchorEl) => { + anchorEl.target = '_blank'; + anchorEl.rel = 'noopener noreferrer'; + }); +} diff --git a/_src/blocks/trusted-main-carousel/trusted-main-carousel.css b/_src/blocks/trusted-main-carousel/trusted-main-carousel.css new file mode 100644 index 000000000..bb190d046 --- /dev/null +++ b/_src/blocks/trusted-main-carousel/trusted-main-carousel.css @@ -0,0 +1,183 @@ +.trusted-main-carousel-container { + background: white; +} + +.trusted-main-carousel-container .navigation-wrapper { + display: flex; + scrollbar-width: none; + overflow: auto; +} + +.trusted-main-carousel-container .navigation-wrapper::-webkit-scrollbar { + display: none; /* For Chrome, Safari, Opera */ +} + +.trusted-main-carousel-container .navigation-wrapper .first-nav { + display: flex; + cursor: pointer; + border-radius: 8px; + background: #EFF6FF; +} + +.trusted-main-carousel-container .navigation-wrapper .second-nav { + display: none; +} + +.trusted-main-carousel-container .navigation-wrapper .nav-item { + color: black; + font-weight: 500; + font-size: 9px; + flex-shrink: 0; + padding: 15px; +} + +.trusted-main-carousel-container .default-content-wrapper { + overflow: hidden; +} + +.trusted-main-carousel-container .navigation-wrapper .nav-item.active { + background: #006EFF; + border-radius: 8px; + color: white; + transition: all .25s linear; + position: relative; + z-index: 1; +} + +.trusted-main-carousel-container .content-wrapper { + color: black; + display: flex; + transform: translateX(0); + transition: transform 0.25s ease-out; +} + +.trusted-main-carousel-container .block.scrolling .content-wrapper { + overflow: unset; +} + +.trusted-main-carousel-container .content-wrapper .slide { + width: 100%; + flex-shrink: 0; + box-sizing: border-box; + margin-right: 50px; +} + +.trusted-main-carousel-container .content-wrapper .slide u { + display: none; +} + +.trusted-main-carousel-container .content-wrapper .slide > * { + position: relative; +} + +.trusted-main-carousel-container .content-wrapper .slide >:first-child p.button-container { + display: flex; + justify-content: center; +} + +.trusted-main-carousel-container .content-wrapper .slide >:last-child { + width: calc(100% + 2em); + margin-left: -1em; + height: 200px; + top: -15px; + z-index: -1; +} + +.trusted-main-carousel-container .content-wrapper .slide >:last-child img { + object-fit: cover; + width: 100%; + height: 100%; +} + +.trusted-main-carousel-container .content-wrapper .slide >:first-child p.button-container a.button:any-link { + background-color: white; + color: black; + font-weight: normal; + border: 1px solid black; + width: 250px; + justify-content: center; +} + +.trusted-main-carousel-container .content-wrapper .slide >:first-child img { + width: 160px; +} + +@media (min-width: 768px) { + .trusted-main-carousel-container .navigation-wrapper .nav-item { + font-size: 100%; + } + + .trusted-main-carousel-container .navigation-wrapper .second-nav { + display: flex; + margin-left: auto; + } + + .trusted-main-carousel-container .left-arrow, + .trusted-main-carousel-container .right-arrow { + color: black; + } + + .trusted-main-carousel-container .left-arrow svg { + transform: rotate(180deg); + } + + .trusted-main-carousel-container .arrow { + width: 100px; + } + + .trusted-main-carousel-container .arrow svg { + width: 100%; + height: 50px; + } + + .trusted-main-carousel-container .arrow svg path { + fill: black; + } + + .trusted-main-carousel-container .left-arrow { + margin-left: auto; + } + + .trusted-main-carousel-container .content-wrapper .slide >:first-child p.button-container { + position: unset; + } + + .trusted-main-carousel-container .content-wrapper .slide >:last-child { + height: 400px; + } +} + +@media (min-width: 992px) { + .trusted-main-carousel-container .content-wrapper .slide { + display: flex; + gap: 50px; + margin-top: 30px; + } + + .trusted-main-carousel-container .navigation-wrapper .nav-item { + padding: 15px 30px; + } + + .trusted-main-carousel-container .content-wrapper .slide >:last-child { + width: calc(60% - 50px); + margin-left: unset; + height: auto; + } + + .trusted-main-carousel-container .content-wrapper .slide >:first-child p.button-container { + justify-content: unset; + } + + .trusted-main-carousel-container .content-wrapper .slide >:first-child > *:not(h2) { + margin: 40px 0; + } + + .trusted-main-carousel-container .content-wrapper .slide >:last-child img { + object-fit: contain; + } + + .trusted-main-carousel-container .content-wrapper .slide > div { + width: calc(40% - 50px); + flex-shrink: 0; + } +} diff --git a/_src/blocks/trusted-main-carousel/trusted-main-carousel.js b/_src/blocks/trusted-main-carousel/trusted-main-carousel.js new file mode 100644 index 000000000..3462b16e7 --- /dev/null +++ b/_src/blocks/trusted-main-carousel/trusted-main-carousel.js @@ -0,0 +1,168 @@ +import { isView } from '../../scripts/scripts.js'; +import { debounce } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const slides = [...block.children]; + const AUTOMATIC_SLIDING = { + enabled: true, + viewport: 'desktop', + slideDelay: 3 * 1000, + }; + + const state = { + currentStep: 0, + carouselIsFocused: false, + currentInterval: null, + }; + + const navItemsNames = slides.map((slideEl) => slideEl.children[0].firstElementChild.textContent); + + block.classList.add('default-content-wrapper'); + block.innerHTML = ` + + +
    + ${slides.map((slide, index) => ` +
    + ${slide.innerHTML} +
    + `).join('')} +
    + `; + + const contentWrapper = block.querySelector('.content-wrapper'); + + const navItems = block.querySelectorAll('.nav-item'); + const slideItems = block.querySelectorAll('.slide'); + const leftArrow = block.querySelector('.left-arrow'); + const rightArrow = block.querySelector('.right-arrow'); + function selectNavItem(itemPosition) { + navItems.forEach((item) => item.classList.remove('active')); + navItems[itemPosition].classList.add('active'); + } + + function selectSlideItem(itemPosition) { + slideItems.forEach((item) => item.classList.remove('active')); + slideItems[itemPosition].classList.add('active'); + } + + function slideToSection(itemPosition) { + block.classList.add('scrolling'); + + const transformValue = -100 * (itemPosition); + const offset = 50 * itemPosition; + contentWrapper.style.transform = `translateX(calc(${transformValue}% - ${offset}px ))`; + setTimeout(() => { + block.classList.remove('scrolling'); + }, 200); + } + + function selectStep(itemPosition) { + state.currentStep = itemPosition; + selectNavItem(itemPosition); + selectSlideItem(itemPosition); + slideToSection(itemPosition); + } + + function endAutomaticSliding(interval) { + clearInterval(interval || state.currentInterval); + } + + function beginAutomaticSliding() { + if (!AUTOMATIC_SLIDING.enabled) return; + + endAutomaticSliding(); + + if (state.carouselIsFocused || !isView(AUTOMATIC_SLIDING.viewport)) { + return; + } + + const interval = setInterval(() => { + const isLastStep = state.currentStep === navItems.length - 1; + const nextStepToSelect = isLastStep ? 0 : (state.currentStep + 1); + selectStep(nextStepToSelect); + + if (!isView(AUTOMATIC_SLIDING.viewport) || state.carouselIsFocused) { + endAutomaticSliding(interval); + } + }, AUTOMATIC_SLIDING.slideDelay); + + state.currentInterval = interval; + } + + function addEventListeners() { + block.addEventListener('mouseenter', () => { + state.carouselIsFocused = true; + endAutomaticSliding(); + }); + + block.addEventListener('mouseleave', () => { + state.carouselIsFocused = false; + beginAutomaticSliding(); + }); + + navItems.forEach((navEl, itemPosition) => { + navEl.addEventListener('click', () => { + selectStep(itemPosition); + }); + }); + + leftArrow.addEventListener('click', (e) => { + e.preventDefault(); + + const isFirstStep = state.currentStep === 0; + if (isFirstStep) { + return; + } + + selectStep(state.currentStep - 1); + }); + + rightArrow.addEventListener('click', (e) => { + e.preventDefault(); + + const isLastStep = state.currentStep === navItems.length - 1; + if (isLastStep) { + return; + } + + selectStep(state.currentStep + 1); + }); + } + + addEventListeners(); + + beginAutomaticSliding(); + window.addEventListener('resize', debounce(beginAutomaticSliding, 250)); +} diff --git a/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.css b/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.css new file mode 100644 index 000000000..5a6c0876c --- /dev/null +++ b/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.css @@ -0,0 +1,112 @@ +.trusted-teaser-impact-container { + background: white; + padding-top: 0 !important; +} + +.trusted-teaser-impact-container .carousel-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 30px; +} + +.trusted-teaser-impact .carousel-header .title { + color: black; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +.trusted-teaser-impact .carousel-header .title >:first-child { + margin: 0; +} + +.trusted-teaser-impact .box-wrapper { + display: flex; + flex-wrap: wrap; + gap: 20px; +} + +.trusted-teaser-impact .box-wrapper .box-item { + width: calc(50% - 10px); + flex-shrink: 0; + color: black; + position: relative; + padding-right: 10px; +} + +.trusted-teaser-impact .box-wrapper .box-item::after { + content: ''; + display: block; + width: 1px; + height: 80%; + position: absolute; + top: 10%; + right: -3px; + background: #006EFF; + opacity: 0.25; + visibility: hidden; +} + +.trusted-teaser-impact .box-wrapper .box-item:nth-child(1)::after, +.trusted-teaser-impact .box-wrapper .box-item:nth-child(3)::after { + visibility: visible; +} + +.trusted-teaser-impact .box-wrapper .box-item .icon { + width: 35px; + height: 35px; + margin: 0; +} + +.trusted-teaser-impact .box-wrapper .box-item .icon .cls-1 { + fill: #006EFF; +} + +.trusted-teaser-impact .box-wrapper .box-item .title { + font-size: 35px; + font-weight: bold; +} + +@media (min-width: 768px) { + .trusted-teaser-impact .box-wrapper .box-item .icon { + width: 50px; + height: 50px; + } + + .trusted-teaser-impact .box-wrapper .box-item:nth-child(2), + .trusted-teaser-impact .box-wrapper .box-item:nth-child(4) { + padding-left: 20px; + } + +} + +@media (min-width: 992px) { + .trusted-teaser-impact .box-wrapper .box-item { + width: calc(25% - 15px); + } + + .trusted-teaser-impact .box-wrapper .box-item .title { + font-size: 50px; + color: #35383C; + } + + .trusted-teaser-impact .box-wrapper .box-item .subtitle { + margin-top: 0; + } + + .trusted-teaser-impact .box-wrapper .box-item .icon { + width: 70px; + height: 70px; + } + + .trusted-teaser-impact .box-wrapper .box-item:nth-child(3) { + padding-left: 20px; + } + + .trusted-teaser-impact .box-wrapper .box-item:nth-child(2)::after { + visibility: visible; + } +} + diff --git a/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.js b/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.js new file mode 100644 index 000000000..24ecf121c --- /dev/null +++ b/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.js @@ -0,0 +1,38 @@ +import { decorateIcons } from '../../scripts/lib-franklin.js'; +import { debounce } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [titleEl, ...boxes] = [...block.children]; + + function render() { + block.classList.add('default-content-wrapper'); + + block.innerHTML = ` + + +
    + ${boxes.map((box) => ` +
    + ${box.children[0].children[0].innerHTML} + +
    + ${box.children[0].children[1].textContent} +
    + +

    + ${box.children[0].children[2].innerHTML} +

    +
    + `).join('')} +
    + `; + + decorateIcons(block); + } + + render(); + + window.addEventListener('resize', debounce(render, 250)); +} diff --git a/_src/blocks/video/video.css b/_src/blocks/video/video.css new file mode 100644 index 000000000..bcac2bf4d --- /dev/null +++ b/_src/blocks/video/video.css @@ -0,0 +1,87 @@ +.video { + width: unset; + text-align: center; + margin-top: 32px; + margin-bottom: 32px; +} + +.video.lazy-loading { + /* reserve an approximate space to avoid extensive layout shifts */ + aspect-ratio: 16/9; +} + +.video > div { + display: flex; + justify-content: center; + border-radius: 13px; + overflow: hidden; +} + +.video.left { + margin-right: auto; +} + +.video.center { + margin-left: auto; + margin-right: auto; +} + +.video.right { + margin-left: auto; +} + +.video video { + max-width: 100%; +} + +.video video[data-loading] { + /* reserve an approximate space to avoid extensive layout shifts */ + width: 100%; + aspect-ratio: 16/9; +} + +.video .video-placeholder { + width: 100%; + aspect-ratio: 16/9; + position: relative; +} + +.video .video-placeholder > * { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + inset: 0; +} + +.video .video-placeholder picture img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.video .video-placeholder-play button { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(3); + width: 22px; + height: 22px; + border: 2px solid; + border-radius: 20px; + padding: 0; +} + +.video .video-placeholder-play button::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 0; + height: 10px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 6px solid; + top: 4px; + left: 7px; +} \ No newline at end of file diff --git a/_src/blocks/video/video.js b/_src/blocks/video/video.js new file mode 100644 index 000000000..482179405 --- /dev/null +++ b/_src/blocks/video/video.js @@ -0,0 +1,108 @@ +/* + * Video Block + * Show a video referenced by a link + * https://www.hlx.live/developer/block-collection/video + */ +function embedYoutube(url, autoplay) { + const usp = new URLSearchParams(url.search); + const suffix = autoplay ? '&muted=1&autoplay=1' : ''; + let vid = usp.get('v') ? encodeURIComponent(usp.get('v')) : ''; + const embed = url.pathname; + if (url.origin.includes('youtu.be')) { + [, vid] = url.pathname.split('/'); + } + return `
    + +
    `; +} + +function embedVimeo(url, autoplay) { + const [, video] = url.pathname.split('/'); + const suffix = autoplay ? '?muted=1&autoplay=1' : ''; + return `
    + +
    `; +} + +function getVideoElement(source, autoplay) { + const video = document.createElement('video'); + video.setAttribute('controls', ''); + video.dataset.loading = 'true'; + video.addEventListener('loadedmetadata', () => delete video.dataset.loading); + if (autoplay) video.setAttribute('autoplay', ''); + + const sourceEl = document.createElement('source'); + sourceEl.setAttribute('src', source); + sourceEl.setAttribute('type', `video/${source.split('.').pop()}`); + video.append(sourceEl); + + return video; +} + +const loadVideoEmbed = (block, link, autoplay) => { + if (block.dataset.embedIsLoaded) { + return; + } + const url = new URL(link); + + const isYoutube = link.includes('youtube') || link.includes('youtu.be'); + const isVimeo = link.includes('vimeo'); + const isMp4 = link.includes('.mp4'); + + if (isYoutube) { + block.innerHTML = embedYoutube(url, autoplay); + } else if (isVimeo) { + block.innerHTML = embedVimeo(url, autoplay); + } else if (isMp4) { + block.textContent = ''; + block.append(getVideoElement(link, autoplay)); + } + + block.dataset.embedIsLoaded = true; +}; + +const DESKTOP_ALIGN_ENUM = { + left: 'left', + right: 'right', + center: 'center', +}; + +function positionVideoContainer(block, desktopAlign) { + block.classList.add(DESKTOP_ALIGN_ENUM[desktopAlign] || DESKTOP_ALIGN_ENUM.LEFT); +} + +export default async function decorate(block) { + block.classList.add('default-content-wrapper'); + block.closest('.section').style.padding = '0'; + const { desktopAlign } = block.closest('.section').dataset; // left / middle / right + const placeholder = block.querySelector('picture'); + const link = block.querySelector('a').href; + block.textContent = ''; + + positionVideoContainer(block, desktopAlign); + + if (placeholder) { + const wrapper = document.createElement('div'); + wrapper.className = 'video-placeholder'; + wrapper.innerHTML = '
    '; + wrapper.prepend(placeholder); + wrapper.addEventListener('click', () => { + loadVideoEmbed(block, link, true); + }); + block.append(wrapper); + } else { + block.classList.add('lazy-loading'); + const observer = new IntersectionObserver((entries) => { + if (entries.some((e) => e.isIntersecting)) { + observer.disconnect(); + loadVideoEmbed(block, link, false); + block.classList.remove('lazy-loading'); + } + }); + observer.observe(block); + } +} diff --git a/_src/fonts/ibm-plex-sans-300.woff2 b/_src/fonts/ibm-plex-sans-300.woff2 new file mode 100644 index 000000000..5eb6300c8 Binary files /dev/null and b/_src/fonts/ibm-plex-sans-300.woff2 differ diff --git a/_src/fonts/ibm-plex-sans-400.woff2 b/_src/fonts/ibm-plex-sans-400.woff2 new file mode 100644 index 000000000..8e1333308 Binary files /dev/null and b/_src/fonts/ibm-plex-sans-400.woff2 differ diff --git a/_src/fonts/ibm-plex-sans-500.woff2 b/_src/fonts/ibm-plex-sans-500.woff2 new file mode 100644 index 000000000..1b3f5c649 Binary files /dev/null and b/_src/fonts/ibm-plex-sans-500.woff2 differ diff --git a/solutions/fonts/roboto-300.woff2 b/_src/fonts/roboto-300.woff2 similarity index 100% rename from solutions/fonts/roboto-300.woff2 rename to _src/fonts/roboto-300.woff2 diff --git a/solutions/fonts/roboto-400.woff2 b/_src/fonts/roboto-400.woff2 similarity index 100% rename from solutions/fonts/roboto-400.woff2 rename to _src/fonts/roboto-400.woff2 diff --git a/solutions/fonts/roboto-500.woff2 b/_src/fonts/roboto-500.woff2 similarity index 100% rename from solutions/fonts/roboto-500.woff2 rename to _src/fonts/roboto-500.woff2 diff --git a/_src/icons/arow_down.png b/_src/icons/arow_down.png new file mode 100644 index 000000000..194b19a3b Binary files /dev/null and b/_src/icons/arow_down.png differ diff --git a/solutions/icons/arrow-right.svg b/_src/icons/arrow-right.svg similarity index 100% rename from solutions/icons/arrow-right.svg rename to _src/icons/arrow-right.svg diff --git a/_src/icons/b-logo-red.svg b/_src/icons/b-logo-red.svg new file mode 100644 index 000000000..14d05cb41 --- /dev/null +++ b/_src/icons/b-logo-red.svg @@ -0,0 +1 @@ + diff --git a/_src/icons/bd-round-thumb.svg b/_src/icons/bd-round-thumb.svg new file mode 100644 index 000000000..102b37c76 --- /dev/null +++ b/_src/icons/bd-round-thumb.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/solutions/icons/blue-circle.svg b/_src/icons/blue-circle.svg similarity index 100% rename from solutions/icons/blue-circle.svg rename to _src/icons/blue-circle.svg diff --git a/_src/icons/book-sharp-regular.svg b/_src/icons/book-sharp-regular.svg new file mode 100644 index 000000000..2c2316457 --- /dev/null +++ b/_src/icons/book-sharp-regular.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_src/icons/burger_menu.JPG b/_src/icons/burger_menu.JPG new file mode 100644 index 000000000..3743e7ef1 Binary files /dev/null and b/_src/icons/burger_menu.JPG differ diff --git a/_src/icons/checkmark-green-circle.svg b/_src/icons/checkmark-green-circle.svg new file mode 100644 index 000000000..de0d9ec77 --- /dev/null +++ b/_src/icons/checkmark-green-circle.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/solutions/icons/checkmark_solid-circle.svg b/_src/icons/checkmark-light-green-circle.svg similarity index 100% rename from solutions/icons/checkmark_solid-circle.svg rename to _src/icons/checkmark-light-green-circle.svg diff --git a/solutions/icons/checkmark-solid-circle-white.svg b/_src/icons/checkmark-solid-circle-white.svg similarity index 100% rename from solutions/icons/checkmark-solid-circle-white.svg rename to _src/icons/checkmark-solid-circle-white.svg diff --git a/_src/icons/checkmark-x-circle.svg b/_src/icons/checkmark-x-circle.svg new file mode 100644 index 000000000..ed5ad8c7d --- /dev/null +++ b/_src/icons/checkmark-x-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_src/icons/checkmark_solid-circle.svg b/_src/icons/checkmark_solid-circle.svg new file mode 100644 index 000000000..151ed5733 --- /dev/null +++ b/_src/icons/checkmark_solid-circle.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/solutions/icons/dark-blue-quote.svg b/_src/icons/dark-blue-quote.svg similarity index 100% rename from solutions/icons/dark-blue-quote.svg rename to _src/icons/dark-blue-quote.svg diff --git a/_src/icons/facebook.svg b/_src/icons/facebook.svg new file mode 100644 index 000000000..ff4c4a0e7 --- /dev/null +++ b/_src/icons/facebook.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/_src/icons/linkedin.svg b/_src/icons/linkedin.svg new file mode 100644 index 000000000..c731c259f --- /dev/null +++ b/_src/icons/linkedin.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_src/icons/minus-sharp-regular.svg b/_src/icons/minus-sharp-regular.svg new file mode 100644 index 000000000..81c865a81 --- /dev/null +++ b/_src/icons/minus-sharp-regular.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_src/icons/particle-band.svg b/_src/icons/particle-band.svg new file mode 100644 index 000000000..589d18298 --- /dev/null +++ b/_src/icons/particle-band.svg @@ -0,0 +1 @@ + diff --git a/_src/icons/plus-sharp-regular.svg b/_src/icons/plus-sharp-regular.svg new file mode 100644 index 000000000..395763b64 --- /dev/null +++ b/_src/icons/plus-sharp-regular.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_src/icons/quot.png b/_src/icons/quot.png new file mode 100644 index 000000000..c5d74ede4 Binary files /dev/null and b/_src/icons/quot.png differ diff --git a/_src/icons/quote-left.svg b/_src/icons/quote-left.svg new file mode 100644 index 000000000..a98b2aa46 --- /dev/null +++ b/_src/icons/quote-left.svg @@ -0,0 +1 @@ + diff --git a/solutions/icons/search.svg b/_src/icons/search.svg similarity index 100% rename from solutions/icons/search.svg rename to _src/icons/search.svg diff --git a/solutions/icons/tabs_arrow.svg b/_src/icons/tabs_arrow.svg similarity index 100% rename from solutions/icons/tabs_arrow.svg rename to _src/icons/tabs_arrow.svg diff --git a/_src/icons/twitter.svg b/_src/icons/twitter.svg new file mode 100644 index 000000000..91888f30f --- /dev/null +++ b/_src/icons/twitter.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/_src/icons/user-guide-white.svg b/_src/icons/user-guide-white.svg new file mode 100644 index 000000000..947acceb9 --- /dev/null +++ b/_src/icons/user-guide-white.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/solutions/icons/user-guide.svg b/_src/icons/user-guide.svg similarity index 100% rename from solutions/icons/user-guide.svg rename to _src/icons/user-guide.svg diff --git a/_src/icons/youtube.svg b/_src/icons/youtube.svg new file mode 100644 index 000000000..731648bb4 --- /dev/null +++ b/_src/icons/youtube.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/_src/images/appstore.webp b/_src/images/appstore.webp new file mode 100644 index 000000000..029cf0a47 Binary files /dev/null and b/_src/images/appstore.webp differ diff --git a/solutions/images/b-red-mask.png b/_src/images/b-red-mask.png similarity index 100% rename from solutions/images/b-red-mask.png rename to _src/images/b-red-mask.png diff --git a/_src/images/black_company_logo.svg b/_src/images/black_company_logo.svg new file mode 100644 index 000000000..485f5412a --- /dev/null +++ b/_src/images/black_company_logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/_src/images/playstore.webp b/_src/images/playstore.webp new file mode 100644 index 000000000..dbe58b8b4 Binary files /dev/null and b/_src/images/playstore.webp differ diff --git a/_src/images/quiz-results-bg.jpg b/_src/images/quiz-results-bg.jpg new file mode 100644 index 000000000..50f80d497 Binary files /dev/null and b/_src/images/quiz-results-bg.jpg differ diff --git a/_src/images/sigla_bd_white.svg b/_src/images/sigla_bd_white.svg new file mode 100644 index 000000000..23ab4e9f2 --- /dev/null +++ b/_src/images/sigla_bd_white.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/_src/plugins/experimentation/CODE_OF_CONDUCT.md b/_src/plugins/experimentation/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/plugins/experimentation/LICENSE.md b/_src/plugins/experimentation/LICENSE.md similarity index 100% rename from solutions/plugins/experimentation/LICENSE.md rename to _src/plugins/experimentation/LICENSE.md diff --git a/solutions/plugins/experimentation/README.md b/_src/plugins/experimentation/README.md similarity index 100% rename from solutions/plugins/experimentation/README.md rename to _src/plugins/experimentation/README.md diff --git a/solutions/plugins/experimentation/package-lock.json b/_src/plugins/experimentation/package-lock.json similarity index 100% rename from solutions/plugins/experimentation/package-lock.json rename to _src/plugins/experimentation/package-lock.json diff --git a/solutions/plugins/experimentation/package.json b/_src/plugins/experimentation/package.json similarity index 100% rename from solutions/plugins/experimentation/package.json rename to _src/plugins/experimentation/package.json diff --git a/solutions/plugins/experimentation/src/index.js b/_src/plugins/experimentation/src/index.js similarity index 100% rename from solutions/plugins/experimentation/src/index.js rename to _src/plugins/experimentation/src/index.js diff --git a/solutions/plugins/experimentation/src/preview.css b/_src/plugins/experimentation/src/preview.css similarity index 100% rename from solutions/plugins/experimentation/src/preview.css rename to _src/plugins/experimentation/src/preview.css diff --git a/solutions/plugins/experimentation/src/preview.js b/_src/plugins/experimentation/src/preview.js similarity index 100% rename from solutions/plugins/experimentation/src/preview.js rename to _src/plugins/experimentation/src/preview.js diff --git a/solutions/plugins/experimentation/src/ued.js b/_src/plugins/experimentation/src/ued.js similarity index 100% rename from solutions/plugins/experimentation/src/ued.js rename to _src/plugins/experimentation/src/ued.js diff --git a/solutions/plugins/rum-conversion/.eslintignore b/_src/plugins/rum-conversion/.eslintignore similarity index 100% rename from solutions/plugins/rum-conversion/.eslintignore rename to _src/plugins/rum-conversion/.eslintignore diff --git a/solutions/plugins/experimentation/.eslintrc.js b/_src/plugins/rum-conversion/.eslintrc.js similarity index 100% rename from solutions/plugins/experimentation/.eslintrc.js rename to _src/plugins/rum-conversion/.eslintrc.js diff --git a/solutions/plugins/rum-conversion/.gitignore b/_src/plugins/rum-conversion/.gitignore similarity index 100% rename from solutions/plugins/rum-conversion/.gitignore rename to _src/plugins/rum-conversion/.gitignore diff --git a/solutions/plugins/rum-conversion/.npmignore b/_src/plugins/rum-conversion/.npmignore similarity index 100% rename from solutions/plugins/rum-conversion/.npmignore rename to _src/plugins/rum-conversion/.npmignore diff --git a/solutions/plugins/experimentation/.stylelintrc.json b/_src/plugins/rum-conversion/.stylelintrc.json similarity index 100% rename from solutions/plugins/experimentation/.stylelintrc.json rename to _src/plugins/rum-conversion/.stylelintrc.json diff --git a/solutions/plugins/rum-conversion/LICENSE b/_src/plugins/rum-conversion/LICENSE similarity index 100% rename from solutions/plugins/rum-conversion/LICENSE rename to _src/plugins/rum-conversion/LICENSE diff --git a/solutions/plugins/rum-conversion/README.md b/_src/plugins/rum-conversion/README.md similarity index 100% rename from solutions/plugins/rum-conversion/README.md rename to _src/plugins/rum-conversion/README.md diff --git a/solutions/plugins/rum-conversion/package-lock.json b/_src/plugins/rum-conversion/package-lock.json similarity index 100% rename from solutions/plugins/rum-conversion/package-lock.json rename to _src/plugins/rum-conversion/package-lock.json diff --git a/solutions/plugins/rum-conversion/package.json b/_src/plugins/rum-conversion/package.json similarity index 100% rename from solutions/plugins/rum-conversion/package.json rename to _src/plugins/rum-conversion/package.json diff --git a/solutions/plugins/rum-conversion/src/index.js b/_src/plugins/rum-conversion/src/index.js similarity index 100% rename from solutions/plugins/rum-conversion/src/index.js rename to _src/plugins/rum-conversion/src/index.js diff --git a/solutions/scripts/analytics.js b/_src/scripts/analytics.js similarity index 100% rename from solutions/scripts/analytics.js rename to _src/scripts/analytics.js diff --git a/solutions/scripts/breadcrumbs.js b/_src/scripts/breadcrumbs.js similarity index 83% rename from solutions/scripts/breadcrumbs.js rename to _src/scripts/breadcrumbs.js index 0a701a416..62612218e 100644 --- a/solutions/scripts/breadcrumbs.js +++ b/_src/scripts/breadcrumbs.js @@ -2,10 +2,10 @@ import { createTag, fetchIndex, fixExcelFilterZeroes, -} from './utils.js'; +} from './utils/utils.js'; // eslint-disable-next-line import/no-cycle -import { decorateBlockWithRegionId } from './scripts.js'; +import { decorateBlockWithRegionId, getDomain } from './scripts.js'; function prependSlash(path) { return path.startsWith('/') ? path : `/${path}`; @@ -40,7 +40,8 @@ async function createBreadcrumbs(container) { const { pathname } = window.location; const pathSeparator = '/'; // split pathname into parts add / at the end and remove empty parts - const pathSplit = pathname.split('/').reduce((acc, curr, index, array) => { + const domain = getDomain(); + const pathSplit = pathname.split('/').filter((item) => item !== domain).reduce((acc, curr, index, array) => { if (index < array.length - 1) { acc.push(`${curr}/`); } else if (curr !== '') { @@ -57,19 +58,19 @@ async function createBreadcrumbs(container) { const breadcrumbs = [ { name: 'Home', - url_path: '/', + url_path: `/${domain}/`, }, ...pathSplit.slice(1, -1).map((part, index) => { const url = urlForIndex(index); return { - name: getName(pageIndex, url, part, false), - url_path: url, + name: getName(pageIndex, `/${domain}${url}`, part, false, domain), + url_path: `/${domain}${url}`, }; }), { // get the breadcrumb title from the metadata; if the metadata does not contain it, // the last part of the path is used as the breadcrumb title - name: getName(pageIndex, pathname, pathSplit[pathSplit.length - 1], true), + name: getName(pageIndex, pathname, pathSplit[pathSplit.length - 1], true, domain), }, ]; diff --git a/solutions/scripts/delayed.js b/_src/scripts/delayed.js similarity index 90% rename from solutions/scripts/delayed.js rename to _src/scripts/delayed.js index 68448a17f..6ee632b94 100644 --- a/solutions/scripts/delayed.js +++ b/_src/scripts/delayed.js @@ -15,7 +15,7 @@ import { openUrlForOs, } from './scripts.js'; import { loadBreadcrumbs } from './breadcrumbs.js'; -import { onAdobeMcLoaded } from './utils.js'; +import { GLOBAL_EVENTS } from './utils/utils.js'; // Core Web Vitals RUM collection sampleRUM('cwv'); @@ -36,7 +36,8 @@ const { launchProdScript, launchStageScript, launchDevScript } = await fetchPlac const adobeMcScriptUrl = `${LAUNCH_URL}${ADOBE_MC_URL_ENV_MAP.get(ENVIRONMENT) || launchDevScript}`; await loadScript(adobeMcScriptUrl); - onAdobeMcLoaded(); + document.dispatchEvent(new Event(GLOBAL_EVENTS.ADOBE_MC_LOADED)); + window.ADOBE_MC_EVENT_LOADED = true; })(); pushProductsToDataLayer(); diff --git a/_src/scripts/lib-franklin-api.js b/_src/scripts/lib-franklin-api.js new file mode 100644 index 000000000..7cfa9d3f0 --- /dev/null +++ b/_src/scripts/lib-franklin-api.js @@ -0,0 +1,264 @@ +/** + * @param {HTMLDivElement} shadoRoot + * @param {string} origin - prepends the origin to the relative links + */ +const updateLinkSources = (shadoRoot, origin) => { + shadoRoot + .querySelectorAll('source') + .forEach(source => source.srcset = new URL(source.getAttribute("srcset"), origin).href); + + shadoRoot + .querySelectorAll('img') + .forEach(image => image.src = new URL(image.getAttribute("src"), origin).href); +}; + +let ICONS_CACHE = {}; +async function decorateIcons(element) { + // Prepare the inline sprite + let svgSprite = element.getElementById('franklin-svg-sprite'); + if (!svgSprite) { + const div = document.createElement('div'); + div.innerHTML = ''; + svgSprite = div.firstElementChild; + element.append(div.firstElementChild); + } + // Download all new icons + const icons = [...element.querySelectorAll('span.icon')]; + await Promise.all(icons.map(async (span) => { + const iconName = Array.from(span.classList).find((c) => c.startsWith('icon-')).substring(5); + if (!ICONS_CACHE[iconName]) { + ICONS_CACHE[iconName] = true; + try { + let dynamicIconsSharepointPath = 'https://www.bitdefender.com/common/icons/'; + if (window.location.hostname.includes('bitdefender.co.uk')) { + dynamicIconsSharepointPath = 'https://www.bitdefender.co.uk/content/dam/franklin/'; + } + if (window.location.hostname.includes('bitdefender.fr')) { + dynamicIconsSharepointPath = 'https://www.bitdefender.fr/content/dam/franklin/'; + } + // check for localhost + if (window.location.hostname === 'localhost') { + dynamicIconsSharepointPath = 'https://www.bitdefender.com/common/icons/'; + } + const response = await fetch(`${dynamicIconsSharepointPath}${iconName}.svg`); + if (!response.ok) { + ICONS_CACHE[iconName] = false; + return; + } + // Styled icons don't play nice with the sprite approach because of shadow dom isolation + const svg = await response.text(); + if (svg.match(/(