Forráskód Böngészése

Upgrading Navigation-Bar

Switched to Vue placement, instead of directly using JS.
Added ability to have links always in the dropdown.
Removed the ability to hide the dropdown button. (Makes things easier + not in use)
Merged the nav code into HeaderBar.
Ecconia 7 éve
szülő
commit
efd4e3428f
3 módosított fájl, 145 hozzáadás és 172 törlés
  1. 0 2
      src/App.vue
  2. 145 32
      src/components/HeaderBar.vue
  3. 0 138
      src/components/MenuContainer.vue

+ 0 - 2
src/App.vue

@@ -5,8 +5,6 @@
 		<div class="content">
 			<p>Website under development, please excuse ugly style and broken/missing features as well as missing legal things.</p>
 			<router-view/>
-			<br>
-			<router-link to="/impressum">Impressum</router-link>
 		</div>
 	</div>
 </template>

+ 145 - 32
src/components/HeaderBar.vue

@@ -4,81 +4,194 @@
 			<span>RedstoneServer</span>
 		</div>
 
-		<MenuContainer class="menu-container">
-			<router-link class="top-link" :to="link" v-for="(link, text) in menu_entries" :key="link">{{ text }}</router-link>
-		</MenuContainer>
+		<nav ref="navigation">
+			<div class="topbar" ref="topbar">
+				<router-link class="t_link link" :to="element.val" v-for="element in primary" :key="element.key">{{ element.key }}</router-link>
+			</div>
+			<div class="wrapper">
+				<span class="t_link_d t_link link" ref="dropdownArrow">VV</span>
+				<div class="dropdown">
+					<router-link class="d_link link" :to="element.val" v-for="element in secondary" :key="element.key">{{ element.key }}</router-link>
+				</div>
+			</div>
+		</nav>
 
 		<div class="user">
 			<div v-if="user">
 				<span>Username: {{ user.username }} </span>
-				<span class="rl" @click="logout">Logout</span>
+				<span class="link" @click="logout">Logout</span>
 			</div>
-			<router-link class="rl" to="/login" v-else>Login</router-link>
+			<router-link class="link" to="/login" v-else>Login</router-link>
 		</div>
 	</header>
 </template>
 
 <script>
