Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions blocks/multiple-variant-table/multiple-variant-table.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.multiple-variant-table > div {
display: flex;
flex-direction: row;
}

.multiple-variant-table img {
width: 100%;
}

@media (min-width: 900px) {
.multiple-variant-table > div {
display: flex;
align-items: center;
flex-direction: unset;
}

.multiple-variant-table > div > div {
flex: 1;
margin-left: 32px;
}

.multiple-variant-table > div > div:first-of-type {
margin-left: unset;
}
}
65 changes: 65 additions & 0 deletions blocks/multiple-variant-table/multiple-variant-table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
getKey,
startsWithTemplateLiteral,
endsWithTemplateLiteral,
placeholderMap,
} from '../../scripts/menu-content-parser.js';

/**
* Decorate Table HTML with specific class selectors so that,
* it can be handled efficiently by the Menu Builder component
* @param block
*/
function instrumentMultipleVariantTable(block) {
if (!block.children) {
return;
}

const blockImmediateChildren = [...block.children];

blockImmediateChildren.forEach((row) => {
const placeholdersDivs = [...row.querySelectorAll('div')].filter(
(div) => div.innerText.includes(startsWithTemplateLiteral)
&& div.innerText.includes(endsWithTemplateLiteral),
);

if (placeholdersDivs.length > 0) {
if (row.children.length === 3) {
// handling three column placement
for (let i = 0; i < placeholdersDivs.length; i += 1) {
placeholdersDivs[i].style.display = 'none';
if (row.children[1] === placeholdersDivs[i]) {
placeholderMap.set(
`${getKey(placeholdersDivs[i].textContent)}:variant1-price`,
placeholdersDivs[i],
);
} else if (row.children[2] === placeholdersDivs[i]) {
placeholderMap.set(
`${getKey(placeholdersDivs[i].textContent)}:variant2-price`,
placeholdersDivs[i],
);
}
}
}

if (row.children.length === 1) {
// handling single column placement

for (let i = 0; i < placeholdersDivs.length; i += 1) {
placeholdersDivs[i].style.display = 'none';
placeholderMap.set(
getKey(placeholdersDivs[i].textContent),
placeholdersDivs[i],
);
}
}
}
});
}

export default function decorate(block) {
const cols = [...block.firstElementChild.children];
block.classList.add(`columns-${cols.length}-cols`);

instrumentMultipleVariantTable(block);
}
75 changes: 75 additions & 0 deletions blocks/spinner/spinner.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* Calibrating text on page load to qualify PSI score */

/* container */
.spinner {
position: absolute;
top: 50%;
right: 50%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
transform: translate(50%, -50%);
font-size: 4rem;
}

.spinner-letter {
/* font-size: 88px; */
font-weight: normal;
letter-spacing: 4px;
text-transform: uppercase;
animation-name: bounce;
animation-duration: 2s;
animation-iteration-count: infinite;
}

.spinner-letter:nth-child(2) {
animation-delay: .1s;
}

.spinner-letter:nth-child(3) {
animation-delay: .2s;
}

.spinner-letter:nth-child(4) {
animation-delay: .3s;
}

.spinner-letter:nth-child(5) {
animation-delay: .4s;
}

.spinner-letter:nth-child(6) {
animation-delay: .5s;
}

.spinner-letter:nth-child(7) {
animation-delay: .6s;
}

.spinner-letter:nth-child(8) {
animation-delay: .8s;
}

.spinner-letter:nth-child(9) {
animation-delay: 1s;
}

.spinner-letter:nth-child(10) {
animation-delay: 1.2s;
}

@keyframes bounce {
0% {
transform: translateY(0)
}

40% {
transform: translateY(-10px);
}

80%,
100% {
transform: translateY(0);
}
}
30 changes: 30 additions & 0 deletions blocks/spinner/spinner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Relocate Spinner HTML element at the body so that main
* content can be hidden (opacity:0) until calibration is in process
* @param block
*/
function splitIntoChildren(block) {
if (!block.children) {
return;
}

const spinnerTextArray = [...block.innerText.trim().concat('...')];

const parentDivElement = document.createElement('div');
parentDivElement.classList += block.classList;
document.querySelector('body').append(parentDivElement);

block.closest('.section').remove();

spinnerTextArray.forEach((letter) => {
const divElement = document.createElement('div');
divElement.classList.add('spinner-letter');
divElement.textContent = letter;
parentDivElement.append(divElement);
});
}

export default function decorate(block) {
block.classList.add('spinner');
splitIntoChildren(block);
}
25 changes: 25 additions & 0 deletions blocks/table/table.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.table > div {
display: flex;
flex-direction: row;
}

.table img {
width: 100%;
}

