Newer
Older
<template>
<div v-if="realContentbarSource === ''">
<MountingPortal mount-to="#responsive-contentbar-container" append>
<portal-target name="layout-page"></portal-target>
</MountingPortal>
<portal to="layout-page">
<div id="responsive-contentbar" class="contentbar" ref="contentbar">
<div v-if="hasSidebar" class="contentbar-nav" ref="leftNav">
<button :class="sidebarIconClasses" @click.prevent="toggleSidebar" id="toggle-sidebar"
:title="$gettext('Sidebar öffnen')">

Thomas Hackl
committed
<studip-icon shape="sidebar3" :size="24" ref="sidebarIcon"
alt=""></studip-icon>
</button>
</div>
<div class="contentbar-wrapper-left">

Thomas Hackl
committed
<studip-icon :shape="icon" :size="24" role="info" class="text-bottom contentbar-icon"></studip-icon>
<nav class="contentbar-breadcrumb" ref="breadcrumbs">
<span>{{ title }}</span>
</nav>
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
</div>
<div class="contentbar-wrapper-right" ref="wrapperRight"></div>
</div>
</portal>
</div>
</template>
<script>
import StudipIcon from '../StudipIcon.vue';
export default {
name: 'ResponsiveContentBar',
components: { StudipIcon },
props: {
icon: {
type: String,
default: 'seminar'
},
title: {
type: String,
default: ''
},
hasSidebar: {
type: Boolean,
default: true
}
},
data() {
return {
realContentbar: null,
realContentbarSource: null,
realContentbarIconContainer: null,
realContentbarType: null,
sidebarOpen: false
}
},
computed: {
sidebarIconClasses() {
let classes = ['styleless', 'contentbar-button', 'contentbar-button-sidebar'];
if (this.sidebarOpen) {
classes.push('contentbar-button-sidebar-open');
}
return classes;
}
},
methods: {
toggleSidebar() {
const sidebar = document.getElementById('sidebar');
const content = document.getElementById('content-wrapper');
const pageTitle = document.getElementById('page-title-container');
if (this.sidebarOpen) {

Thomas Hackl
committed
sidebar.ariaHidden = 'true';
sidebar.classList.add('responsive-hide');
sidebar.classList.remove('responsive-show');
if (document.documentElement.classList.contains('responsive-display')
&& !document.documentElement.classList.contains('fullscreen-mode')) {

Thomas Hackl
committed
content.style.display = '';
pageTitle.style.display = '';
if (!document.documentElement.classList.contains('responsive-display')) {

Thomas Hackl
committed
setTimeout(() => {

Thomas Hackl
committed
document.body.classList.remove('fullscreen-sidebar-shown');

Thomas Hackl
committed
}, 300);
this.sidebarOpen = false;
} else {

Thomas Hackl
committed
sidebar.ariaHidden = '';
sidebar.classList.add('responsive-show');
sidebar.classList.remove('responsive-hide');

Thomas Hackl
committed
if (document.documentElement.classList.contains('responsive-display')

Thomas Hackl
committed
&& !document.documentElement.classList.contains('fullscreen-mode')) {

Thomas Hackl
committed
// Set a timeout here so that the content "disappears" after slide-in aninmation is finished.
setTimeout(() => {
content.style.display = 'none';
pageTitle.style.display = 'none';
}, 300);
if (!document.documentElement.classList.contains('responsive-display')) {

Thomas Hackl
committed
document.body.classList.add('fullscreen-sidebar-shown');
this.sidebarOpen = true;
}
// Adjust toggle sidebar button title
document.getElementById('toggle-sidebar').title = this.sidebarOpen
? this.$gettext('Sidebar schließen')
: this.$gettext('Sidebar öffnen');
},
adjustExistingContentbar(responsiveMode) {
if (this.realContentbar) {
if (responsiveMode) {
this.realContentbar.id = 'responsive-contentbar';
this.realContentbar.classList.add('contentbar');
if (!this.realContentbar.querySelector('#toggle-sidebar')) {
this.realContentbar.querySelector(this.realContentbarIconContainer)
.prepend(this.createSidebarIcon());
}
if (this.realContentbarType === 'courseware') {
this.realContentbar.querySelector('.cw-ribbon-wrapper-left')
.classList.add('contentbar-wrapper-left');
this.realContentbar.querySelector('.cw-ribbon-wrapper-right')
.classList.add('contentbar-wrapper-right');
}
document.getElementById('responsive-contentbar-container').prepend(this.realContentbar);
} else {
this.realContentbar.id = 'contentbar';
document.getElementById('toggle-sidebar').remove();
if (this.realContentbarType === 'courseware') {
this.realContentbar.classList.remove('contentbar');
this.realContentbar.querySelector('.cw-ribbon-wrapper-left')
.classList.remove('contentbar-wrapper-left');
this.realContentbar.querySelector('.cw-ribbon-wrapper-right')
.classList.remove('contentbar-wrapper-right');
}
document.querySelector(this.realContentbarSource).prepend(this.realContentbar);
}
}
},
createSidebarIcon() {
const button = document.createElement('button');
this.sidebarIconClasses.map(className => {
button.classList.add(className);
});
button.id = 'toggle-sidebar';
button.title = this.$gettext('Sidebar einblenden');
button.addEventListener('click', (event) => {
button.classList.toggle('contentbar-button-sidebar-open');
event.preventDefault();
this.toggleSidebar();
})
const sidebarIcon = document.createElement('img');
sidebarIcon.src = STUDIP.ASSETS_URL + '/images/icons/blue/sidebar3.svg';
sidebarIcon.height = 24;
sidebarIcon.width = 24;
button.appendChild(sidebarIcon);
return button;
}
},
mounted() {
// There's already a PHP contentbar on this page, use it.
this.$nextTick(() => {
const realContentbar = document.querySelector('.contentbar:not(#responsive-contentbar)');
if (realContentbar) {
STUDIP.eventBus.emit('has-contentbar', true);
this.realContentbar = realContentbar;
this.realContentbarSource = '#content';
this.realContentbarIconContainer = '.contentbar-nav';
this.realContentbarType = 'wiki';
this.adjustExistingContentbar(true);
} else {
this.realContentbarSource = '';
const cwContentbar = document.querySelector('#contentbar header');
if (cwContentbar) {
STUDIP.eventBus.emit('has-contentbar', true);
this.realContentbar = cwContentbar;
this.realContentbarSource = '.cw-structural-element-content > div';
this.realContentbarIconContainer = '.cw-ribbon-nav';
this.realContentbarType = 'courseware';
this.adjustExistingContentbar(true);
}
}
// Add click listener to sidebar so that it can be hidden on clicking an item
document.querySelectorAll('.sidebar-widget a').forEach(item => {
item.addEventListener('click', () => this.toggleSidebar());
});
})
// Use courseware contentbar instead of this Vue component.
this.globalOn('courseware-contentbar-mounted', element => {
STUDIP.eventBus.emit('has-contentbar', true);
this.realContentbar = element.$el.querySelector('header');
this.realContentbarSource = '.cw-structural-element-content > div';
this.realContentbarIconContainer = '.cw-ribbon-nav';
this.realContentbarType = 'courseware';
this.adjustExistingContentbar(true);
document.querySelectorAll('.sidebar-widget button span').forEach(item => {
item.addEventListener('click', () => this.toggleSidebar());
});
})
this.globalOn('toggle-focus-mode', (state) => {
const html = document.querySelector('html');
if (html.classList.contains('responsive-display') || html.classList.contains('fullscreen-mode')) {
this.adjustExistingContentbar(!state);
}
},
beforeDestroy() {
if (this.realContentbar) {
this.adjustExistingContentbar(false);
}
STUDIP.eventBus.off('toggle-focus-mode');
STUDIP.eventBus.off('courseware-contentbar-mounted');
}
}
</script>