diff --git a/app.js b/app.js index 31f4937..eaa3cad 100644 --- a/app.js +++ b/app.js @@ -1,155 +1,122 @@ -const body = document.body; -const modal = document.querySelector('.modal'); +const navDialogEl = document.querySelector(".dialog"); +const dialogOverlay = document.querySelector(".dialog-overlay"); -const openModal = document.querySelectorAll('.modal-open'); -const closeModal = document.querySelectorAll('.modal-close'); -const overlay = document.querySelector('.modal-overlay'); - -const toggleModal = function() { - modal.classList.toggle('opacity-0'); - modal.classList.toggle('pointer-events-none'); - body.classList.toggle('modal-active'); -}; - -for (let i = 0; i < openModal.length; i++) { - openModal[i].addEventListener('click', function(event) { - event.preventDefault(); - toggleModal(); - }); -}; - -for (let i = 0; i < closeModal.length; i++) { - closeModal[i].addEventListener('click', toggleModal); -} - -overlay.addEventListener('click', toggleModal); - -document.onkeydown = function(evt) { - evt = evt || window.event; - let isEscape = false; - - if ("key" in evt) { - isEscape = (evt.key === "Escape" || evt.key === "Esc"); - } else { - isEscape = (evt.keyCode === 27); - } - if (isEscape && document.body.classList.contains('modal-active')) { - toggleModal(); - } -}; +const myDialog = new Dialog(navDialogEl, dialogOverlay); +myDialog.addEventListeners(".open-dialog", ".close-dialog"); +const menuButton = document.getElementById("menu-button"); +const menuContainer = document.getElementById("menu-container"); -const menuButton = document.getElementById('menu-button'); -const menuContainer = document.getElementById('menu-container'); - -menuButton.addEventListener('click', function(event) { - menuContainer.classList.toggle('hidden'); +menuButton.addEventListener("click", function(event) { + menuContainer.classList.toggle("hidden"); }); - -const computersButton = document.querySelectorAll('.computers-button'); -const computersContainer = document.getElementById('computers-container'); -const computersCards = document.getElementById('computers-cards'); -const computersGrid = document.getElementById('computers-grid'); -const idevicesButton = document.querySelectorAll('.idevices-button'); -const idevicesContainer = document.getElementById('idevices-container'); -const idevicesCards = document.getElementById('idevices-cards'); -const idevicesGrid = document.getElementById('idevices-grid'); -const collectionLabel = document.getElementById('collection-label'); -const uiButtons = document.querySelectorAll('.computers-button, .idevices-button'); -const modeButtons = document.querySelectorAll('.mode-button'); +const computersButton = document.querySelectorAll(".computers-button"); +const computersContainer = document.getElementById("computers-container"); +const computersCards = document.getElementById("computers-cards"); +const computersGrid = document.getElementById("computers-grid"); +const idevicesButton = document.querySelectorAll(".idevices-button"); +const idevicesContainer = document.getElementById("idevices-container"); +const idevicesCards = document.getElementById("idevices-cards"); +const idevicesGrid = document.getElementById("idevices-grid"); +const collectionLabel = document.getElementById("collection-label"); +const uiButtons = document.querySelectorAll( + ".computers-button, .idevices-button" +); +const modeButtons = document.querySelectorAll(".mode-button"); const showCollection = function(collection) { let items = null; let label = null; - if (collection === 'computers') { - items = document.querySelectorAll('#computers-container .card'); - label = 'Computers (' + items.length + ')'; - idevicesContainer.classList.add('hidden'); - computersContainer.classList.remove('hidden'); + if (collection === "computers") { + items = document.querySelectorAll("#computers-container .card"); + label = "Computers (" + items.length + ")"; + idevicesContainer.classList.add("hidden"); + computersContainer.classList.remove("hidden"); } else { - items = document.querySelectorAll('#idevices-container .card'); - label = 'iDevices (' + items.length + ')'; - idevicesContainer.classList.remove('hidden'); - computersContainer.classList.add('hidden'); + items = document.querySelectorAll("#idevices-container .card"); + label = "iDevices (" + items.length + ")"; + idevicesContainer.classList.remove("hidden"); + computersContainer.classList.add("hidden"); } uiButtons.forEach(function(element) { const dataCollection = element.dataset.collection; if (dataCollection === collection) { - element.classList.remove('text-gray-800'); - element.classList.add('text-purple-600'); + element.classList.remove("text-gray-800"); + element.classList.add("text-purple-800"); } else { - element.classList.add('text-gray-800'); - element.classList.remove('text-purple-600'); + element.classList.add("text-gray-800"); + element.classList.remove("text-purple-800"); } }); collectionLabel.innerHTML = label; const params = new URLSearchParams(location.search); - params.set('collection', collection); - window.history.replaceState({}, '', `${location.pathname}?${params}`); + params.set("collection", collection); + window.history.replaceState({}, "", `${location.pathname}?${params}`); // TODO: replaceState is not updating the title document.title = `${label} - Leo's Collection`; // Mobile: close menu after click - if (!menuContainer.classList.contains('hidden')) { - menuContainer.classList.add('hidden'); + if (!menuContainer.classList.contains("hidden")) { + menuContainer.classList.add("hidden"); } -} +}; uiButtons.forEach(function(element) { - element.addEventListener('click', function(event) { + element.addEventListener("click", function(event) { const collection = element.dataset.collection; showCollection(collection); + + event.preventDefault(); }); }); const toggleMode = function(mode) { - if (mode === 'grid') { - computersCards.classList.add('hidden'); - idevicesCards.classList.add('hidden'); - computersGrid.classList.remove('hidden'); - idevicesGrid.classList.remove('hidden'); + if (mode === "grid") { + computersCards.classList.add("hidden"); + idevicesCards.classList.add("hidden"); + computersGrid.classList.remove("hidden"); + idevicesGrid.classList.remove("hidden"); } else { - computersCards.classList.remove('hidden'); - idevicesCards.classList.remove('hidden'); - computersGrid.classList.add('hidden'); - idevicesGrid.classList.add('hidden'); + computersCards.classList.remove("hidden"); + idevicesCards.classList.remove("hidden"); + computersGrid.classList.add("hidden"); + idevicesGrid.classList.add("hidden"); } modeButtons.forEach(function(button) { const dataMode = button.dataset.mode; if (dataMode === mode) { - button.classList.remove('text-gray-800'); - button.classList.add('text-purple-600'); + button.classList.remove("text-gray-800"); + button.classList.add("text-purple-800"); } else { - button.classList.add('text-gray-800'); - button.classList.remove('text-purple-600'); + button.classList.add("text-gray-800"); + button.classList.remove("text-purple-800"); } }); const params = new URLSearchParams(location.search); - params.set('mode', mode); - window.history.replaceState({}, '', `${location.pathname}?${params}`); -} + params.set("mode", mode); + window.history.replaceState({}, "", `${location.pathname}?${params}`); +}; modeButtons.forEach(function(element) { - element.addEventListener('click', function(event) { + element.addEventListener("click", function(event) { const mode = element.dataset.mode; toggleMode(mode); }); }); - const params = new URLSearchParams(location.search); -if (params.get('collection')) { - showCollection(params.get('collection')); +if (params.get("collection")) { + showCollection(params.get("collection")); } -if (params.get('mode')) { - toggleMode(params.get('mode')); +if (params.get("mode")) { + toggleMode(params.get("mode")); } diff --git a/dialog.js b/dialog.js new file mode 100644 index 0000000..f5ace34 --- /dev/null +++ b/dialog.js @@ -0,0 +1,108 @@ +// Acessible dialog by Ire Aderinokun +// https://bitsofco.de/accessible-modal-dialog/ + +function Dialog(dialogEl, overlayEl) { + this.dialogEl = dialogEl; + this.overlayEl = overlayEl; + this.focusedElBeforeOpen; + + var focusableEls = this.dialogEl.querySelectorAll( + 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex="0"]' + ); + this.focusableEls = Array.prototype.slice.call(focusableEls); + + this.firstFocusableEl = this.focusableEls[0]; + this.lastFocusableEl = this.focusableEls[this.focusableEls.length - 1]; + + this.close(); // Reset +} + +Dialog.prototype.open = function() { + var Dialog = this; + + this.dialogEl.removeAttribute("aria-hidden"); + this.dialogEl.classList.remove("hidden"); + this.overlayEl.removeAttribute("aria-hidden"); + this.overlayEl.classList.remove("hidden"); + document.body.classList.add("overflow-hidden"); + + this.focusedElBeforeOpen = document.activeElement; + + this.dialogEl.addEventListener("keydown", function(e) { + Dialog._handleKeyDown(e); + }); + + this.overlayEl.addEventListener("click", function() { + Dialog.close(); + }); + + this.firstFocusableEl.focus(); +}; + +Dialog.prototype.close = function() { + this.dialogEl.setAttribute("aria-hidden", true); + this.dialogEl.classList.add("hidden"); + this.overlayEl.setAttribute("aria-hidden", true); + this.overlayEl.classList.add("hidden"); + document.body.classList.remove("overflow-hidden"); + + if (this.focusedElBeforeOpen) { + this.focusedElBeforeOpen.focus(); + } +}; + +Dialog.prototype._handleKeyDown = function(e) { + var Dialog = this; + var KEY_TAB = 9; + var KEY_ESC = 27; + + function handleBackwardTab() { + if (document.activeElement === Dialog.firstFocusableEl) { + e.preventDefault(); + Dialog.lastFocusableEl.focus(); + } + } + function handleForwardTab() { + if (document.activeElement === Dialog.lastFocusableEl) { + e.preventDefault(); + Dialog.firstFocusableEl.focus(); + } + } + + switch (e.keyCode) { + case KEY_TAB: + if (Dialog.focusableEls.length === 1) { + e.preventDefault(); + break; + } + if (e.shiftKey) { + handleBackwardTab(); + } else { + handleForwardTab(); + } + break; + case KEY_ESC: + Dialog.close(); + break; + default: + break; + } +}; + +Dialog.prototype.addEventListeners = function(openDialogSel, closeDialogSel) { + var Dialog = this; + + var openDialogEls = document.querySelectorAll(openDialogSel); + for (var i = 0; i < openDialogEls.length; i++) { + openDialogEls[i].addEventListener("click", function() { + Dialog.open(); + }); + } + + var closeDialogEls = document.querySelectorAll(closeDialogSel); + for (var i = 0; i < closeDialogEls.length; i++) { + closeDialogEls[i].addEventListener("click", function() { + Dialog.close(); + }); + } +}; diff --git a/index.html b/index.html index 4607bb4..f34025e 100644 --- a/index.html +++ b/index.html @@ -26,38 +26,27 @@ - +
-
-
- +
+

+ Leo's Collection -

- - + - + - -
- -
@@ -65,16 +54,16 @@
-

Computers

+

Computers

- -
@@ -83,29 +72,32 @@
- + {{computer}}'s photo
-

{{computer}}

-

+

{{computer}}

+

{{notes}}

- +

{{hardware}}

-
- Bought at
+
+ Bought at
{{bought_at}}
- History + + History + +
@@ -114,23 +106,23 @@
-