diff options
Diffstat (limited to 'static')
-rw-r--r-- | static/index.html | 14 | ||||
-rw-r--r-- | static/menu.css | 99 | ||||
-rw-r--r-- | static/menu.js | 159 | ||||
-rw-r--r-- | static/pages.css | 6 | ||||
-rw-r--r-- | static/pages.json | 32 |
5 files changed, 310 insertions, 0 deletions
diff --git a/static/index.html b/static/index.html new file mode 100644 index 0000000..c651142 --- /dev/null +++ b/static/index.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html lang="fi"> +<head> + <title>Kyselmä</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta author="Viljami Ilola"> + <link rel="stylesheet" href="menu.css"> + <link rel="stylesheet" href="pages.css"> + <link rel="icon" type="image/svg+xml" href="kyselma.svg"> + <script src="menu.js"></script> +</head> +<body></body> +</html>
\ No newline at end of file diff --git a/static/menu.css b/static/menu.css new file mode 100644 index 0000000..04127ae --- /dev/null +++ b/static/menu.css @@ -0,0 +1,99 @@ +@charset "utf-8"; + +:root { + --menuColor: #000; + --menuBgColor: #fee; + --menuColorActive: #000; + --menuBgActive: #c88; + --menuColorHover: #fff; + --menuBgHover: #48f; + + --menuHeight: 1.5em; + --menuFontSize: 2; + --menuHamburgerHeight: 1.25em; + --menuHamburgerFontSize: 2.4; +} + +.menuItem { + height: var(--menuHeight); + display: flex; + align-items: center; + background-color: var(--menuBgColor); + font-size: calc(var(--menuFontSize)*100%); + cursor: pointer; + transition: background-color 0.3s; +} +.menuItem:hover { + background-color: var(--menuBgHover); +} +.menuItemActive, .menuItemActive:hover { + background-color: var(--menuBgActive); +} +.menuTitle, .menuTitle:hover, .menuSpacer, .menuSpacer:hover { + background-color: var(--menuBgColor); + cursor: unset; +} +.menuSpacer, .menuTitle { display: none; } + +.menuIcon { + width: calc(var(--menuHeight)*0.9); + height: calc(var(--menuHeight)*0.9); + padding: calc(var(--menuHeight)*0.05); +} +.menuIcon > a > img { + width: 100%; + height: 100%; +} +.menuText { + padding-left: calc(var(--menuHeight)/4); +} +.menuText > a { + color: var(--menuColor); + text-decoration: none; +} +.menuItem:hover > .menuText > a { + color: var(--menuColorHover); +} +.menuItemActive > .menuText > a, .menuItemActive:hover > .menuText > a { + color: var(--menuColorActive); +} +#menu { + position: absolute; + top: 0; + left: 0; + width: 100%; + display: block; +} +.menuHidden { display: none !important } + +#hamburgerMenu { + position: fixed; + right: 0; + top: 0; + display: flex; + z-index: 1; + width: var(--menuHamburgerHeight); + height: var(--menuHamburgerHeight); + font-size: calc(var(--menuHamburgerFontSize)*100%); + align-items: center; + justify-content: center; + background-color: var(--menuBgActive); + color: var(--menuColorActive); +} +#hamburgerMenu::before { content: "☰"; } +#spaceBeforePage { height: 0; } + +.page { display: none } +.pageActive { display: unset } + +@media only screen and (min-width: 64em) { + #hamburgerMenu { display: none; } + #menu { position: fixed; } + #spaceBeforePage { height: calc(var(--menuHeight)*var(--menuFontSize)); } + .menuHidden, .menuSpacer, .menuTitle { display: flex !important } + .menuSpacer { flex-grow: 2; } + .menuText { + padding-left: calc(var(--menuHeight)/2); + padding-right: calc(var(--menuHeight)/2); + } +} diff --git a/static/menu.js b/static/menu.js new file mode 100644 index 0000000..a014793 --- /dev/null +++ b/static/menu.js @@ -0,0 +1,159 @@ +// menu.js - menu system for small site - 2022 Viljami Ilola + +const jsonURL = 'pages.json' + +var conf = {} +var pages = {} +var currentPage = null; +loadPages = async() => { + await fetch( jsonURL ) + .then( response => response.json() ) + .then( json => conf = json ) + .catch( error => { + document.body.innerHTML = `Error loading ${jsonURL}<hr>${error}` + } ) + pages = conf.pages + + installHamburger() + createMenu() + createPlaceholders() + hashToPage() +} + +createPlaceholders = () => { + pagesMain = document.createElement('main') + Object.keys(pages).forEach(p => { + if ( pages[p].URL && pages[p].URL !== "" ) { + const pageSection = document.createElement('section') + pageSection.id = `${p}_page` + pageSection.className='page' + pagesMain.appendChild( pageSection ) + } + }) + document.documentElement.lastChild.append( pagesMain ) +} + +createMenuIcon = (p) => { + const icon = pages[p].menuIcon ? pages[p].menuIcon : '' + if ( icon === '' ) return null + + const iconImg = document.createElement('img') + iconImg.src = icon + + const iconAnchor = document.createElement('a') + iconAnchor.href = `#${p}` + iconAnchor.appendChild( iconImg ) + + const iconDiv = document.createElement('div') + iconDiv.className = 'menuIcon' + iconDiv.appendChild( iconAnchor ) + + return iconDiv +} + +createMenuText = (p) => { + const url = pages[p].URL ? pages[p].URL : "" + const name = pages[p].menuName ? pages[p].menuName : url + + if ( name === '' ) return null + + const textNode = document.createTextNode( name ) + + const textAnchor = document.createElement( url === "" ? 'div' : 'a') + textAnchor.href = `#${p}` + textAnchor.appendChild( textNode ) + + const textDiv = document.createElement('div') + textDiv.className = 'menuText' + textDiv.appendChild( textAnchor ) + + return textDiv +} + +createMenu = () => { + const menuNav = document.createElement('nav') + menuNav.id = 'menu' + menuNav.className = 'menuHidden' + + Object.keys(pages).forEach(p => { + + const entryDiv = document.createElement('div') + entryDiv.className = 'menuItem' + entryDiv.id = `${p}_menuEntry` + + const iconDiv = createMenuIcon(p) + const textDiv = createMenuText(p) + if ( iconDiv ) entryDiv.appendChild( iconDiv ) + if ( textDiv ) entryDiv.appendChild( textDiv ) + + const url = pages[p].URL ? pages[p].URL : "" + const name = pages[p].menuName ? pages[p].menuName : url + if ( url === "" ) entryDiv.className += + name === "" ? ' menuSpacer' : ' menuTitle' + else entryDiv.onclick = () => window.location.hash = p; + + menuNav.append( entryDiv ) + }) + document.documentElement.lastChild.append( menuNav ) + + const spacerDiv = document.createElement('div') + spacerDiv.id = 'spaceBeforePage' + document.documentElement.lastChild.append( spacerDiv ) +} + +installHamburger = () => { + hamburgerDiv = document.createElement('div') + hamburgerDiv.id = 'hamburgerMenu' + hamburgerDiv.onclick = () => toggleMenu() + document.documentElement.lastChild.append( hamburgerDiv ) +} + +toggleMenu = () => { + const menuNav = document.getElementById('menu') + menuNav.className = menuNav.className === 'menuHidden' ? '' : 'menuHidden' + if (menuNav.className === '') window.scrollTo(0,0) +} + +hashToPage = () => { + const p = !document.location.hash + ? Object.keys(pages)[0] : document.location.hash.substr(1) in pages + ? document.location.hash.substr(1) : Object.keys(pages)[0] + + if ( p === Object.keys(pages)[0] ) { + window.history.replaceState('', '', window.location.pathname) + } + if ( p === currentPage ) return false + + const pageElement = document.getElementById(`${p}_page`) + + if ( !currentPage ) currentPage = p; + else document.getElementById(`${currentPage}_page`).className = 'page' + pageElement.className = 'page pageActive' + + if ( !pageElement.loaded ) fetch( pages[p].URL ) + .then( response => { + if (!response.ok) return `ERROR loading "${pages[p].URL}"!` + return response.text() + } ) + .then( text => { + pageElement.innerHTML = text + pageElement.loaded = true + } ) + document.getElementById(`${currentPage}_menuEntry`) + .className = 'menuItem' + document.getElementById(`${p}_menuEntry`) + .className = 'menuItem menuItemActive' + currentPage = p + if (!pages[p].pageTitle) document.title = conf.title + else document.title = `${pages[p].pageTitle} - ${conf.title}` +} + +hideMenu = () => document.getElementById('menu').className = 'menuHidden'; + +window.onload = async() => { + loadPages() +} +window.onhashchange = () => { + hideMenu() + hashToPage() +} diff --git a/static/pages.css b/static/pages.css new file mode 100644 index 0000000..75be5f6 --- /dev/null +++ b/static/pages.css @@ -0,0 +1,6 @@ +@charset "utf-8"; + +h1 { + font-size: 2em; + margin: 1em; +}
\ No newline at end of file diff --git a/static/pages.json b/static/pages.json new file mode 100644 index 0000000..4935c1d --- /dev/null +++ b/static/pages.json @@ -0,0 +1,32 @@ +{ + "title": "Kyselmä", + "pages": { + "info": { + "URL": "pages/info.html", + "menuIcon": "kyselma.svg", + "menuName": "Kyselmä" + }, + "spacer-1": { + }, + "create": { + "pageTitle": "Luo kysely", + "URL": "pages/create.html", + "menuName": "Luo" + }, + "answer": { + "pageTitle": "Vastaa kyselyyn", + "URL": "pages/answer.html", + "menuName": "Vastaa" + }, + "analyse": { + "pageTitle": "Tutki vastauksia", + "URL": "pages/analyse.html", + "menuName": "Tutki" + }, + "moderate": { + "pageTitle": "Moderoi sivustoa", + "URL": "pages/moderate.html", + "menuName": "Moderoi" + } + } +} |