const flagIcon = ``;
const homeIcon = ``;
const starIcon = ``;
const calendarIcon = ``;
const mIcon = ``;
const searchIcon = ``;
const chevronIcon = ``;
const Colors = {
white: '#fff',
offWhite: '#f1f1f1',
grayLight: '#e6e6e6',
gray: '#222',
grayDark: '#454545',
red: '#e21833',
redDark: '#951022',
yellow: '#FFD200',
green: '#70ebd6',
};
const Breakpoints = {
largeMobileMax: 767,
tabletMax: 1023,
desktopMin: 1024,
};
const ELEMENT_NAME = 'umd-utility-header';
const ALERTS_URL = 'https://umd.edu/api/alerts';
const SEARCH_URL = 'https://search.umd.edu';
const MOBILE_MENU_ID = 'umd-global-mobile-menu';
const SEARCH_FORM_ID = 'umd-global-search';
const ALERT_ELEMENT_ID = 'umd-global-alert';
const LOCK_CLASS = `umd-global-header-lock`;
const MOBILE_BUTTON_CLASS = `umd-global-header-mobile_button`;
const LOGO_CLASS = 'umd-global-header-logo';
const SR_ONLY_CLASS = 'umd-global-sr-only';
const ALERT_TIME_REF = 'umd-alert-time';
const ALERT_REF = 'umd-alert';
const ALERT_ID_REF = 'umd-alert-id';
const ANIMATION_IN_SPEED = 800;
const ANIMATION_OUT_SPEED = 400;
const isDesktop = () => window.innerWidth >= Breakpoints.desktopMin;
const template = document.createElement('template');
template.innerHTML = `
`;
const isValidUrl = (url) => {
try {
new URL(url);
}
catch (e) {
return false;
}
return true;
};
const makeLinkElement = ({ name, icon, url, }) => {
const tag = document.createElement('a');
tag.setAttribute('href', url);
tag.setAttribute('target', '_blank');
tag.setAttribute('rel', 'noopener noreferrer');
tag.innerHTML = `${icon} ${name}`;
return tag;
};
const toggleExpandElements = ({ expandElement, elements, button, }) => {
const isOpen = expandElement.getAttribute('aria-hidden') === 'false';
const elementToFocus = () => {
const formElement = elements.find((element) => element.nodeName === 'DIV');
const isFirstNodeAnchor = elements[0].nodeName === 'A';
if (!formElement)
return elements[0];
if (!isFirstNodeAnchor && formElement) {
const input = formElement.querySelector('input');
return input;
}
return elements[0];
};
const eventKeyDown = (event) => {
if (event.key === 'Esc' || event.keyCode == 27) {
close(true);
}
};
const eventKeyUp = (event) => {
const path = event.composedPath();
const currentElement = path[0];
if (!expandElement)
return;
if (event.key === 'Tab' || event.keyCode == 9) {
if (!expandElement.contains(currentElement)) {
close();
}
}
if (event.key === 'ArrowDown' || event.keyCode == 40) {
const nextElement = currentElement.nextElementSibling;
if (expandElement.contains(nextElement)) {
nextElement.focus();
}
}
if (event.key === 'ArrowUp' || event.keyCode == 38) {
const previousElement = currentElement.previousElementSibling;
if (expandElement.contains(previousElement)) {
previousElement.focus();
}
}
};
const eventClick = (event) => {
const globalHeaderElement = event.target;
if (globalHeaderElement.nodeName !== ELEMENT_NAME.toUpperCase()) {
close();
}
};
const open = () => {
const focusElement = elementToFocus();
expandElement.style.display =
expandElement.nodeName === 'FORM' ? 'block' : 'flex';
setTimeout(() => {
const size = elements.reduce((accumulator, currentValue) => {
return accumulator + currentValue.offsetHeight;
}, 0);
expandElement.setAttribute('aria-hidden', 'false');
expandElement.style.height = `${size}px`;
focusElement.focus();
window.addEventListener('keydown', eventKeyDown);
window.addEventListener('keyup', eventKeyUp);
window.addEventListener('click', eventClick);
}, 100);
};
const close = (focus = false) => {
expandElement.style.height = `0`;
setTimeout(() => {
expandElement.style.display = 'none';
expandElement.setAttribute('aria-hidden', 'true');
if (focus) {
button.focus();
}
window.removeEventListener('keydown', eventKeyDown);
window.removeEventListener('keyup', eventKeyUp);
window.removeEventListener('click', eventClick);
}, ANIMATION_OUT_SPEED + 100);
};
isOpen ? close() : open();
};
const makeMobileMenuButton = ({ expandElement, }) => {
const button = document.createElement('button');
const elements = Array.from(expandElement.querySelectorAll('a, form'));
button.innerHTML = `${chevronIcon}`;
button.setAttribute('type', 'button');
button.setAttribute('aria-label', 'toggle mobile menu');
button.setAttribute('aria-controls', MOBILE_MENU_ID);
button.classList.add(MOBILE_BUTTON_CLASS);
button.addEventListener('click', () => {
toggleExpandElements({ expandElement, elements, button });
});
return button;
};
const makeSearchFormButton = ({ expandElement, }) => {
const button = document.createElement('button');
const elements = Array.from(expandElement.querySelectorAll('div'));
button.setAttribute('aria-label', 'enable the search form');
button.setAttribute('type', 'button');
button.innerHTML = `${searchIcon}`;
button.setAttribute('aria-controls', SEARCH_FORM_ID);
button.addEventListener('click', () => {
toggleExpandElements({ expandElement, elements, button });
});
return button;
};
const makeLogoElement = () => {
const logo = document.createElement('a');
logo.innerHTML = 'University of Maryland';
logo.setAttribute('href', 'https://umd.edu');
logo.setAttribute('target', '_blank');
logo.setAttribute('rel', 'noopener noreferrer');
logo.classList.add(LOGO_CLASS);
return logo;
};
const makeFormElement = () => {
const form = document.createElement('form');
const wrapper = document.createElement('div');
const inputTextLabel = document.createElement('label');
const inputText = document.createElement('input');
const inputSubmit = document.createElement('input');
inputTextLabel.innerHTML = 'Search input';
inputTextLabel.setAttribute('for', 'input-text');
inputTextLabel.classList.add(SR_ONLY_CLASS);
inputText.setAttribute('type', 'text');
inputText.setAttribute('id', 'input-text');
inputText.setAttribute('name', 'query');
inputText.setAttribute('placeholder', 'Search for People, places and things');
inputText.setAttribute('required', '');
inputSubmit.setAttribute('type', 'submit');
inputSubmit.value = 'Submit';
form.setAttribute('id', SEARCH_FORM_ID);
form.setAttribute('aria-hidden', isDesktop().toString());
wrapper.appendChild(inputTextLabel);
wrapper.appendChild(inputText);
wrapper.appendChild(inputSubmit);
form.appendChild(wrapper);
return form;
};
const checkAlertTime = () => {
const alertDate = window.localStorage.getItem(ALERT_TIME_REF);
const currentDate = new Date();
const futureDate = new Date(currentDate.getTime() + 1000 * 60);
const shouldCheckMessage = (alertDate) => {
const storedDate = new Date(Date.parse(alertDate));
if (storedDate instanceof Date && currentDate > storedDate) {
localStorage.setItem(ALERT_TIME_REF, futureDate.toString());
return true;
}
return false;
};
if (!alertDate) {
localStorage.setItem(ALERT_TIME_REF, futureDate.toString());
return true;
}
return shouldCheckMessage(alertDate);
};
const setAlertStorage = (alert) => {
window.localStorage.setItem(ALERT_REF, JSON.stringify(alert));
};
const getAlertStorage = () => window.localStorage.getItem(ALERT_REF);
const shouldAlertHide = ({ alert_id }) => window.localStorage.getItem(ALERT_ID_REF) === alert_id;
const makeAlert = (data) => {
const wrapper = document.createElement('div');
const lock = document.createElement('div');
const titleElement = document.createElement('p');
const textElement = document.createElement('div');
const button = document.createElement('button');
wrapper.setAttribute('data-type', data.alert_type);
wrapper.setAttribute('id', ALERT_ELEMENT_ID);
lock.classList.add(LOCK_CLASS);
titleElement.classList.add('alert-title');
titleElement.innerHTML = data.alert_title;
textElement.innerHTML = data.alert_message;
button.setAttribute('aria-label', 'remove alert');
button.addEventListener('click', () => {
wrapper.style.height = `${wrapper.offsetHeight}px`;
window.localStorage.setItem(ALERT_ID_REF, data.alert_id);
setTimeout(() => {
wrapper.style.height = '0px';
}, 100);
setTimeout(() => {
wrapper.remove();
}, ANIMATION_IN_SPEED + 100);
});
lock.appendChild(button);
lock.appendChild(titleElement);
lock.appendChild(textElement);
wrapper.appendChild(lock);
return wrapper;
};
export default class UtilityHeaderElement extends HTMLElement {
constructor() {
super();
this._containerElement = document.createElement('div');
this._menuContainerElement = document.createElement('div');
this._logoElement = makeLogoElement();
this._formElement = makeFormElement();
this._menuElements = [];
this._paddingAmount = '20';
this._searchType = null;
this._isSearchSet = false;
this._isEventsSet = false;
this._isNewsSet = false;
this._isSchoolsSet = false;
this._isAdmissionsSet = false;
this._isGiftSet = false;
this._shadow = this.attachShadow({ mode: 'open' });
this._shadow.appendChild(template.content.cloneNode(true));
}
static get observedAttributes() {
return [
'padding',
'size',
'search',
'events',
'news',
'schools',
'admissions',
'gift',
];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'padding' && newValue) {
this._paddingAmount = newValue;
this.paddingContainer({ padding: this._paddingAmount });
}
if (name === 'size' && newValue) {
const width = newValue === 'full' ? '100%' : newValue;
this.sizeContainer({ width });
}
if (name === 'admissions' && !this._isAdmissionsSet) {
this._isAdmissionsSet = true;
const element = makeLinkElement({
name: 'Admissions',
url: 'https://umd.edu/admissions',
icon: flagIcon,
});
this._menuElements.push({
order: 1,
element,
});
}
if (name === 'schools' && !this._isSchoolsSet) {
this._isSchoolsSet = true;
const element = makeLinkElement({
name: 'Colleges & Schools',
url: 'https://umd.edu/colleges-and-schools',
icon: homeIcon,
});
this._menuElements.push({
order: 2,
element,
});
}
if (name === 'news' && !this._isNewsSet) {
this._isNewsSet = true;
const element = makeLinkElement({
name: 'News',
url: 'https://today.umd.edu/',
icon: starIcon,
});
this._menuElements.push({
order: 3,
element,
});
}
if (name === 'events' && !this._isEventsSet) {
this._isEventsSet = true;
const element = makeLinkElement({
name: 'Events',
url: 'https://calendar.umd.edu',
icon: calendarIcon,
});
this._menuElements.push({
order: 4,
element,
});
}
if (name === 'gift' && !this._isGiftSet) {
this._isGiftSet = true;
const getURL = () => {
const defaultURL = 'https://giving.umd.edu/giving';
if (!newValue)
return defaultURL;
const validURL = newValue ? isValidUrl(newValue) : null;
return validURL ? newValue : defaultURL;
};
const element = makeLinkElement({
name: 'Make a Gift',
url: getURL(),
icon: mIcon,
});
this._menuElements.push({
order: 5,
element,
});
}
if (name === 'search' && !this._isSearchSet) {
const button = makeSearchFormButton({
expandElement: this._formElement,
});
this._isSearchSet = true;
if (newValue) {
this._searchType = newValue;
}
this._menuElements.push({
order: 6,
element: button,
});
}
}
connectedCallback() {
const containsMenuItems = this._menuElements.length > 0;
const resizeElements = {};
this._containerElement.classList.add(LOCK_CLASS);
this._containerElement.appendChild(this._logoElement);
if (containsMenuItems) {
this.addMenuItems();
this._containerElement.appendChild(makeMobileMenuButton({
expandElement: this._menuContainerElement,
}));
this._menuContainerElement.setAttribute('id', MOBILE_MENU_ID);
this._menuContainerElement.setAttribute('aria-hidden', (!isDesktop()).toString());
this._containerElement.appendChild(this._menuContainerElement);
resizeElements['menu'] = this._menuContainerElement;
}
else {
this._containerElement.style.display = 'flex';
this._containerElement.style.justifyContent = 'center';
}
if (this._isSearchSet) {
resizeElements['form'] = this._formElement;
this.searchSubmit();
}
if (Object.keys(resizeElements).length > 0) {
window.addEventListener('resize', () => {
this.resizeEvent(resizeElements);
});
}
this.alert();
this._shadow.appendChild(this._containerElement);
}
resizeEvent({ menu, form, }) {
if (menu) {
menu.setAttribute('aria-hidden', (!isDesktop()).toString());
}
if (form) {
form.setAttribute('aria-hidden', isDesktop().toString());
}
}
paddingContainer({ padding }) {
this._containerElement.style.paddingLeft = `${padding}px`;
}
sizeContainer({ width }) {
this._containerElement.style.maxWidth = `${width}`;
}
searchSubmit() {
this._formElement.addEventListener('submit', (event) => {
event.preventDefault();
const input = this._formElement.querySelector('input[type="text"]');
let searchString = `#gsc.tab=0&gsc`;
if (this._searchType === 'domain') {
searchString += `.q=site:${window.location.hostname} ${input.value}`;
}
else {
searchString += `.q=${input.value}`;
}
searchString += `&gsc.sort=`;
window.open(`${SEARCH_URL}${encodeURI(searchString)}`, '_blank');
});
}
addMenuItems() {
const items = this._menuElements.sort((a, b) => a.order > b.order ? 1 : -1);
const setPadding = ({ element }) => {
const mobileButton = this._shadow.querySelector(MOBILE_BUTTON_CLASS);
const padding = parseInt(this._paddingAmount);
const elementPadding = padding > 20 ? 20 : padding;
element.style.paddingRight = `${elementPadding}px`;
if (mobileButton)
mobileButton.style.paddingRight = `${elementPadding}px`;
if (padding > 20) {
this._containerElement.style.paddingRight = `${padding - 20}px`;
}
};
items.forEach(({ element }, i) => {
if (i === items.length - 1)
setPadding({ element });
this._menuContainerElement.appendChild(element);
});
if (this._isSearchSet) {
this._menuContainerElement.appendChild(this._formElement);
}
}
async alert() {
const shouldCheck = checkAlertTime();
const setMarkup = (data) => {
const domAlert = makeAlert(data);
const styleNode = this._shadow.querySelector('style');
const containerNode = styleNode.nextElementSibling;
if (shouldAlertHide({ alert_id: data.alert_id }))
return;
if (containerNode) {
this._shadow.insertBefore(domAlert, containerNode);
}
else {
this._shadow.appendChild(domAlert);
}
};
const fetchAlerts = async () => {
try {
const params = {
method: 'GET',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
};
const response = await fetch(ALERTS_URL, params);
return response.json();
}
catch (ex) {
throw ex;
}
};
if (shouldCheck) {
const { data = [] } = await fetchAlerts();
if (data.length > 0) {
if (data[0] == '')
return;
setMarkup(data[0]);
setAlertStorage(data[0]);
}
else {
const alertElement = this._shadow.querySelector(`#${ALERT_ELEMENT_ID}`);
window.localStorage.setItem(ALERT_REF, '');
window.localStorage.removeItem(ALERT_REF);
if (alertElement) {
alertElement.remove();
}
}
}
else {
const data = getAlertStorage();
if (data) {
setMarkup(JSON.parse(data));
}
}
}
}
if (!window.customElements.get(ELEMENT_NAME)) {
window.UtilityHeaderElement = UtilityHeaderElement;
window.customElements.define(ELEMENT_NAME, UtilityHeaderElement);
}
//# sourceMappingURL=index.js.map