|
@@ -4,81 +4,194 @@
|
|
|
<span>RedstoneServer</span>
|
|
<span>RedstoneServer</span>
|
|
|
</div>
|
|
</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 class="user">
|
|
|
<div v-if="user">
|
|
<div v-if="user">
|
|
|
<span>Username: {{ user.username }} </span>
|
|
<span>Username: {{ user.username }} </span>
|
|
|
- <span class="rl" @click="logout">Logout</span>
|
|
|
|
|
|
|
+ <span class="link" @click="logout">Logout</span>
|
|
|
</div>
|
|
</div>
|
|
|
- <router-link class="rl" to="/login" v-else>Login</router-link>
|
|
|
|
|
|
|
+ <router-link class="link" to="/login" v-else>Login</router-link>
|
|
|
</div>
|
|
</div>
|
|
|
</header>
|
|
</header>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
- import MenuContainer from './MenuContainer.vue'
|
|
|
|
|
-
|
|
|
|
|
export default {
|
|
export default {
|
|
|
data () {
|
|
data () {
|
|
|
return {
|
|
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: {
|
|
computed: {
|
|
|
user() {
|
|
user() {
|
|
|
return this.$store.state.user
|
|
return this.$store.state.user
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
-
|
|
|
|
|
methods: {
|
|
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() {
|
|
logout() {
|
|
|
this.core.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>
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
|
<style scoped>
|
|
|
|
|
+ /*
|
|
|
|
|
+ Whole line:
|
|
|
|
|
+ */
|
|
|
header {
|
|
header {
|
|
|
- font-size: 1.5em;
|
|
|
|
|
- color: #aaa;
|
|
|
|
|
- background-color: #222;
|
|
|
|
|
display: flex;
|
|
display: flex;
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- header .logo {
|
|
|
|
|
- display: inline-block;
|
|
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ background-color: #222;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- header .menu-container {
|
|
|
|
|
|
|
+ nav {
|
|
|
flex-grow: 100;
|
|
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;
|
|
color: #aaa;
|
|
|
- padding: 0.2em 1em;
|
|
|
|
|
|
|
+ text-decoration: none;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- .rl:hover {
|
|
|
|
|
|
|
+ .link:hover {
|
|
|
color: #ddd;
|
|
color: #ddd;
|
|
|
background-color: #333;
|
|
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>
|
|
</style>
|