diff --git a/blocks/showcards/showcards.css b/blocks/showcards/showcards.css new file mode 100644 index 00000000..d06f2609 --- /dev/null +++ b/blocks/showcards/showcards.css @@ -0,0 +1,65 @@ +.custom-bg { + background-image: url('https://www.aldevron.com/hs-fs/hubfs/aldevron-solid-orange-background.png?width=1800&name=aldevron-solid-orange-background.png'); +} + +.lists { + display: flex; + justify-content: center; + grid-gap: 3rem; + flex-wrap: wrap; +} + +.card { + position: relative; + display: flex; + text-align: var(--custom-text-alignment, center); + flex-direction: var(--custom-direction, column); + min-width: var(--custom-min-width); + height: var(--custom-height); + height: var(--custom-min-height); + width: var(--custom-width, 300px); + color: var(--custom-color); + word-wrap: break-word; + background-color: var(--custom-bg, #fff); + background-clip: border-box; + border: var(--custom-width) solid var(--custom-border-color); + border-radius: var(--custom-border-radius, 3px); + transition-property: var(--custom-ts-property, transform); + transition-timing-function: var(--custom-ts-timing, cubic-bezier(0.4, 0, 0.2, 1)); + transition-duration: var(--custom-ts-duration, 150ms); + padding: 1rem 0.25rem; +} + +.module-title{ + text-transform: capitalize; +} + +.card-header, .card-body, .card-footer { + padding: var(--custom-width, 0.75rem 0.5rem); +} + +.card .card-img img { + max-width: 120px; + width: 100%; + max-height: 130px; + height: 100%; +} + +.card .card-header { + background-color: var(--custom-header-color, #fff); +} + +.card .card-header .card-title { + font-size: var(--text-size, 1.5rem); + line-height: var(--text-line-height, 1.5rem); +} + +.card .card-body { + flex: 1 1 auto; + background-color: var(--custom-body-color, #fff); +} + +.card .card-footer { + background-color: var(--custom-footer-color, #fff); +} + diff --git a/blocks/showcards/showcards.js b/blocks/showcards/showcards.js new file mode 100644 index 00000000..4d143966 --- /dev/null +++ b/blocks/showcards/showcards.js @@ -0,0 +1,37 @@ +import { + div, h2, h3, li, p, ul, +} from '../../scripts/dom-builder.js'; + +export default function decorate(block) { + const checkServiceSection = block.classList.contains('data-block-heading-services'); + block.className += checkServiceSection ? ' module mmg-rich-columns padding-all wide-section center shift-top style-icons' + : 'module mmg-rich-columns padding-all custom-bg wide-section center style-icons'; + const clondBlock = block.cloneNode(true); + const dataHeading = block.className.split(' ').filter((y) => y.includes('data-block-heading-')); + const wrapper = div({ class: 'outer' }); + if (dataHeading.length > 0) wrapper.append(h2({ class: 'module-title align-center' }, dataHeading[0].replace('data-block-heading-', ''))); + const lists = ul({ class: 'content flex cols3' }); + [...clondBlock.children].forEach((element) => { + const picElement = element.querySelector('picture'); + picElement.className = 'media img'; + const ancButton = element.querySelector('p.button-container'); + const showcaseBanner = li({ class: 'col with-cta' }, picElement); + const contentEle = div({ class: 'card-body' }); + if (ancButton.previousElementSibling && ancButton.previousElementSibling.previousElementSibling && ancButton.previousElementSibling.previousElementSibling.textContent !== '') { + const title = h3({ class: 'title' }, ancButton.previousElementSibling.previousElementSibling.textContent); + contentEle.append(title); + } + if (ancButton.previousElementSibling && ancButton.previousElementSibling.textContent !== '') { + const description = p({ class: 'description' }, ancButton.previousElementSibling.textContent); + contentEle.append(description); + } + showcaseBanner.append(contentEle); + if (ancButton.children.length > 0) { + const cardFooter = div({ class: 'actions' }, ancButton.children[0]); + showcaseBanner.append(cardFooter); + } + lists.append(showcaseBanner); + }); + wrapper.append(lists); + block.replaceChildren(wrapper); +} diff --git a/scripts/dom-builder.js b/scripts/dom-builder.js new file mode 100644 index 00000000..4253cef0 --- /dev/null +++ b/scripts/dom-builder.js @@ -0,0 +1,88 @@ +/* eslint-disable no-param-reassign */ + +/** + * Example Usage: + * + * domEl('main', + * div({ class: 'card' }, + * a({ href: item.path }, + * div({ class: 'card-thumb' }, + * createOptimizedPicture(item.image, item.title, 'lazy', [{ width: '800' }]), + * ), + * div({ class: 'card-caption' }, + * h3(item.title), + * p({ class: 'card-description' }, item.description), + * p({ class: 'button-container' }, + * a({ href: item.path, 'aria-label': 'Read More', class: 'button primary' }, 'Read More'), + * ), + * ), + * ), + * ) + */ + +/** + * Helper for more concisely generating DOM Elements with attributes and children + * @param {string} tag HTML tag of the desired element + * @param {[Object?, ...Element]} items: First item can optionally be an object of attributes, + * everything else is a child element + * @returns {Element} The constructred DOM Element + */ +export function domEl(tag, ...items) { + const element = document.createElement(tag); + if (!items || items.length === 0) return element; + if (!(items[0] instanceof Element || items[0] instanceof HTMLElement) && typeof items[0] === 'object') { + const [attributes, ...rest] = items; + items = rest; + Object.entries(attributes).forEach(([key, value]) => { + if (!key.startsWith('on')) { + element.setAttribute(key, Array.isArray(value) ? value.join(' ') : value); + } else { + element.addEventListener(key.substring(2).toLowerCase(), value); + } + }); + } + items.forEach((item) => { + item = item instanceof Element || item instanceof HTMLElement + ? item + : document.createTextNode(item); + element.appendChild(item); + }); + return element; +} +/* + More short hand functions can be added for very common DOM elements below. + domEl function from above can be used for one off DOM element occurrences. +*/ +export function div(...items) { return domEl('div', ...items); } +export function p(...items) { return domEl('p', ...items); } +export function a(...items) { return domEl('a', ...items); } +export function h1(...items) { return domEl('h1', ...items); } +export function h2(...items) { return domEl('h2', ...items); } +export function h3(...items) { return domEl('h3', ...items); } +export function h4(...items) { return domEl('h4', ...items); } +export function h5(...items) { return domEl('h5', ...items); } +export function h6(...items) { return domEl('h6', ...items); } +export function ul(...items) { return domEl('ul', ...items); } +export function ol(...items) { return domEl('ol', ...items); } +export function li(...items) { return domEl('li', ...items); } +export function i(...items) { return domEl('i', ...items); } +export function img(...items) { return domEl('img', ...items); } +export function span(...items) { return domEl('span', ...items); } +export function form(...items) { return domEl('form', ...items); } +export function input(...items) { return domEl('input', ...items); } +export function label(...items) { return domEl('label', ...items); } +export function button(...items) { return domEl('button', ...items); } +export function iframe(...items) { return domEl('iframe', ...items); } +export function nav(...items) { return domEl('nav', ...items); } +export function fieldset(...items) { return domEl('fieldset', ...items); } +export function article(...items) { return domEl('article', ...items); } +export function strong(...items) { return domEl('strong', ...items); } +export function select(...items) { return domEl('select', ...items); } +export function option(...items) { return domEl('option', ...items); } +export function table(...items) { return domEl('table', ...items); } +export function tbody(...items) { return domEl('tbody', ...items); } +export function thead(...items) { return domEl('thead', ...items); } +export function tr(...items) { return domEl('tr', ...items); } +export function td(...items) { return domEl('td', ...items); } +export function th(...items) { return domEl('th', ...items); } +export function time(...items) { return domEl('time', ...items); }