aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hackl <hackl@data-quest.de>2023-07-15 20:54:20 +0000
committerDavid Siegfried <david.siegfried@uni-vechta.de>2023-07-15 20:54:20 +0000
commita70a5f70aadf1cba165c41b33f3485a22979338b (patch)
tree8e3858f5c118a926bd9166e9f355cef07cbebd19
parentafc35076b87c74e40fa5f9c9241de44974b35673 (diff)
Sidebar in Veranstaltungen->Administration scrollt nicht mit, closes #2255
Closes #2255 Merge request studip/studip!1772
-rw-r--r--resources/assets/javascripts/bootstrap/forms.js2
-rw-r--r--resources/assets/javascripts/bootstrap/sidebar.js14
-rw-r--r--resources/assets/javascripts/chunks/vue.js24
-rw-r--r--resources/assets/javascripts/entry-base.js1
-rw-r--r--resources/assets/javascripts/lib/sidebar.js108
-rw-r--r--resources/assets/stylesheets/scss/responsive.scss6
-rw-r--r--resources/assets/stylesheets/scss/sidebar.scss63
7 files changed, 202 insertions, 16 deletions
diff --git a/resources/assets/javascripts/bootstrap/forms.js b/resources/assets/javascripts/bootstrap/forms.js
index 1a6bc53..41c2c77 100644
--- a/resources/assets/javascripts/bootstrap/forms.js
+++ b/resources/assets/javascripts/bootstrap/forms.js
@@ -201,7 +201,7 @@ function createSelect2(element) {
minimumResultsForSearch: $(element).closest('#sidebar').length > 0 ? 15 : 10,
placeholder: placeholder,
dropdownAutoWidth: dropdownAutoWidth,
- dropdownParent: $(element).closest('.ui-dialog,#sidebar,body'),
+ dropdownParent: $(element).closest('.ui-dialog,.sidebar-widget,#sidebar,#content-wrapper,body'),
templateResult: function(data, container) {
if (data.element) {
let option_classes = $(data.element).attr('class'),
diff --git a/resources/assets/javascripts/bootstrap/sidebar.js b/resources/assets/javascripts/bootstrap/sidebar.js
new file mode 100644
index 0000000..5e89a7f
--- /dev/null
+++ b/resources/assets/javascripts/bootstrap/sidebar.js
@@ -0,0 +1,14 @@
+import eventBus from '../lib/event-bus.ts';
+
+STUDIP.ready(() => {
+ // Manually nudge sidebar under main header.
+ STUDIP.Sidebar.place();
+
+ STUDIP.Sidebar.observeBody();
+ STUDIP.Sidebar.observeFooter();
+ STUDIP.Sidebar.observeSidebar();
+
+ document.defaultView.addEventListener('resize',() => {
+ STUDIP.Sidebar.reset();
+ });
+});
diff --git a/resources/assets/javascripts/chunks/vue.js b/resources/assets/javascripts/chunks/vue.js
index cf95ed3..5ee9389 100644
--- a/resources/assets/javascripts/chunks/vue.js
+++ b/resources/assets/javascripts/chunks/vue.js
@@ -41,6 +41,30 @@ Vue.mixin({
},
getStudipConfig: store.getters['studip/getConfig']
},
+ beforeCreate() {
+ eventBus.emit('vue:app:will-create', this);
+ },
+ created() {
+ eventBus.emit('vue:app:did-create', this);
+ },
+ beforeMount() {
+ eventBus.emit('vue:app:will-mount', this);
+ },
+ mounted() {
+ eventBus.emit('vue:app:did-mount', this);
+ },
+ beforeUpdate() {
+ eventBus.emit('vue:app:will-update', this);
+ },
+ updated() {
+ eventBus.emit('vue:app:did-update', this);
+ },
+ beforeDestroy() {
+ eventBus.emit('vue:app:will-destroy', this);
+ },
+ destroyed() {
+ eventBus.emit('vue:app:did-destroy', this);
+ }
});
Vue.use(CKEditor);
diff --git a/resources/assets/javascripts/entry-base.js b/resources/assets/javascripts/entry-base.js
index 9fcb57b..82e5640 100644
--- a/resources/assets/javascripts/entry-base.js
+++ b/resources/assets/javascripts/entry-base.js
@@ -86,6 +86,7 @@ import "./bootstrap/contentmodules.js"
import "./bootstrap/responsive-navigation.js"
import "./bootstrap/treeview.js"
import "./bootstrap/stock-images.js"
+import "./bootstrap/sidebar.js"
import "./mvv_course_wizard.js"
import "./mvv.js"
diff --git a/resources/assets/javascripts/lib/sidebar.js b/resources/assets/javascripts/lib/sidebar.js
index 3cb1c05..eefd317 100644
--- a/resources/assets/javascripts/lib/sidebar.js
+++ b/resources/assets/javascripts/lib/sidebar.js
@@ -1,20 +1,104 @@
-import Scroll from './scroll.js';
-
const Sidebar = {
- open () {
- this.toggle(true);
+
+ place() {
+ const header = document.getElementById('main-header');
+ document.getElementById('sidebar').style.top =
+ header.offsetTop + header.offsetHeight + 'px';
+ },
+
+ observeSidebar() {
+ const options = {
+ root: null,
+ rootMargin: '0px',
+ threshold: 1
+ };
+
+ /**
+ * Observe if sidebar fits into viewport.
+ */
+ const sObserver = new IntersectionObserver(STUDIP.Sidebar.fits, options);
+ sObserver.observe(document.getElementById('sidebar'));
+ },
+
+ observeBody() {
+ const sidebar = document.getElementById('sidebar');
+ /**
+ * Observe body for class changes. If "fixed" is added or removed, we are in scroll mode
+ * where the top navigation is removed or visible again.
+ */
+ const mObserver = new MutationObserver(mutations => {
+ for (const mutation of mutations) {
+ if ((!mutation.oldValue || mutation.oldValue.indexOf('fixed') === -1)
+ && mutation.target.classList.contains('fixed')) {
+ sidebar.classList.add('fixed');
+ sidebar.style.top = '';
+ } else if (mutation.oldValue && mutation.oldValue.indexOf('fixed') !== -1
+ && !mutation.target.classList.contains('fixed')) {
+ sidebar.classList.remove('fixed');
+ }
+ }
+ });
+
+ // Observe body for class changes.
+ mObserver.observe(document.body, {
+ attributes: true,
+ attributeOldValue : true,
+ attributeFilter: ['class']
+ });
},
- close () {
- this.toggle(false);
+
+ observeFooter() {
+ const options = {
+ root: null,
+ rootMargin: '0px',
+ threshold: 1
+ };
+
+ /**
+ * Observe if the footer is visible in viewport.
+ */
+ const fObserver = new IntersectionObserver(STUDIP.Sidebar.footerVisible, options);
+ fObserver.observe(document.getElementById('main-footer'));
+
},
- toggle (visible = null) {
- visible = visible ?? !$('#sidebar').hasClass('visible-sidebar');
- // Hide navigation
- $('#responsive-toggle').prop('checked', false);
- $('#responsive-navigation').removeClass('visible');
+ reset() {
+ const sidebar = document.getElementById('sidebar');
+ if (sidebar) {
+ sidebar.classList.remove('oversized', 'adjusted', 'fixed');
+ sidebar.style.top = '';
+ }
+ STUDIP.Sidebar.observe();
+ },
+
+ fits(entries, observer) {
+ const sidebar = document.getElementById('sidebar');
+ if (sidebar) {
+ entries.forEach(entry => {
+ // Sidebar fits onto current page.
+ if (entry.isIntersecting) {
+ sidebar.classList.remove('oversized');
+ } else {
+ sidebar.classList.add('oversized', 'adjusted');
+ }
+ });
+ }
+ },
- $('#sidebar').toggleClass('visible-sidebar', visible);
+ footerVisible(entries, observer) {
+ const sidebar = document.getElementById('sidebar');
+ entries.forEach(entry => {
+ // Footer is visible on current page.
+ if (entry.isIntersecting) {
+ if (sidebar.classList.contains('no-footer')) {
+ sidebar.classList.remove('no-footer');
+ }
+ } else {
+ if (!sidebar.classList.contains('no-footer')) {
+ sidebar.classList.add('no-footer');
+ }
+ }
+ });
}
};
diff --git a/resources/assets/stylesheets/scss/responsive.scss b/resources/assets/stylesheets/scss/responsive.scss
index cbf2e75..9226db8 100644
--- a/resources/assets/stylesheets/scss/responsive.scss
+++ b/resources/assets/stylesheets/scss/responsive.scss
@@ -337,9 +337,13 @@ $sidebarOut: -330px;
@media not prefers-reduced-motion {
animation: slide-in $transition-duration forwards;
}
- position: sticky;
+
top: 100px;
visibility: visible;
+
+ &:not(.oversized) {
+ position: sticky;
+ }
}
.sidebar-image {
diff --git a/resources/assets/stylesheets/scss/sidebar.scss b/resources/assets/stylesheets/scss/sidebar.scss
index f03d7a2..60114c7 100644
--- a/resources/assets/stylesheets/scss/sidebar.scss
+++ b/resources/assets/stylesheets/scss/sidebar.scss
@@ -2,16 +2,49 @@
background: $white;
border-left: 0;
display: inline-block;
- height: max-content;
margin-bottom: $page-margin + 35px;
margin-top: 15px;
padding: 0 5px 7px 15px;
position: sticky;
text-align: left;
- top: 50px;
+ top: 75px;
width: $sidebar-width;
z-index: 2;
+ &.adjusted {
+ height: calc(100vh - 265px);
+ position: fixed;
+ overflow-x: hidden;
+ overflow-y: scroll;
+ top: 150px;
+ transition: all $transition-duration ease-in-out;
+
+ &::-webkit-scrollbar {
+ background-color: var(--white);
+ position: relative;
+ left: 35px;
+ width: 5px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background-color: var(--light-gray-color-60);
+ border-radius: 5px;
+ }
+
+ &.no-footer {
+ height: calc(100vh - 225px);
+ }
+
+ &.fixed {
+ height: calc(100vh - 150px);
+ top: 40px;
+
+ &.no-footer {
+ height: calc(100vh - 125px);
+ }
+ }
+ }
+
.sidebar-image {
width: calc($sidebar-width - 2px);
height: 60px;
@@ -88,6 +121,7 @@
background: $white;
border: 1px solid $content-color-40;
margin: 15px 0 0;
+ position: relative;
width: $sidebar-width - 5px;
}
.sidebar-widget-header,
@@ -112,6 +146,30 @@
}
}
+#admin-courses-index {
+ #sidebar {
+ top: 50px;
+
+ &.adjusted {
+ height: calc(100vh - 250px);
+ top: 155px;
+
+ &.no-footer {
+ height: calc(100vh - 200px);
+ }
+
+ &.fixed {
+ height: calc(100vh - 125px);
+ top: 35px;
+
+ &.no-footer {
+ height: calc(100vh - 100px);
+ }
+ }
+ }
+ }
+}
+
ul.widget-list {
list-style: none;
margin: 0;
@@ -352,3 +410,4 @@ select.sidebar-selectlist {
}
}
}
+