@media (min-width: 900px) {
.table > div {
display: flex;
align-items: center;
flex-direction: unset;
}

.table > div > div {
flex: 1;
margin-left: 32px;
}

.table > div > div:first-of-type {
margin-left: unset;
}
}
40 changes: 40 additions & 0 deletions blocks/table/table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {
getKey,
startsWithTemplateLiteral,
endsWithTemplateLiteral,
placeholderMap,
} from '../../scripts/menu-content-parser.js';

/**
* Decorate Table HTML with specific class selectors so that,
* it can be handled efficiently by the Menu Builder component
* @param block
*/
function instrumentSingleVariantTable(block) {
if (!block.children) {
return;
}

const blockImmediateChildren = [...block.children];

blockImmediateChildren.forEach((row) => {
const placeholdersDivs = [...row.querySelectorAll('div')].filter(
(div) => div.innerText.includes(startsWithTemplateLiteral)
&& div.innerText.includes(endsWithTemplateLiteral),
);
for (let i = 0; i < placeholdersDivs.length; i += 1) {
placeholdersDivs[i].style.display = 'none';
placeholderMap.set(
getKey(placeholdersDivs[i].textContent),
placeholdersDivs[i],
);
}
});
}

export default function decorate(block) {
const cols = [...block.firstElementChild.children];
block.classList.add(`columns-${cols.length}-cols`);

instrumentSingleVariantTable(block);
}
2 changes: 2 additions & 0 deletions head.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<script src="/scripts/menu-builder.js" type="module"></script>
<script src="/scripts/menu-content-parser.js" type="module"></script>
<script src="/scripts/lib-franklin.js" type="module"></script>
<script src="/scripts/scripts.js" type="module"></script>
<link rel="stylesheet" href="/styles/styles.css"/>
Expand Down
54 changes: 52 additions & 2 deletions scripts/delayed.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,57 @@
// eslint-disable-next-line import/no-cycle
import { sampleRUM } from './lib-franklin.js';
import { sampleRUM, isMenuBoardTemplate } from './lib-franklin.js';

const MENU_CAFE_FONT_SIZE_CACHE_KEY = 'menu-cafe-fontSize';

// Core Web Vitals RUM collection
sampleRUM('cwv');

// add more delayed functionality here
// FixMe: workaround to set the fluid/responsiveness typography

async function isScrollbarHidden(element) {
return element.offsetHeight < element.scrollHeight - 2; // threshhold = 2
}

/* function delayTimer(ms) {
return new Promise((res) => setTimeout(res, ms));
} */

/**
* Temporary Workaround: Increase the fontSize of the page until Scroll Bar appears
* @returns {Promise<void>}
*/
async function checkAndSetTypography() {
const htmlElement = document.querySelector('html');
const cachedFontSize = localStorage.getItem(MENU_CAFE_FONT_SIZE_CACHE_KEY);
if (cachedFontSize) {
htmlElement.style.fontSize = `${cachedFontSize}%`;
} else {
let fontSize = 73; // default fontSize for 1200x800 resolution
/* eslint-disable no-await-in-loop */
while (await isScrollbarHidden(htmlElement)) {
if (fontSize > 200) {
break;
}
fontSize += 1;
localStorage.setItem(MENU_CAFE_FONT_SIZE_CACHE_KEY, fontSize.toString());
htmlElement.style.fontSize = `${fontSize}%`;
window.dispatchEvent(new Event('resize'));
// await delayTimer(100); // add delay if needed on specific native platforms
}
}
htmlElement.querySelector('.beverages-menu').style.backgroundColor = '#601014'; // background-color: #601014;
htmlElement.querySelector('.food-menu').style.backgroundColor = '#000'; // background-color: #000;

htmlElement.querySelector('.spinner').style.display = 'none';

// remove the vertical scroll once menu is calibrated
htmlElement.style.overflow = 'hidden';
// unhide the main element once menu is ready
htmlElement.querySelector('main').style.opacity = '1';
}

setTimeout(() => {
if(isMenuBoardTemplate(document)) {
checkAndSetTypography();
}
}, 1);
21 changes: 21 additions & 0 deletions scripts/lib-franklin.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export function toCamelCase(name) {
}

const ICONS_CACHE = {};
const MENUBOARD_TEMPLATE = 'menuboard';
/**
* Replace icons with inline SVG and prefix with codeBasePath.
* @param {Element} [element] Element containing icons
Expand Down Expand Up @@ -439,6 +440,26 @@ export async function loadBlocks(main) {
}
}

export function getTemplateName(doc) {
let template = '';
const head = doc.querySelector('head');
for (const meta of [...head.querySelectorAll(':scope > meta')]) {
if(meta.getAttribute('name') === 'template') {
template = meta.getAttribute('content');
}
}
return template;
}

/**
* Checks if the doc is menuboard or not
* @param doc
* @returns <boolean>
*/
export function isMenuBoardTemplate(doc) {
return getTemplateName(doc) === MENUBOARD_TEMPLATE;
}

/**
* Returns a picture element with webp and fallbacks
* @param {string} src The image URL
Expand Down
Loading