| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- <template>
- <header ref="header">
- <div class="logo">
- <div class="small">
- <span> RS </span>
- </div>
- <div class="big">
- <span> RedstoneServer </span>
- </div>
- </div>
- <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 v-if="!compressed">Username: {{ user.username }} </span>
- <span v-else>Hi, {{ user.username }} </span>
- <span class="link" @click="logout">Logout</span>
- </div>
- <router-link class="link" to="/login" v-else>Login</router-link>
- </div>
- </header>
- </template>
- <script>
- export default {
- data () {
- return {
- links: {
- primary: {
- 'Startpage': '/',
- 'Applications': '/applications',
- 'Development Blog': '/devblog',
- },
- secondary: {
- 'Impressum': '/impressum',
- },
- },
- intLinks: {
- primary: [],
- secondary: [],
- },
- primary: [],
- secondary: [],
- compressed: false,
- }
- },
- 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.compressed = false
- 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)
- //TODO: Improve, set dropdown to middle when this mode.
- //Check if there is still no space, if so, minimized view.
- this.$nextTick(() => {
- if(this.$refs.header.scrollWidth > (window.innerWidth || document.documentElement.clientWidth)) {
- this.compressed = true
- }
- })
- })
- })
- },
- 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()
- }
- },
- 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 {
- display: flex;
- white-space: nowrap;
- background-color: #222;
- font-size: 1.5em;
- }
- nav {
- flex-grow: 100;
- /* try permanent? */
- display: flex;
- justify-content: center;
- align-items: center;
- }
- /*
- 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;
- }
- /*
- Generic link properties:
- */
- .link {
- padding: 0em 0.2em;
- color: #aaa;
- text-decoration: none;
- }
- .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;
- }
- /*
- Header compression:
- */
- .logo > .small {
- display: none;
- }
- @media (max-width: 600px) {
- /* Switch to the small logo */
- .logo > .small {
- display: initial;
- }
- .logo > .big {
- display: none;
- }
- /* Center the dropdown menu */
- .wrapper {
- position: initial;
- }
- }
- </style>
|