summaryrefslogtreecommitdiff
path: root/static
diff options
context:
space:
mode:
Diffstat (limited to 'static')
-rw-r--r--static/index.html14
-rw-r--r--static/menu.css99
-rw-r--r--static/menu.js159
-rw-r--r--static/pages.css6
-rw-r--r--static/pages.json32
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"
+ }
+ }
+}