From 9c142581f1520a0134f3888b8e7359e5ee0d91f5 Mon Sep 17 00:00:00 2001 From: Arkerthan <arkerthan@gmail.com> Date: Sun, 17 May 2020 16:26:17 +0200 Subject: [PATCH] add proper styling to quick menu --- src/003-assets/CSS/quicklinks.css | 51 ++++++++++++ src/gui/quicklinks.js | 133 ++++++++++++++++++++---------- 2 files changed, 142 insertions(+), 42 deletions(-) create mode 100644 src/003-assets/CSS/quicklinks.css diff --git a/src/003-assets/CSS/quicklinks.css b/src/003-assets/CSS/quicklinks.css new file mode 100644 index 00000000000..20050739652 --- /dev/null +++ b/src/003-assets/CSS/quicklinks.css @@ -0,0 +1,51 @@ +div.quick-links { + margin-bottom: 2px; /* the last menu link has a bottom outline, make enough space for it */ +} + +div.quick-links div.toggle { + position: relative; /* so ::before works in relation to this element */ + background-color: #4c4c4c; +} + +div.quick-links div.toggle:hover { + background-color: #7f7f7f; +} + +div.quick-links div.toggle::before { + font-family: "tme-fa-icons"; + position: absolute; + left: 5px; + content: "\e818"; +} + +div.quick-links div.collapsed div.toggle::before { + content: "\e81a"; +} + +div.quick-links div.content { + margin: 0 5px; +} + +div.quick-links div.collapsed div.content { + display: none +} + +div.quick-links div.menu-link { + background-color: #2b2b2b; + border: solid #3c3c3c; + border-width: 0 2px; + margin: 0 2px; + /* we cannot detect if an element has something after it, so we just add a shadow to every element. Only for the + last element the shadow is not hidden behind another element. */ + box-shadow: 0 2px 0 0 #3c3c3c; +} + +/* give the very first link an upper border */ +div.quick-links > div.menu-link:first-child { + border-top-width: 2px; +} + +/* give the link directly after an opened toggle an upper border */ +div.quick-links div:not(.menu-link):not(.collapsed) + div.menu-link { + border-top-width: 2px; +} diff --git a/src/gui/quicklinks.js b/src/gui/quicklinks.js index 64880cd344d..a7cc8614f1e 100644 --- a/src/gui/quicklinks.js +++ b/src/gui/quicklinks.js @@ -10,7 +10,7 @@ App.UI.quickMenu = (function() { // if property name is a passage name, then it's a link, otherwise only text. // Only two values are allowed: true or an object following the same rules - const layout = { + const layout = addOtherCategory({ Main: true, Manage: { "Manage Personal Affairs": true, @@ -25,8 +25,22 @@ App.UI.quickMenu = (function() { Schoolroom: true, "Servants' Quarters": true, Spa: true + }, + deepTest: { + Options: true, + deeper: { + "Summary Options": true, + "Description Options": true + }, + "Costs Budget": true, } - }; + }); + + /** + * The DOM element of name of the currently played passage + * @type {HTMLElement} + */ + let currentPassageDOM = null; // setup hotkeys list, upper/lower case is important! const hotkeys = cleanHotkeys({ @@ -99,23 +113,16 @@ App.UI.quickMenu = (function() { } // quick menu - // we need to modify jumpTo, but not the original - const jumpToCopy = jumpTo.slice(); - fragment.append(generateQuickMenu(jumpToCopy, layout, 0)); - - // put uncategorized passages in others menu - if (jumpToCopy.length > 0) { - const div = document.createElement("div"); - div.append("Other"); - fragment.append("0 ", div); - for (let i = 0; i < jumpToCopy.length; i++) { - if (State.passage !== jumpToCopy[i]) { - fragment.append(generatePassageLink(jumpToCopy[i], 1)); - } else { - const div = document.createElement("div"); - div.append("1 ", jumpToCopy[i]); - fragment.append(div); - } + const div = document.createElement("div"); + div.classList.add("quick-links"); + div.append(generateLinkList(layout)); + fragment.append(div); + + // traverse from current passage up to uncollapse. + if (currentPassageDOM !== null) { + while (!currentPassageDOM.classList.contains("quick-links")) { + currentPassageDOM.classList.remove("collapsed"); + currentPassageDOM = currentPassageDOM.parentElement; } } @@ -123,49 +130,91 @@ App.UI.quickMenu = (function() { return fragment; } - function generateQuickMenu(passages, group, level) { + function generateLinkList(group) { const fragment = document.createDocumentFragment(); for (const passage in group) { - const included = jumpTo.includes(passage); - // remove used passage from list - if (included) { - const index = passages.indexOf(passage); - if (index > -1) { - passages.splice(index, 1); - } - } - - // make link - if (included && State.passage !== passage) { - fragment.append(generatePassageLink(passage, level)); + if (group[passage] === true) { + fragment.append(menuLink(passage)); } else { - const div = document.createElement("div"); - div.append(level, " ", passage); - fragment.append(div); - } - - // lower levels - if (group[passage] !== true) { - fragment.append(generateQuickMenu(passages, group[passage], level + 1)); + fragment.append(generateCategory(passage, group[passage])); } } return fragment; } - function generatePassageLink(passage, level) { + function generateCategory(name, group) { + const toggle = document.createElement("div"); + toggle.classList.add("toggle"); + toggle.append(menuLink(name, true)); + const content = document.createElement("div"); + content.classList.add("content"); + content.append(generateLinkList(group)); + + // wrap everything in one div, so we can control it by changing only one class + const wrapper = document.createElement("div"); + wrapper.classList.add("collapsed"); + toggle.onclick = () => { + wrapper.classList.toggle("collapsed"); + }; + wrapper.append(toggle, content); + return wrapper; + } + + function menuLink(passage, toggle = false) { const div = document.createElement("div"); + if (!toggle) { + div.classList.add("menu-link"); + } + // we are already on this passage + if (State.passage === passage) { + div.append(passage); + currentPassageDOM = div; + return div; + } + // That is not a passage we can safely jump to, it's a deco element + if (!jumpTo.includes(passage)) { + div.append(passage); + return div; + } + // Create link const a = document.createElement("a"); a.append(passage); a.onclick = () => { Engine.play(passage); }; - div.append(level, " ", a); + div.append(a); if (hotkeys[passage]) { div.append(" ", App.UI.DOM.makeElement("span", `[${hotkeys[passage]}]`, "hotkey")); } return div; } + function addOtherCategory(layout) { + const passages = jumpTo.slice(); + filterPassages(passages, layout); + + if (passages.length > 0) { + const other = {}; + for (let i = 0; i < passages.length; i++) { + other[passages[i]] = true; + } + layout.Other = other; + } + return layout; + } + + function filterPassages(passages, layout) { + for (const category in layout) { + const index = passages.indexOf(category); + if (index > -1) { + passages.splice(index, 1); + } + if (layout[category] !== true) { + filterPassages(passages, layout[category]); + } + } + } + /** * Cleans out all keys that are not contained in jumpTo and therefore not considered safe. * -- GitLab