-	import MenuContainer from './MenuContainer.vue'
-
 	export default {
 		data () {
 			return {
-				menu_entries: {
-					'Startpage': '/',
-					'Applications': '/applications',
-					'Development Blog': '/devblog',
+				links: {
+					primary: {
+						'Startpage': '/',
+						'Applications': '/applications',
+						'Development Blog': '/devblog',
+					},
+					secondary: {
+						'Impressum': '/impressum',
+					},
 				},
+				intLinks: {
+					primary: [],
+					secondary: [],
+				},
+				primary: [],
+				secondary: [],
 			}
 		},
-
+		created() {
+			//Convert the given links to arrays for later processing.
+			this.intLinks.primary = this.convertToArray(this.links.primary)
+			this.intLinks.secondary = this.convertToArray(this.links.secondary)
+		},
 		computed: {
 			user() {
 				return this.$store.state.user
 			},
 		},
-
 		methods: {
+			updateMenu() {
+				//Empty to measure the whole available space.
+				this.primary = []
+
+				this.$nextTick(() => {
+					let menubar = this.$refs.topbar
+					//Subtract safety pixels, scrollbars come a bit later after resize.
+					let maxWidth = this.$refs.navigation.clientWidth - this.$refs.dropdownArrow.offsetWidth - 30
+
+					//Add all preprocessed links to measure them in current env.
+					this.primary = this.intLinks.primary
+
+					this.$nextTick(() => {
+						let sizes = []
+						for(let el of menubar.childNodes) {
+							sizes.push(el.offsetWidth)
+						}
+
+						this.primary = []
+						this.secondary = []
+
+						let linkSize = this.intLinks.primary.length
+						let tmp = 0;
+						for(let i = 0; i < linkSize; i++) {
+							tmp += sizes[i] //Add the size of the current element
+
+							if(maxWidth > tmp) {
+								this.primary.push(this.intLinks.primary[i])
+							} else {
+								this.secondary.push(this.intLinks.primary[i])
+							}
+						}
+
+						this.secondary = this.secondary.concat(this.intLinks.secondary)
+					})
+				})
+			},
+			convertToArray(obj) {
+				let els = []
+				for(let key in obj) {
+					if(obj.hasOwnProperty(key)) {
+						els.push({
+							key: key,
+							val: obj[key],
+						})
+					}
+				}
+				return els
+			},
 			logout() {
 				this.core.logout()
+			},
+		},
+		watch: {
+			user: function() {
+				this.updateMenu()
 			}
 		},
-
-		components: {
-			MenuContainer
+		mounted() {
+			window.addEventListener('resize', this.updateMenu)
+			//Initial menu sorting
+			this.updateMenu()			
+		},
+		beforeDestroy() {
+			//TBI never will be closed...!
+			window.removeEventListener('resize', this.updateMenu)
 		},
 	}
 </script>
 
 <style scoped>
+	/*
+	Whole line:
+	*/
 	header {
-		font-size: 1.5em;
-		color: #aaa;
-		background-color: #222;
 		display: flex;
-	}
 
-	header .logo {
-		display: inline-block;
+		white-space: nowrap;
+		background-color: #222;
 	}
-
-	header .menu-container {
+	nav {
 		flex-grow: 100;
-		box-sizing: border-box;
 	}
 
-	header .user {
-		padding: 0.2em 0em;
+	/*
+	Dropdown mechanic:
+	*/
+	.dropdown {
+		position: absolute;
+		display: none;
+
+		background-color: #222;
+		
+		right: 50%;
+		transform: translateX(50%);
+	}
+	.wrapper:hover > .dropdown {
+		display: block;
+	}
+	.wrapper {
+		position: relative;
+		display: inline;
+	}
+	.topbar {
+		display: inline;
 	}
 
-	.rl {
-		text-decoration: none;
+	/*
+	Generic link properties:
+	*/
+	.link {
+		padding: 0em 0.2em;
+
 		color: #aaa;
-		padding: 0.2em 1em;
+		text-decoration: none;
 	}
-
-	.rl:hover {
+	.link:hover {
 		color: #ddd;
 		background-color: #333;
 	}
+
+	/*
+	Specific link properties:
+	*/
+	.t_link {
+		border-right: 1px solid #aaa;
+	}
+	.d_link {
+		display: block;
+		border-top: 1px solid #aaa;
+	}
+	.t_link_d {
+		border-right: none;
+	}
+
 </style>

+ 0 - 138
src/components/MenuContainer.vue

@@ -1,138 +0,0 @@
-<template>
-	<div ref="whole">
-		<div class="topbar" ref="topbar">
-			<slot class="top-link"></slot>
-		</div>
-		<span class="arrow">
-			<span class="top-link" ref="dropdownbutton">vv</span>
-			<div class="dropdown" ref="dropdown" />
-		</span>
-	</div>
-</template>
-
-<script>
-	//TODO: Upgrade to a system using Vue for placement.
-	export default {
-		methods: {
-			onResize() {
-				this.update()
-			},
-
-			update() {
-				let topbar = this.$refs.topbar
-				let dropdown = this.$refs.dropdown
-				
-				let dropDownButton = this.$refs.dropdownbutton
-				dropDownButton.classList.remove('alone', 'full')
-				let dropdownWidth = dropDownButton.offsetWidth
-				
-				let topbarElements = Array.from(topbar.childNodes)
-				let dropboxElements = Array.from(dropdown.childNodes)
-				for(let el of dropboxElements) {
-					dropdown.removeChild(el)
-					topbar.appendChild(el)
-				}
-
-				let childAndSize = []
-				for(let child of topbarElements.concat(dropboxElements)) {
-					childAndSize.push([child.offsetWidth, child])
-				}
-
-				topbar.innerHTML = ''
-				let width = this.$refs.whole.clientWidth - dropdownWidth - 50
-				let tmp = 0
-				for(let child of childAndSize) {
-					tmp += child[0]
-
-					if(width > tmp) {
-						topbar.appendChild(child[1])
-					} else {
-						dropdown.appendChild(child[1])
-					}
-				}
-
-				if(dropdown.childNodes.length === 0) {
-					dropDownButton.classList.add('full')
-				} else if(topbar.childNodes.length === 0) {
-					dropDownButton.classList.add('alone')
-				}
-			}
-		},
-
-		mounted() {
-			window.addEventListener('resize', this.onResize)
-			//Initial menu sorting
-			this.update()			
-		},
-
-		beforeDestroy() {
-			//TBI never will be closed...!
-			window.removeEventListener('resize', this.onResize)
-		}
-	}
-</script>
-
-<style scoped>
-	.whole {
-		box-sizing: border-box;
-	}
-
-	.topbar > .top-link:first-child {
-		border: none;
-	}
-	.top-link {
-		box-sizing: border-box;
-		white-space: nowrap;
-		display: inline-block;
-		padding: 0.2em 0.3em 0.2em 0.3em;
-		border-left: solid 1px #aaa;
-
-		color: #aaa;
-		text-decoration: none;
-	}
-
-	.alone {
-		border-left: none;
-	}
-
-	.full {
-		display: none;
-	}
-
-	.topbar {
-		box-sizing: border-box;
-		display: inline-block;
-	}
-	.arrow {
-		position: relative;
-	}
-
-	.dropdown {
-		display: none;
-		position: absolute;
-		
-		z-index: 1;
-
-		min-width: 100%;
-		top: 1.3em;
-		left: 50%;
-		transform: translateX(-50%);
-	}
-
-	.dropdown .top-link {
-		border: none;
-		border-top: 1px solid #aaa;
-		display: block;
-		position: relative;
-		background-color: #222;
-	}
-
-	.arrow:hover .dropdown {
-		display: inline-block;
-	}
-
-	.top-link:hover {
-		background-color: #333;
-		color: #ddd;
-	}
-</style>