diff --git a/src/main.js b/src/main.js index 67120ff7526ff5b879532dab859656ae8cdcabe7..e5d08f81eb058ced00873203a274ef73aab2cfd5 100644 --- a/src/main.js +++ b/src/main.js @@ -1,107 +1,111 @@ import * as helpers from "./modules/helpers.js"; const navigation = { - label: "Menu", - path: "/menu", - command: "menu", - depth: 0, - submenu: { - call: { - label: "Call", - path: "/menu/call", - command: "call", - depth: 1, - submenu: { - emergency: { - label: "Emergency", - command: "emergency", - path: "/menu/call/emergency", - depth: 2, - message: "Calling Emergency", - }, - contact1: { - label: "Flute Inc.", - command: "contact A", - path: "/menu/call/contact1", - depth: 2, - message: "Calling Flute Inc.", - }, - contact2: { - label: "Brays AG", - command: "contact B", - path: "/menu/call/contact2", - depth: 2, - message: "Calling Brays AG", - }, - }, - }, - check: { - label: "Check", - path: "/menu/check", - command: "check", - depth: 1, - submenu: { - daily: { - label: "Daily", - command: "daily", - path: "/menu/check/daily", - depth: 2, - message: "Displaying Daily Checklist", - }, - weekly: { - label: "Weekly", - command: "weekly", - path: "/menu/check/weekly", - depth: 2, - message: "Displaying Weekly Checklist", - }, - monthly: { - label: "Monthly", - command: "monthly", - path: "/menu/check/monthly", - depth: 2, - message: "Displaying Monthly Checklist", - }, - }, - }, - apps: { - label: "Apps", - path: "/menu/apps", - command: "apps", - depth: 1, - submenu: { - record: { - label: "Record", - command: "record", - path: "/menu/apps/record", - depth: 2, - message: "Opening Recording App", - }, - breakout: { - label: "Breakout", - command: "breakout", - path: "/menu/apps/breakout", - depth: 2, - message: "Opening Breakout App", - }, - statistics: { - label: "Statistics", - command: "statistics", - path: "/menu/apps/statistics", - depth: 2, - message: "Opening Statistics App", + home: { + label: "Home", + path: "/", + command: "home", + depth: 0, + submenu: { + menu: { + label: "Menu", + path: "/menu", + command: "menu", + depth: 1, + submenu: { + call: { + label: "Call", + path: "/menu/call", + command: "call", + depth: 2, + submenu: { + emergency: { + label: "Emergency", + command: "emergency", + path: "/menu/call/emergency", + depth: 3, + message: "Calling Emergency", + }, + contact1: { + label: "Flute Inc.", + command: "contact A", + path: "/menu/call/contact1", + depth: 3, + message: "Calling Flute Inc.", + }, + contact2: { + label: "Brays AG", + command: "contact B", + path: "/menu/call/contact2", + depth: 3, + message: "Calling Brays AG", + }, + }, + }, + check: { + label: "Check", + path: "/menu/check", + command: "check", + depth: 2, + submenu: { + daily: { + label: "Daily", + command: "daily", + path: "/menu/check/daily", + depth: 3, + message: "Displaying Daily Checklist", + }, + weekly: { + label: "Weekly", + command: "weekly", + path: "/menu/check/weekly", + depth: 3, + message: "Displaying Weekly Checklist", + }, + monthly: { + label: "Monthly", + command: "monthly", + path: "/menu/check/monthly", + depth: 3, + message: "Displaying Monthly Checklist", + }, + }, + }, + apps: { + label: "Apps", + path: "/menu/apps", + command: "apps", + depth: 2, + submenu: { + record: { + label: "Record", + command: "record", + path: "/menu/apps/record", + depth: 3, + message: "Opening Recording App", + }, + breakout: { + label: "Breakout", + command: "breakout", + path: "/menu/apps/breakout", + depth: 3, + message: "Opening Breakout App", + }, + statistics: { + label: "Statistics", + command: "statistics", + path: "/menu/apps/statistics", + depth: 3, + message: "Opening Statistics App", + }, + }, + }, }, }, }, }, }; -const backItem = { - label: "Back", - path: "../", - command: "back", -}; - // init application function init() { // build navigation @@ -110,30 +114,26 @@ function init() { navigationEl.id = "navigation"; const listEl = document.createElement("ul"); navigationEl.appendChild(listEl); - appEl.replaceChildren(navigationEl); + appEl.appendChild(navigationEl); - resetNavigationEl(); -} + // navigate to home + navigateTo("/"); -function resetNavigationEl() { - const navigationEl = document.getElementById("navigation"); - const listEl = navigationEl.querySelector("ul"); - let itemEl = buildNavigationItemEl(navigation); - listEl.replaceChildren(itemEl); + // add two button controls for menu + document.addEventListener("keydown", onKeyDown); } -// build navigation item -function buildNavigationItemEl(item) { - const itemEl = document.createElement("li"); - const linkEl = document.createElement("a"); - linkEl.href = item.path; - linkEl.innerHTML = item.label; - linkEl.dataset.command = item.command; - itemEl.appendChild(linkEl); - - linkEl.addEventListener("click", onMouseClick); +// get current navigation items +function getCurrentNavigationItems() { + return listItems; +} - return itemEl; +// on keydown event +function onKeyDown(event) { + event.preventDefault(); + if (event.code === "Tab") { + selectNextNavigationItem(); + } } // on menu item mouseclick @@ -145,24 +145,21 @@ function onMouseClick(event) { // navigate to page function navigateTo(path) { - if (path === "/") resetNavigationEl(); + let navObj = helpers.findNestedObject(navigation, "path", path); + + // is menu + if (navObj.hasOwnProperty("submenu")) updateNavigation(navObj); else { - let navObj = helpers.findNestedObject(navigation, "path", path); - - // is menu - if (navObj.hasOwnProperty("submenu")) updateNavigation(navObj); - else { - //is final page - let appEl = document.getElementById("app"); - let messageEl = document.createElement("div"); - messageEl.innerHTML = navObj.message; - appEl.replaceChildren(messageEl); - - let exitEl = document.createElement("a"); - exitEl.href = "/"; - exitEl.innerHTML = "Exit"; - appEl.appendChild(exitEl); - } + //is final page + let appEl = document.getElementById("app"); + let messageEl = document.createElement("div"); + messageEl.innerHTML = navObj.message; + appEl.replaceChildren(messageEl); + + let exitEl = document.createElement("a"); + exitEl.href = "/"; + exitEl.innerHTML = "Exit"; + appEl.appendChild(exitEl); } } @@ -171,32 +168,82 @@ function updateNavigation(object) { // update navigation const listEl = document.createElement("ul"); - // is navigation + // add navigation items for (let key in object.submenu) { let itemEl = buildNavigationItemEl(object.submenu[key]); listEl.appendChild(itemEl); } // add "back" button - let backItemEl; - if (object.depth === 0) { - backItemEl = buildNavigationItemEl({ - label: "Close", - path: "/", - command: "close", - }); - } else if (object.depth === 1) { - backItemEl = buildNavigationItemEl({ - label: "Back", - path: "/menu", - command: "back", - }); + if (object.depth === 1 || object.depth === 2) { + let backItemEl; + if (object.depth === 1) + backItemEl = buildNavigationItemEl({ + label: "Close", + path: "/", + command: "close", + }); + else if (object.depth === 2) + backItemEl = buildNavigationItemEl({ + label: "Back", + path: "/menu", + command: "back", + }); + + listEl.appendChild(backItemEl); } - listEl.appendChild(backItemEl); - const navigationEl = document.getElementById("navigation"); navigationEl.replaceChildren(listEl); + + selectNavigationItem(1); + + // build navigation item + function buildNavigationItemEl(item) { + const itemEl = document.createElement("li"); + itemEl.className = "link"; + const linkEl = document.createElement("a"); + linkEl.href = item.path; + linkEl.innerHTML = item.label; + linkEl.dataset.command = item.command; + itemEl.appendChild(linkEl); + + if (item.label.toLowerCase() !== item.command.toLowerCase()) { + const commandEl = document.createElement("div"); + commandEl.className = "command"; + commandEl.innerHTML = item.command; + itemEl.appendChild(commandEl); + } + + linkEl.addEventListener("click", onMouseClick); + + return itemEl; + } +} + +// select specific navigation item +function selectNavigationItem(n) { + // unselect all items + const navigationList = document.querySelectorAll("#navigation li"); + for (let item of navigationList) delete item.dataset.selected; + + // select requested element + const navigationItem = document.querySelector( + `#navigation > ul > li:nth-child(${n})` + ); + navigationItem.dataset.selected = ""; +} + +// select next navigation item +function selectNextNavigationItem() { + // get currently selected element + let currentItem = document.querySelector( + "#navigation > ul > li[data-selected]" + ); + if (currentItem.nextSibling) { + delete currentItem.dataset.selected; + currentItem.nextSibling.dataset.selected = ""; + } else selectNavigationItem(1); } init(); diff --git a/src/styles/config.css b/src/styles/config.css index 6fed1823715b553eb1c1f9a657a9498e22e0a026..dd8507e45a329397ddc4852b9b7ab84f11c5ef61 100644 --- a/src/styles/config.css +++ b/src/styles/config.css @@ -28,4 +28,5 @@ https://github.com/less/less.js/issues/3537 */ :root { --color-white: hsl(0 0% 100%); --color-black: hsl(0 0% 0%); + --color-grey-01: hsl(0 0% 50%); } diff --git a/src/styles/main.css b/src/styles/main.css index 8f77ff8ed8d761b9182bd5553d57a3c8eb5d9026..3bf75907d2ff0b225839e080de2774ed4dfce39b 100644 --- a/src/styles/main.css +++ b/src/styles/main.css @@ -14,6 +14,17 @@ a { color: inherit; text-decoration: none; + border-bottom: solid 0.1em transparent; +} +.link .command { + font-size: 0.5em; + line-height: 1em; + font-style: italic; + color: var(--color-grey-01); +} +.link:hover a, +.link[data-selected] a { + border-color: var(--color-white); } #log { position: absolute; diff --git a/src/styles/main.less b/src/styles/main.less index 9aaeb2f799c04c1416b372fffb95a9259bcf1fca..afff171a85358d84b0c355ace31b1e23040f69d1 100644 --- a/src/styles/main.less +++ b/src/styles/main.less @@ -16,6 +16,23 @@ a { color: inherit; text-decoration: none; + border-bottom: solid 0.1em transparent; +} + +.link { + .command { + font-size: 0.5em; + line-height: 1em; + font-style: italic; + color: var(--color-grey-01); + } + + &:hover, + &[data-selected] { + a { + border-color: var(--color-white); + } + } } #log {