From cff48047b00b890600356fad29064b6a28532c2b Mon Sep 17 00:00:00 2001 From: Thomas Hackl Date: Mon, 6 Feb 2023 08:36:42 +0000 Subject: Resolve ""Zweistufiger" Vollbildmodus" Closes #2037, #1759, and #2097 Merge request studip/studip!1326 --- app/views/oer/market/details.php | 2 +- lib/wiki.inc.php | 12 ++ public/assets/images/icons/black/focusmode-off.svg | 1 - .../assets/images/icons/black/fullscreen-off.svg | 1 - public/assets/images/icons/black/fullscreen-on.svg | 1 - public/assets/images/icons/blue/focusmode-off.svg | 1 - public/assets/images/icons/blue/fullscreen-off.svg | 1 - .../assets/images/icons/blue/fullscreen-off2.svg | 1 - .../assets/images/icons/blue/fullscreen-off3.svg | 1 - public/assets/images/icons/blue/fullscreen-on.svg | 1 - public/assets/images/icons/blue/fullscreen-on2.svg | 1 - public/assets/images/icons/blue/fullscreen-on3.svg | 1 - public/assets/images/icons/blue/fullscreen-on4.svg | 1 - public/assets/images/icons/blue/fullscreen-on5.svg | 1 - public/assets/images/icons/blue/screen-compact.svg | 1 + public/assets/images/icons/blue/screen-full.svg | 1 + .../assets/images/icons/blue/screen-standard.svg | 1 + public/assets/images/icons/green/focusmode-off.svg | 1 - .../assets/images/icons/green/fullscreen-off.svg | 1 - public/assets/images/icons/green/fullscreen-on.svg | 1 - public/assets/images/icons/grey/focusmode-off.svg | 1 - public/assets/images/icons/grey/fullscreen-off.svg | 1 - public/assets/images/icons/grey/fullscreen-on.svg | 2 +- public/assets/images/icons/red/focusmode-off.svg | 1 - public/assets/images/icons/red/fullscreen-off.svg | 1 - public/assets/images/icons/red/fullscreen-on.svg | 1 - public/assets/images/icons/white/focusmode-off.svg | 1 - .../assets/images/icons/white/fullscreen-off.svg | 1 - .../assets/images/icons/white/fullscreen-off2.svg | 1 - .../assets/images/icons/white/fullscreen-off3.svg | 1 - public/assets/images/icons/white/fullscreen-on.svg | 1 - .../assets/images/icons/white/fullscreen-on2.svg | 1 - .../assets/images/icons/white/fullscreen-on3.svg | 1 - .../assets/images/icons/white/fullscreen-on4.svg | 1 - .../assets/images/icons/white/screen-compact.svg | 1 + public/assets/images/icons/white/screen-full.svg | 1 + .../assets/images/icons/white/screen-standard.svg | 1 + .../assets/images/icons/yellow/focusmode-off.svg | 1 - .../assets/images/icons/yellow/fullscreen-off.svg | 1 - .../assets/images/icons/yellow/fullscreen-on.svg | 1 - .../assets/javascripts/bootstrap/application.js | 8 - .../assets/javascripts/bootstrap/fullscreen.js | 33 +++- .../assets/javascripts/bootstrap/responsive.js | 8 +- resources/assets/javascripts/bootstrap/sidebar.js | 58 +------ resources/assets/javascripts/lib/fullscreen.js | 66 +++----- resources/assets/javascripts/lib/responsive.js | 11 +- resources/assets/javascripts/lib/sidebar.js | 26 ++-- resources/assets/stylesheets/scss/contentbar.scss | 23 --- resources/assets/stylesheets/scss/courseware.scss | 33 ++-- resources/assets/stylesheets/scss/header.scss | 2 +- resources/assets/stylesheets/scss/index.scss | 9 ++ resources/assets/stylesheets/scss/layouts.scss | 17 ++- resources/assets/stylesheets/scss/responsive.scss | 103 ++++++++++--- resources/assets/stylesheets/scss/sidebar.scss | 6 +- resources/assets/stylesheets/studip.less | 3 - resources/assets/stylesheets/studip.scss | 2 +- .../vue/components/courseware/CoursewareRibbon.vue | 25 +-- .../courseware/CoursewareStructuralElement.vue | 19 ++- .../vue/components/responsive/NavigationItem.vue | 13 +- .../components/responsive/ResponsiveContentBar.vue | 42 +++++- .../components/responsive/ResponsiveNavigation.vue | 167 +++++++++++++-------- .../components/responsive/ResponsiveSkipLinks.vue | 2 +- .../vue/components/responsive/ToggleFullscreen.vue | 51 ------- templates/contentbar/contentbar.php | 5 - templates/header.php | 13 +- templates/tabs.php | 9 +- 66 files changed, 415 insertions(+), 392 deletions(-) delete mode 100644 public/assets/images/icons/black/focusmode-off.svg delete mode 100644 public/assets/images/icons/black/fullscreen-off.svg delete mode 100644 public/assets/images/icons/black/fullscreen-on.svg delete mode 100644 public/assets/images/icons/blue/focusmode-off.svg delete mode 100644 public/assets/images/icons/blue/fullscreen-off.svg delete mode 100644 public/assets/images/icons/blue/fullscreen-off2.svg delete mode 100644 public/assets/images/icons/blue/fullscreen-off3.svg delete mode 100644 public/assets/images/icons/blue/fullscreen-on.svg delete mode 100644 public/assets/images/icons/blue/fullscreen-on2.svg delete mode 100644 public/assets/images/icons/blue/fullscreen-on3.svg delete mode 100644 public/assets/images/icons/blue/fullscreen-on4.svg delete mode 100644 public/assets/images/icons/blue/fullscreen-on5.svg create mode 100644 public/assets/images/icons/blue/screen-compact.svg create mode 100644 public/assets/images/icons/blue/screen-full.svg create mode 100644 public/assets/images/icons/blue/screen-standard.svg delete mode 100644 public/assets/images/icons/green/focusmode-off.svg delete mode 100644 public/assets/images/icons/green/fullscreen-off.svg delete mode 100644 public/assets/images/icons/green/fullscreen-on.svg delete mode 100644 public/assets/images/icons/grey/focusmode-off.svg delete mode 100644 public/assets/images/icons/grey/fullscreen-off.svg delete mode 100644 public/assets/images/icons/red/focusmode-off.svg delete mode 100644 public/assets/images/icons/red/fullscreen-off.svg delete mode 100644 public/assets/images/icons/red/fullscreen-on.svg delete mode 100644 public/assets/images/icons/white/focusmode-off.svg delete mode 100644 public/assets/images/icons/white/fullscreen-off.svg delete mode 100644 public/assets/images/icons/white/fullscreen-off2.svg delete mode 100644 public/assets/images/icons/white/fullscreen-off3.svg delete mode 100644 public/assets/images/icons/white/fullscreen-on.svg delete mode 100644 public/assets/images/icons/white/fullscreen-on2.svg delete mode 100644 public/assets/images/icons/white/fullscreen-on3.svg delete mode 100644 public/assets/images/icons/white/fullscreen-on4.svg create mode 100644 public/assets/images/icons/white/screen-compact.svg create mode 100644 public/assets/images/icons/white/screen-full.svg create mode 100644 public/assets/images/icons/white/screen-standard.svg delete mode 100644 public/assets/images/icons/yellow/focusmode-off.svg delete mode 100644 public/assets/images/icons/yellow/fullscreen-off.svg delete mode 100644 public/assets/images/icons/yellow/fullscreen-on.svg delete mode 100644 resources/vue/components/responsive/ToggleFullscreen.vue diff --git a/app/views/oer/market/details.php b/app/views/oer/market/details.php index e764d90..60468bb 100644 --- a/app/views/oer/market/details.php +++ b/app/views/oer/market/details.php @@ -336,7 +336,7 @@ if ($material['player_url'] || $material->isVideo() || $material->isPDF()) { $actions->addLink( _('Vollbild aktivieren'), "#", - Icon::create("fullscreen-on", Icon::ROLE_CLICKABLE), + Icon::create('screen-full'), ['onclick' => "STUDIP.OER.requestFullscreen('.lernmarktplatz_player');"] ); } diff --git a/lib/wiki.inc.php b/lib/wiki.inc.php index 6d37e54..f7caafe 100644 --- a/lib/wiki.inc.php +++ b/lib/wiki.inc.php @@ -1028,6 +1028,12 @@ function wikiEdit($keyword, $wikiData, $user_id, $backpage=NULL, $ancestor=NULL) ['data-confirm' => showDeleteDialog($page->keyword, $page->version)] ); } + $actionMenu->addLink( + '#', + _('Als Vollbild anzeigen'), + Icon::create('screen-compact'), + ['class' => 'fullscreen-trigger'] + ); } // Create content bar. @@ -1593,6 +1599,12 @@ function showWikiPage($keyword, $version, $special="", $show_comments="icon", $h ['data-confirm' => showDeleteDialog($page->keyword, $page->version)] ); } + $actionMenu->addLink( + '#', + _('Als Vollbild anzeigen'), + Icon::create('screen-full'), + ['class' => 'fullscreen-trigger'] + ); } // Create content bar. diff --git a/public/assets/images/icons/black/focusmode-off.svg b/public/assets/images/icons/black/focusmode-off.svg deleted file mode 100644 index d7fe2e4..0000000 --- a/public/assets/images/icons/black/focusmode-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/black/fullscreen-off.svg b/public/assets/images/icons/black/fullscreen-off.svg deleted file mode 100644 index d7fe2e4..0000000 --- a/public/assets/images/icons/black/fullscreen-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/black/fullscreen-on.svg b/public/assets/images/icons/black/fullscreen-on.svg deleted file mode 100644 index 9f42af5..0000000 --- a/public/assets/images/icons/black/fullscreen-on.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/blue/focusmode-off.svg b/public/assets/images/icons/blue/focusmode-off.svg deleted file mode 100644 index b7e965a..0000000 --- a/public/assets/images/icons/blue/focusmode-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/blue/fullscreen-off.svg b/public/assets/images/icons/blue/fullscreen-off.svg deleted file mode 100644 index b7e965a..0000000 --- a/public/assets/images/icons/blue/fullscreen-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/blue/fullscreen-off2.svg b/public/assets/images/icons/blue/fullscreen-off2.svg deleted file mode 100644 index c10c1d1..0000000 --- a/public/assets/images/icons/blue/fullscreen-off2.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/blue/fullscreen-off3.svg b/public/assets/images/icons/blue/fullscreen-off3.svg deleted file mode 100644 index 6830b2e..0000000 --- a/public/assets/images/icons/blue/fullscreen-off3.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/blue/fullscreen-on.svg b/public/assets/images/icons/blue/fullscreen-on.svg deleted file mode 100644 index 08c249c..0000000 --- a/public/assets/images/icons/blue/fullscreen-on.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/blue/fullscreen-on2.svg b/public/assets/images/icons/blue/fullscreen-on2.svg deleted file mode 100644 index 16ba091..0000000 --- a/public/assets/images/icons/blue/fullscreen-on2.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/blue/fullscreen-on3.svg b/public/assets/images/icons/blue/fullscreen-on3.svg deleted file mode 100644 index bdaad6d..0000000 --- a/public/assets/images/icons/blue/fullscreen-on3.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/blue/fullscreen-on4.svg b/public/assets/images/icons/blue/fullscreen-on4.svg deleted file mode 100644 index da6502e..0000000 --- a/public/assets/images/icons/blue/fullscreen-on4.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/blue/fullscreen-on5.svg b/public/assets/images/icons/blue/fullscreen-on5.svg deleted file mode 100644 index 8566dec..0000000 --- a/public/assets/images/icons/blue/fullscreen-on5.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/blue/screen-compact.svg b/public/assets/images/icons/blue/screen-compact.svg new file mode 100644 index 0000000..24a3618 --- /dev/null +++ b/public/assets/images/icons/blue/screen-compact.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/images/icons/blue/screen-full.svg b/public/assets/images/icons/blue/screen-full.svg new file mode 100644 index 0000000..23d2d61 --- /dev/null +++ b/public/assets/images/icons/blue/screen-full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/images/icons/blue/screen-standard.svg b/public/assets/images/icons/blue/screen-standard.svg new file mode 100644 index 0000000..05a5dee --- /dev/null +++ b/public/assets/images/icons/blue/screen-standard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/images/icons/green/focusmode-off.svg b/public/assets/images/icons/green/focusmode-off.svg deleted file mode 100644 index b5aa406..0000000 --- a/public/assets/images/icons/green/focusmode-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/green/fullscreen-off.svg b/public/assets/images/icons/green/fullscreen-off.svg deleted file mode 100644 index b5aa406..0000000 --- a/public/assets/images/icons/green/fullscreen-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/green/fullscreen-on.svg b/public/assets/images/icons/green/fullscreen-on.svg deleted file mode 100644 index 38c011b..0000000 --- a/public/assets/images/icons/green/fullscreen-on.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/grey/focusmode-off.svg b/public/assets/images/icons/grey/focusmode-off.svg deleted file mode 100644 index 6509d79..0000000 --- a/public/assets/images/icons/grey/focusmode-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/grey/fullscreen-off.svg b/public/assets/images/icons/grey/fullscreen-off.svg deleted file mode 100644 index 6509d79..0000000 --- a/public/assets/images/icons/grey/fullscreen-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/grey/fullscreen-on.svg b/public/assets/images/icons/grey/fullscreen-on.svg index d2e63bc..4ce992f 100644 --- a/public/assets/images/icons/grey/fullscreen-on.svg +++ b/public/assets/images/icons/grey/fullscreen-on.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/public/assets/images/icons/red/focusmode-off.svg b/public/assets/images/icons/red/focusmode-off.svg deleted file mode 100644 index 9767595..0000000 --- a/public/assets/images/icons/red/focusmode-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/red/fullscreen-off.svg b/public/assets/images/icons/red/fullscreen-off.svg deleted file mode 100644 index 9767595..0000000 --- a/public/assets/images/icons/red/fullscreen-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/red/fullscreen-on.svg b/public/assets/images/icons/red/fullscreen-on.svg deleted file mode 100644 index b592812..0000000 --- a/public/assets/images/icons/red/fullscreen-on.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/white/focusmode-off.svg b/public/assets/images/icons/white/focusmode-off.svg deleted file mode 100644 index f852c7f..0000000 --- a/public/assets/images/icons/white/focusmode-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/white/fullscreen-off.svg b/public/assets/images/icons/white/fullscreen-off.svg deleted file mode 100644 index f852c7f..0000000 --- a/public/assets/images/icons/white/fullscreen-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/white/fullscreen-off2.svg b/public/assets/images/icons/white/fullscreen-off2.svg deleted file mode 100644 index 5c7b0c6..0000000 --- a/public/assets/images/icons/white/fullscreen-off2.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/white/fullscreen-off3.svg b/public/assets/images/icons/white/fullscreen-off3.svg deleted file mode 100644 index d51bf9d..0000000 --- a/public/assets/images/icons/white/fullscreen-off3.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/white/fullscreen-on.svg b/public/assets/images/icons/white/fullscreen-on.svg deleted file mode 100644 index 6c10665..0000000 --- a/public/assets/images/icons/white/fullscreen-on.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/white/fullscreen-on2.svg b/public/assets/images/icons/white/fullscreen-on2.svg deleted file mode 100644 index bc25ed8..0000000 --- a/public/assets/images/icons/white/fullscreen-on2.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/white/fullscreen-on3.svg b/public/assets/images/icons/white/fullscreen-on3.svg deleted file mode 100644 index 0492439..0000000 --- a/public/assets/images/icons/white/fullscreen-on3.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/white/fullscreen-on4.svg b/public/assets/images/icons/white/fullscreen-on4.svg deleted file mode 100644 index 0e406ef..0000000 --- a/public/assets/images/icons/white/fullscreen-on4.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/white/screen-compact.svg b/public/assets/images/icons/white/screen-compact.svg new file mode 100644 index 0000000..6c9415b --- /dev/null +++ b/public/assets/images/icons/white/screen-compact.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/images/icons/white/screen-full.svg b/public/assets/images/icons/white/screen-full.svg new file mode 100644 index 0000000..e721e14 --- /dev/null +++ b/public/assets/images/icons/white/screen-full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/images/icons/white/screen-standard.svg b/public/assets/images/icons/white/screen-standard.svg new file mode 100644 index 0000000..24ff02b --- /dev/null +++ b/public/assets/images/icons/white/screen-standard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/images/icons/yellow/focusmode-off.svg b/public/assets/images/icons/yellow/focusmode-off.svg deleted file mode 100644 index a98b0e0..0000000 --- a/public/assets/images/icons/yellow/focusmode-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/yellow/fullscreen-off.svg b/public/assets/images/icons/yellow/fullscreen-off.svg deleted file mode 100644 index a98b0e0..0000000 --- a/public/assets/images/icons/yellow/fullscreen-off.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/public/assets/images/icons/yellow/fullscreen-on.svg b/public/assets/images/icons/yellow/fullscreen-on.svg deleted file mode 100644 index 3a3d01b..0000000 --- a/public/assets/images/icons/yellow/fullscreen-on.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/resources/assets/javascripts/bootstrap/application.js b/resources/assets/javascripts/bootstrap/application.js index a7101fa..d9175d3 100644 --- a/resources/assets/javascripts/bootstrap/application.js +++ b/resources/assets/javascripts/bootstrap/application.js @@ -365,11 +365,3 @@ jQuery(document).on('click', 'a[data-behaviour~="ajax-toggle"]', function (event $('#open_variable').attr('value', $(this).parent('fieldset').data('open')); }); }(jQuery)); - -// Trigger consuming mode on contentbar -STUDIP.domReady(function () { - $(document).on("click", ".consuming_mode_trigger", function () { - $("body").toggleClass("consuming_mode"); - return false; - }); -}); diff --git a/resources/assets/javascripts/bootstrap/fullscreen.js b/resources/assets/javascripts/bootstrap/fullscreen.js index 2a72173..990eae7 100644 --- a/resources/assets/javascripts/bootstrap/fullscreen.js +++ b/resources/assets/javascripts/bootstrap/fullscreen.js @@ -1,7 +1,26 @@ -STUDIP.domReady(function () { - $('.fullscreen-toggle').click(() => STUDIP.Fullscreen.toggle()); - - if (sessionStorage.getItem('studip-fullscreen') == 'on' && $('.fullscreen-toggle').length > 0) { - STUDIP.Fullscreen.enter(true); - } -}, true); +STUDIP.ready(() => { + $('#fullscreen-on').on('click', event => { + event.preventDefault(); + STUDIP.Vue.emit('toggle-compact-navigation', true); + }); + $('#fullscreen-off').on('click', event => { + event.preventDefault(); + STUDIP.Vue.emit('toggle-compact-navigation', false); + }); + $('#focusmode-on, .fullscreen-trigger').on('click', event => { + event.preventDefault(); + STUDIP.Fullscreen.activate(); + }); + // Listen for fullscreen exit, ending focus mode with it. + document.addEventListener('fullscreenchange', event => { + if (!document.fullscreenElement) { + STUDIP.Fullscreen.deactivate(); + } + }); + // Fullscreen exit on Safari + document.addEventListener('webkitfullscreenchange', event => { + if (!document.webkitFullscreenElement) { + STUDIP.Fullscreen.deactivate(); + } + }); +}); diff --git a/resources/assets/javascripts/bootstrap/responsive.js b/resources/assets/javascripts/bootstrap/responsive.js index 0dd7149..af06f28 100644 --- a/resources/assets/javascripts/bootstrap/responsive.js +++ b/resources/assets/javascripts/bootstrap/responsive.js @@ -2,8 +2,12 @@ STUDIP.domReady(() => { STUDIP.Responsive.engage(); - if (STUDIP.Responsive.isFullscreen()) { - document.querySelector('html').classList.add('fullscreen-mode'); + if (STUDIP.Responsive.isCompactNavigation()) { + document.documentElement.classList.add('fullscreen-mode'); + const sidebar = document.getElementById('sidebar'); + if (sidebar) { + sidebar.style.display = 'none'; + } } }, true); diff --git a/resources/assets/javascripts/bootstrap/sidebar.js b/resources/assets/javascripts/bootstrap/sidebar.js index 01e9d96..92b37d6 100644 --- a/resources/assets/javascripts/bootstrap/sidebar.js +++ b/resources/assets/javascripts/bootstrap/sidebar.js @@ -1,58 +1,4 @@ -function heightChangeHandler() { - var curr_height = $(document).height(); - if (doc_height !== curr_height) { - doc_height = curr_height; - $(document.body).trigger('sticky_kit:recalc'); - } -} - -// Handle dynamic content -if (window.MutationObserver !== undefined) { - // Attach mutation observer to #content and trigger it on - // changes to class and style attributes (which affect the height - // of the content). Trigger a recalculation of the sticky kit when - // a mutation occurs so the sidebar will - $(document).ready(function() { - if ($('#content').length === 0) { - return; - } - var target = $('#content').get(0), - stickyObserver = new window.MutationObserver(function() { - window.requestAnimationFrame(function() { - $(document.body).trigger('sticky_kit:recalc'); - }); - }); - stickyObserver.observe(target, { - attributes: true, - attributeFilter: ['style', 'class'], - characterData: true, - childList: true, - subtree: true - }); - }); -} else { - // Stores document height (we will need this to check for changes) - var doc_height; - - STUDIP.domReady(() => { - doc_height = $(document).height(); - }); - - // Recalculcate positions on ajax and img load events. - // Inside the handlers the current document height is compared - // to the previous height before the event occured so recalculation - // only happens on actual changes - $(document).on('ajaxComplete', heightChangeHandler); - $(document).on('load', '#content img', heightChangeHandler); - - // Specialized handler to trigger recalculation when wysiwyg - // instances are created. - $(document).on('load.wysiwyg', 'textarea', function() { - $(document.body).trigger('sticky_kit:recalc'); - }); -} - -// Engage +// Set correct sidebar height for stickyness STUDIP.domReady(() => { - STUDIP.Sidebar.checkActiveLineHeight(); + STUDIP.Sidebar.adjustHeight(); }); diff --git a/resources/assets/javascripts/lib/fullscreen.js b/resources/assets/javascripts/lib/fullscreen.js index 5d91eb9..16001da 100644 --- a/resources/assets/javascripts/lib/fullscreen.js +++ b/resources/assets/javascripts/lib/fullscreen.js @@ -1,51 +1,27 @@ const Fullscreen = { - toggle () { - if (sessionStorage.getItem('studip-fullscreen') === 'on') { - STUDIP.Fullscreen.leave(); - } else { - STUDIP.Fullscreen.enter(); + activate() { + STUDIP.ActionMenu.closeAll(); + if (document.documentElement.classList.contains('fullscreen-mode')) { + const cache = STUDIP.Cache.getInstance('responsive.'); + cache.set('was-compact-navigation', true); + } + STUDIP.Vue.emit('switch-focus-mode', true); + document.documentElement.classList.remove('fullscreen-mode'); + document.body.classList.add('consuming_mode'); + if (document.body.requestFullscreen) { + document.body.requestFullscreen({ hide: true }); + } else if (document.body.webkitRequestFullscreen) { /* Safari */ + document.body.webkitRequestFullscreen({ hide: true }); } }, - - enter (immediate = false) { - // Set appropriate class on html element to trigger fullscreen mode and - // transisitions - $('html').addClass('is-fullscreen').toggleClass('is-fullscreen-immediately', immediate); - - // Attach key handler that allows keypress on escape to leave fullscreen - $(document).on('keydown.key27', (event) => { - if (event.key === 'Escape') { - STUDIP.Fullscreen.leave(); - } - }); - - // Store indicator in session - sessionStorage.setItem('studip-fullscreen', 'on'); - }, - - leave () { - // Remove indicator from session - sessionStorage.removeItem('studip-fullscreen'); - - // Deactivate key handler - $(document).off('keydown.key27'); - - (new Promise((resolve, reject) => { - var timeout = setTimeout(() => { - $('#sidebar').off('transitionend'); - resolve(); - }, 500); - $('#sidebar').one('transitionend', () => { - clearTimeout(timeout); - resolve(); - }); - })).then(() => { - $(document.body).trigger('sticky_kit:recalc'); - }); - - - // Remove classes on html element - $('html').removeClass('is-fullscreen is-fullscreen-immediately'); + deactivate() { + STUDIP.Vue.emit('switch-focus-mode', false); + document.body.classList.remove('consuming_mode'); + const cache = STUDIP.Cache.getInstance('responsive.'); + if (cache.get('was-compact-navigation')) { + STUDIP.Vue.emit('toggle-compact-navigation', true); + } + cache.remove('was-compact-navigation'); } }; diff --git a/resources/assets/javascripts/lib/responsive.js b/resources/assets/javascripts/lib/responsive.js index a493e8d..ee851fc 100644 --- a/resources/assets/javascripts/lib/responsive.js +++ b/resources/assets/javascripts/lib/responsive.js @@ -26,10 +26,15 @@ const Responsive = { return Responsive.media_query.matches; }, - isFullscreen() { + isCompactNavigation() { const cache = STUDIP.Cache.getInstance('responsive.'); - - return cache.get('fullscreen-mode') ?? false; + let result = false; + if (STUDIP.USER_ID) { + result = cache.get('fullscreen-mode') ?? false; + } else { + cache.remove('fullscreen-mode'); + } + return result; } }; diff --git a/resources/assets/javascripts/lib/sidebar.js b/resources/assets/javascripts/lib/sidebar.js index 8f01d79..d3d67d5 100644 --- a/resources/assets/javascripts/lib/sidebar.js +++ b/resources/assets/javascripts/lib/sidebar.js @@ -18,17 +18,19 @@ const Sidebar = { } }; -Sidebar.checkActiveLineHeight = () => { - $('#sidebar .sidebar-widget-content .widget-links li.active a.active').each(function() { - var link = $(this); - var actual_text = link.text(); - link.text('tmp'); - var default_height = link.outerHeight(); - link.text(actual_text); - var actual_height = link.outerHeight(); - if (actual_height > default_height) { //it is rendered in more lines - link.css('line-height', '20px'); - } - }); +Sidebar.adjustHeight = () => { + const display = $('#sidebar').css('display'); + + if (display === 'none') { + $('#sidebar').css('display', 'block'); + } + const lastWidget = $('.sidebar-widget:last-child'); + if (lastWidget.length > 0) { + const height = lastWidget.offset().top + lastWidget.height(); + $('#sidebar').css('height', height + 'px'); + } + if (display === 'none') { + $('#sidebar').css('display', 'none'); + } } export default Sidebar; diff --git a/resources/assets/stylesheets/scss/contentbar.scss b/resources/assets/stylesheets/scss/contentbar.scss index a4e24af..b85fdf9 100644 --- a/resources/assets/stylesheets/scss/contentbar.scss +++ b/resources/assets/stylesheets/scss/contentbar.scss @@ -119,26 +119,3 @@ } } - -body:not(.consuming_mode) { - .consuming_mode_trigger { - @include icon(before, fullscreen-on, clickable, 24px, 0); - margin-top: -2px; - margin-left: 0 - } -} - -body.consuming_mode { - .contentbar { - margin-left: 10px; - margin-right: 0; - padding-left: 20px; - padding-right: 20px; - } - - .consuming_mode_trigger { - @include icon(before, focusmode-off, clickable, 24px, 0); - margin-top: -2px; - margin-left: 0 - } -} diff --git a/resources/assets/stylesheets/scss/courseware.scss b/resources/assets/stylesheets/scss/courseware.scss index 1eb349a..ccc11bf 100644 --- a/resources/assets/stylesheets/scss/courseware.scss +++ b/resources/assets/stylesheets/scss/courseware.scss @@ -400,14 +400,6 @@ $consum_ribbon_width: calc(100% - 58px); @include background-icon(table-of-contents, clickable, 24); } - &.cw-ribbon-button-zoom { - @include background-icon(fullscreen-on, clickable, 24); - } - - &.cw-ribbon-button-zoom-out { - @include background-icon(focusmode-off, clickable, 24); - } - &.cw-ribbon-button-prev { @include background-icon(arr_1left, clickable, 24); margin: 0 0.5em 0 0; @@ -654,7 +646,7 @@ ribbon end } .cw-container-wrapper { - max-width: 1095px; + max-width: $max-content-width; margin: 0; padding: 0; display: flex; @@ -816,7 +808,7 @@ ribbon end margin-bottom: 1em; &.cw-container-colspan-full { - max-width: 1095px; + max-width: $max-content-width; width: 100%; } &.cw-container-colspan-half { @@ -824,7 +816,7 @@ ribbon end width: 100%; } &.cw-container-colspan-half-center { - width: 1095px; + width: $max-content-width; .cw-container-content { max-width: 540px; margin: auto; @@ -974,7 +966,7 @@ form.cw-container-dialog-edit-form { .cw-container-wrapper-discuss { .cw-container-colspan-full { .cw-content-wrapper { - max-width: 1095px; + max-width: $max-content-width; } } .cw-container-colspan-half, @@ -1064,7 +1056,7 @@ form.cw-container-dialog-edit-form { @media only screen and (max-width: 1820px) { .cw-structural-element .cw-container-wrapper.cw-container-wrapper-discuss { - max-width: 1095px; + max-width: $max-content-width; .cw-container.cw-container-list.cw-container-item.cw-container-colspan-full { .cw-default-block { flex-flow: column; @@ -1079,7 +1071,7 @@ form.cw-container-dialog-edit-form { @media only screen and (max-width: 1200px) { .cw-structural-element .cw-container-wrapper.cw-container-wrapper-discuss { - max-width: 1095px; + max-width: $max-content-width; .cw-container.cw-container-list.cw-container-item.cw-container-colspan-half, .cw-container.cw-container-list.cw-container-item.cw-container-colspan-half-center { .cw-default-block { @@ -2034,7 +2026,7 @@ c o m p a n i o n o v e r l a y .cw-companion-box-wrapper { width: 100%; - max-width: 1095px; + max-width: $max-content-width; } /* * * * * * * * * * * * * * * * * * @@ -2048,9 +2040,6 @@ v i e w w i d g e t .cw-action-widget-show-toc { @include background-icon(table-of-contents, clickable); } - .cw-action-widget-show-consume-mode { - @include background-icon(fullscreen-on, clickable); - } .cw-action-widget-edit{ @include background-icon(edit, clickable); } @@ -2249,7 +2238,7 @@ d a s h b o a r d margin-right: 1em; &.cw-dashboard-box-full { - max-width: 1095px; + max-width: $max-content-width; width: calc(100% - 16px); } &.cw-dashboard-box-half { @@ -2301,7 +2290,7 @@ d a s h b o a r d } .cw-activities-wrapper { - max-width: 1095px; + max-width: $max-content-width; .cw-companion-box { margin: 10px; @@ -4381,7 +4370,7 @@ headline block min-height: 600px; overflow: hidden; background-position: center; - background-size: 1095px; + background-size: $max-content-width; background-repeat: no-repeat; &.half { @@ -5394,5 +5383,5 @@ w i z a r d e l e m e n t s } } /* * * * * * * * * * * * * * * * * * -w i z a r d e l e m e n t s e n d +w i z a r d e l e m e n t s e n d * * * * * * * * * * * * * * * * * */ diff --git a/resources/assets/stylesheets/scss/header.scss b/resources/assets/stylesheets/scss/header.scss index 1f146cf..48cb571 100644 --- a/resources/assets/stylesheets/scss/header.scss +++ b/resources/assets/stylesheets/scss/header.scss @@ -21,7 +21,7 @@ transform: translate(0, 0) !important; // We need !important due to the horizontal scroll handler position: fixed; top: 0; - z-index: 1000; + z-index: 1001; } diff --git a/resources/assets/stylesheets/scss/index.scss b/resources/assets/stylesheets/scss/index.scss index 47d21cb..c5e0059 100644 --- a/resources/assets/stylesheets/scss/index.scss +++ b/resources/assets/stylesheets/scss/index.scss @@ -1,3 +1,7 @@ +body { + min-height: 100%; +} + #main-header { grid-column: 1 / 3; grid-row: 1 / 1; @@ -117,6 +121,11 @@ #index, #login { + + #current-page-structure { + display: none; + } + .messagebox { margin: 50px 0 -25px 50px; width: 418px; diff --git a/resources/assets/stylesheets/scss/layouts.scss b/resources/assets/stylesheets/scss/layouts.scss index 27be3c4..46689d5 100644 --- a/resources/assets/stylesheets/scss/layouts.scss +++ b/resources/assets/stylesheets/scss/layouts.scss @@ -2,12 +2,13 @@ $page-margin: 15px; -$content-width: 400px; -$content-margin: 12px; - $sidebar-padding: 12px; $sidebar-width: 270px; +$content-width: 400px; +$content-margin: 12px; +$max-content-width: 4 * $sidebar-width + $page-margin; + $footer-height: 32px; $site-width: ($page-margin * 2 + $sidebar-width + $sidebar-padding * 2 + $sidebar-border-width * 2 + $content-width + $content-margin * 2); @@ -15,6 +16,11 @@ $page-width: ($sidebar-width + $sidebar-padding * 2 + $sidebar-border-width * 2 $grid-gap: 0; +html { + height: 100vh; + overflow-y: auto; +} + body { background-color: $white; display: grid; @@ -22,6 +28,10 @@ body { grid-row-gap: $grid-gap; grid-template-columns: ($sidebar-width + $sidebar-padding) 1fr; grid-template-rows: auto 1fr $footer-height; + + &::backdrop { + background: $white; + } } #main-header { @@ -214,6 +224,7 @@ body { grid-row: 3 / 4; justify-content: space-between; line-height: $footer-height - 4px; + z-index: 1000; } #main-footer-info { diff --git a/resources/assets/stylesheets/scss/responsive.scss b/resources/assets/stylesheets/scss/responsive.scss index 7610f96..a1e09d4 100644 --- a/resources/assets/stylesheets/scss/responsive.scss +++ b/resources/assets/stylesheets/scss/responsive.scss @@ -11,14 +11,13 @@ $sidebarIn: -15px; $sidebarOut: -330px; #responsive-toggle-desktop, -#responsive-toggle-fullscreen { +#responsive-toggle-fullscreen, +#responsive-toggle-focusmode { display: none; } -#responsive-toggle-fullscreen { - position: relative; - top: 4px; - +#responsive-toggle-fullscreen, +#responsive-toggle-focusmode { img { cursor: pointer; } @@ -35,6 +34,7 @@ $sidebarOut: -330px; } } + #responsive-menu { font-size: $font-size-base; margin-top: 4px; @@ -261,6 +261,10 @@ $sidebarOut: -330px; } } +.cw-ribbon-button-zoom { + display: none; +} + .responsive-display, .fullscreen-mode body:not(.consuming_mode) { @@ -272,7 +276,12 @@ $sidebarOut: -330px; flex: 0; } - #site-title, + #site-title { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + #quicksearch_item, #avatar-menu-container, #current-page-structure { @@ -281,7 +290,7 @@ $sidebarOut: -330px; #header-links { > ul { - > li:not(#responsive-toggle-fullscreen):not(.helpbar-container) { + > li:not(#responsive-toggle-fullscreen):not(#responsive-toggle-focusmode):not(.helpbar-container) { display: none; } @@ -365,6 +374,7 @@ $sidebarOut: -330px; } #responsive-contentbar { + justify-content: stretch; margin-bottom: 15px; padding-bottom: 0.5em; padding-left: 5px; @@ -395,7 +405,7 @@ $sidebarOut: -330px; .contentbar-wrapper-left { flex: 1; - max-width: unset; + min-width: 0; & > .contentbar-icon { margin-right: 15px; @@ -403,12 +413,20 @@ $sidebarOut: -330px; .contentbar-breadcrumb { font-size: $font-size-large; - width: calc(100% - 75px); > img { margin-left: 15px; width: 24px; } + + > span { + display: inline; + flex-shrink: 10000; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } } } @@ -508,27 +526,49 @@ $sidebarOut: -330px; max-height: unset; opacity: 1; overflow: unset; - } - - #responsive-menu { - max-width: calc(100% - 100px); - min-width: calc(100% - 100px); - width: calc(100% - 100px); + width: calc(100% - 20px); } #main-header { flex-basis: 100%; } + #header-links { + margin-left: auto; + + ul { + li { + &:not(#responsive-toggle-fullscreen):not(#responsive-toggle-focusmode) { + padding: 0; + } + + .helpbar-container { + right: 0; + } + } + } + } + + #responsive-toggle-fullscreen, + #responsive-toggle-focusmode { + margin-top: 4px; + padding: 4px 0 0; + } + #responsive-toggle-fullscreen { display: block; - right: 30px; } .contentbar:not(#responsive-contentbar) { display: none; } + #responsive-contentbar-container { + position: fixed; + width: 100vw; + z-index: 1000; + } + #responsive-contentbar { padding-left: 15px; @@ -544,14 +584,17 @@ $sidebarOut: -330px; #content-wrapper { flex: 1; - height: 100%; + margin-top: 75px; + min-height: calc(100vh - 150px); } } } .consuming_mode { display: unset; + overflow-y: auto; + #skip_link_navigation, #main-header, #sidebar, #main-footer, @@ -559,13 +602,29 @@ $sidebarOut: -330px; display: none; } - #content { - height: 100vh; - position: fixed; - width: 100vw; + #content-wrapper { + display: block; + margin-left: auto; + margin-right: auto; + max-width: $max-content-width; + min-height: 100vh; + padding-top: 10px; + } + #content { .contentbar { - margin-right: 30px; + margin: 10px; + padding-left: 20px; + padding-right: 20px; + width: calc(100% - 60px); + + .action-menu { + display: none; + } + } + + .cw-companion-box-wrapper { + padding-top: 120px; } } diff --git a/resources/assets/stylesheets/scss/sidebar.scss b/resources/assets/stylesheets/scss/sidebar.scss index e44196c..a0118e8 100644 --- a/resources/assets/stylesheets/scss/sidebar.scss +++ b/resources/assets/stylesheets/scss/sidebar.scss @@ -4,11 +4,13 @@ display: inline-block; margin-top: 15px; padding: 0 5px 7px 15px; + position: sticky; text-align: left; + top: 50px; z-index: 2; .sidebar-image { - width: $sidebar-width; + width: calc($sidebar-width - 2px); height: 60px; max-height: 60px; @@ -66,7 +68,7 @@ background: $white; border: 1px solid $content-color-40; margin: 15px 0 0; - width: $sidebar-width - 2px; + width: $sidebar-width - 5px; } .sidebar-widget-header { @include clearfix(); diff --git a/resources/assets/stylesheets/studip.less b/resources/assets/stylesheets/studip.less index 97eb904..1cb3da3 100644 --- a/resources/assets/stylesheets/studip.less +++ b/resources/assets/stylesheets/studip.less @@ -19,9 +19,6 @@ /* --- Standardvorgaben ----------------------------------------------------- */ //TODO: the Body-Background color should be similar to A:link.toolbar and A:visited.toolbar for best effect!! -html, body { - height: 100%; -} body { background-color: #d8dadc; background-repeat: repeat-x; diff --git a/resources/assets/stylesheets/studip.scss b/resources/assets/stylesheets/studip.scss index 3e476e6..fb38beb 100644 --- a/resources/assets/stylesheets/studip.scss +++ b/resources/assets/stylesheets/studip.scss @@ -7,6 +7,7 @@ @import "scss/variables"; @import "scss/breakpoints"; @import "scss/visibility"; +@import "scss/layouts"; @import "scss/actionmenu"; @import "scss/activityfeed"; @@ -46,7 +47,6 @@ @import "scss/forum"; @import "scss/gradebook"; @import "scss/grid"; -@import "scss/layouts"; @import "scss/header"; @import "scss/headings"; @import "scss/helpbar"; diff --git a/resources/vue/components/courseware/CoursewareRibbon.vue b/resources/vue/components/courseware/CoursewareRibbon.vue index 7450bf6..ddf5c9b 100644 --- a/resources/vue/components/courseware/CoursewareRibbon.vue +++ b/resources/vue/components/courseware/CoursewareRibbon.vue @@ -21,15 +21,6 @@ @click.prevent="activeToolbar" > -
@@ -112,13 +103,15 @@ export default { }), toggleConsumeMode() { - STUDIP.Vue.emit('toggle-focus-mode', !this.consumeMode); + STUDIP.eventBus.emit('toggle-focus-mode', !this.consumeMode); if (!this.consumeMode) { + document.body.classList.add('consuming_mode'); this.coursewareConsumeMode(true); this.coursewareSelectedToolbarItem('contents'); this.coursewareViewMode('read'); } else { this.coursewareConsumeMode(false); + document.body.classList.remove('consuming_mode'); } }, activeToolbar() { @@ -138,8 +131,17 @@ export default { mounted() { window.addEventListener('scroll', this.handleScroll); if (this.isContentBar) { - STUDIP.Vue.emit('courseware-contentbar-mounted', this); + STUDIP.eventBus.emit('courseware-contentbar-mounted', this); } + + this.globalOn('switch-focus-mode', (state) => { + if (state !== this.consumeMode) { + this.toggleConsumeMode(); + } + }); + }, + beforeDestroy() { + STUDIP.eventBus.off('switch-focus-mode'); }, watch: { toolsActive(newState, oldState) { @@ -157,7 +159,6 @@ export default { } }, consumeMode(newState) { - this.$refs.consumeModeSwitch?.focus(); if (newState) { document.body.classList.add('consuming_mode'); } else { diff --git a/resources/vue/components/courseware/CoursewareStructuralElement.vue b/resources/vue/components/courseware/CoursewareStructuralElement.vue index 5332226..e396bcf 100644 --- a/resources/vue/components/courseware/CoursewareStructuralElement.vue +++ b/resources/vue/components/courseware/CoursewareStructuralElement.vue @@ -63,10 +63,11 @@ @showSuggest="menuAction('showSuggest')" @linkElement="menuAction('linkElement')" @removeLock="menuAction('removeLock')" + @activateFullscreen="menuAction('activateFullscreen')" /> - +
c.id === container.id); - this.assistiveLive = + this.assistiveLive = this.$gettextInterpolate( this.$gettext('%{containerTitle} Abschnitt ausgewählt. Aktuelle Position in der Liste: %{pos} von %{listLength}. Drücken Sie die Aufwärts- und Abwärtspfeiltasten, um die Position zu ändern, die Leertaste zum Ablegen, die Escape-Taste zum Abbrechen.') , {containerTitle: container.attributes.title, pos: index + 1, listLength: this.containerList.length} @@ -1669,7 +1674,7 @@ export default { const container = this.containerById({id: containerId}); const newPos = currentIndex - 1; this.containerList.splice(newPos, 0, this.containerList.splice(currentIndex, 1)[0]); - this.assistiveLive = + this.assistiveLive = this.$gettextInterpolate( this.$gettext('%{containerTitle} Abschnitt. Aktuelle Position in der Liste: %{pos} von %{listLength}.') , {containerTitle: container.attributes.title, pos: newPos + 1, listLength: this.containerList.length} @@ -1682,7 +1687,7 @@ export default { const container = this.containerById({id: containerId}); const newPos = currentIndex + 1; this.containerList.splice(newPos, 0, this.containerList.splice(currentIndex, 1)[0]); - this.assistiveLive = + this.assistiveLive = this.$gettextInterpolate( this.$gettext('%{containerTitle} Abschnitt. Aktuelle Position in der Liste: %{pos} von %{listLength}.') , {containerTitle: container.attributes.title, pos: newPos + 1, listLength: this.containerList.length} @@ -1692,7 +1697,7 @@ export default { abortKeyboardSorting(containerId) { const container = this.containerById({id: containerId}); this.keyboardSelected = null; - this.assistiveLive = + this.assistiveLive = this.$gettextInterpolate( this.$gettext('%{containerTitle} Abschnitt, Neuordnung abgebrochen.') , {containerTitle: container.attributes.title} @@ -1703,7 +1708,7 @@ export default { const container = this.containerById({id: containerId}); const currentIndex = this.containerList.findIndex(container => container.id === containerId); this.keyboardSelected = null; - this.assistiveLive = + this.assistiveLive = this.$gettextInterpolate( this.$gettext('%{containerTitle} Abschnitt, abgelegt. Entgültige Position in der Liste: %{pos} von %{listLength}.') , {containerTitle: container.attributes.title, pos: currentIndex + 1, listLength: this.containerList.length} diff --git a/resources/vue/components/responsive/NavigationItem.vue b/resources/vue/components/responsive/NavigationItem.vue index 0bfd6d2..c227771 100644 --- a/resources/vue/components/responsive/NavigationItem.vue +++ b/resources/vue/components/responsive/NavigationItem.vue @@ -2,7 +2,8 @@
@@ -66,27 +68,44 @@ export default { const sidebar = document.getElementById('sidebar'); const content = document.getElementById('content-wrapper'); const pageTitle = document.getElementById('page-title-container'); - const html = document.querySelector('html'); if (this.sidebarOpen) { sidebar.classList.add('responsive-hide'); sidebar.classList.remove('responsive-show'); - if (html.classList.contains('responsive-display') && !html.classList.contains('fullscreen-mode')) { + if (document.documentElement.classList.contains('responsive-display') + && !document.documentElement.classList.contains('fullscreen-mode')) { content.style.display = null; pageTitle.style.display = null; } + if (!document.documentElement.classList.contains('responsive-display')) { + document.body.style.display = 'flex'; + } + + // Hide sidebar after slide-out animation has ended so that it isn't focusable anymore. + setTimeout(() => { + sidebar.style.display = 'none'; + }, 301); + this.sidebarOpen = false; } else { + sidebar.style.display = ''; + sidebar.classList.add('responsive-show'); sidebar.classList.remove('responsive-hide'); - if (html.classList.contains('responsive-display') && !html.classList.contains('fullscreen-mode')) { + if (document.documentElement.classList.contains('responsive-display') + && !document.documentElement.classList.contains('fullscreen-mode')) { // 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')) { + document.body.style.display = 'grid'; + } + this.sidebarOpen = true; } @@ -155,6 +174,8 @@ export default { 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'; @@ -165,6 +186,8 @@ export default { 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'; @@ -180,7 +203,9 @@ export default { }) // Use courseware contentbar instead of this Vue component. - STUDIP.Vue.on('courseware-contentbar-mounted', element => { + 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'; @@ -192,18 +217,21 @@ export default { }); }) - STUDIP.Vue.on('toggle-focus-mode', (state) => { + 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'); } } diff --git a/resources/vue/components/responsive/ResponsiveNavigation.vue b/resources/vue/components/responsive/ResponsiveNavigation.vue index 0942021..3f4d163 100644 --- a/resources/vue/components/responsive/ResponsiveNavigation.vue +++ b/resources/vue/components/responsive/ResponsiveNavigation.vue @@ -3,8 +3,9 @@
-
- + @@ -109,13 +114,12 @@ import NavigationItem from './NavigationItem.vue'; import StudipIcon from '../StudipIcon.vue'; import ResponsiveContentBar from './ResponsiveContentBar.vue'; -import ToggleFullscreen from './ToggleFullscreen.vue'; import ResponsiveSkipLinks from './ResponsiveSkipLinks.vue'; import { FocusTrap } from 'focus-trap-vue'; export default { name: 'ResponsiveNavigation', - components: { ResponsiveContentBar, StudipIcon, NavigationItem, ToggleFullscreen, ResponsiveSkipLinks, FocusTrap }, + components: { ResponsiveContentBar, StudipIcon, NavigationItem, ResponsiveSkipLinks, FocusTrap }, props: { me: { type: Object, @@ -154,7 +158,9 @@ export default { avatarNavigation: studipNavigation.avatar, avatarMenuOpen: false, observer: null, - hasSkiplinks: document.querySelector('#skiplink_list') !== null + hasSkiplinks: document.querySelector('#skiplink_list') !== null, + hasContentbar: false, + contentbarTitle: '' } }, computed: { @@ -183,10 +189,6 @@ export default { ]; if (this.isFullscreen) { - links.push( - { url: '#toggle-fullscreen', label: this.$gettext('Vollbildmodus verlassen') }, - ); - if (this.hasSidebar) { let name = ''; if (document.getElementById('sidebar').classList.contains('responsive-show')) { @@ -272,6 +274,10 @@ export default { this.showMenu = !this.showMenu; + if (!this.showMenu && this.avatarMenuOpen) { + this.toggleAvatarMenu(); + } + this.$nextTick(() => { if (this.showMenu && !this.headerMagic) { this.currentNavigation = this.initialNavigation; @@ -286,22 +292,41 @@ export default { }) }, /** - * Turn fullscreen mode on or off + * Turn compact navigation mode on or off * @param state */ - setFullscreen(state) { - const html = document.querySelector('html'); + setCompactNavigation(state) { const sidebar = document.getElementById('sidebar'); const cache = STUDIP.Cache.getInstance('responsive.'); if (state) { - html.classList.add('fullscreen-mode'); + if (this.hasContentbar) { + document.getElementById('responsive-toggle-focusmode').style.display = 'block'; + } + document.documentElement.classList.add('fullscreen-mode'); cache.set('fullscreen-mode', true); + + const siteTitle = document.getElementById('site-title'); + siteTitle.dataset.originalTitle = siteTitle.textContent.trim(); + siteTitle.textContent = this.initialTitle; + + sidebar.style.display = 'none'; + } else { - html.classList.remove('fullscreen-mode'); - sidebar.classList.remove('responsive-show', 'fullscreen-mode'); + document.documentElement.classList.remove('fullscreen-mode'); + sidebar?.classList.remove('responsive-show', 'fullscreen-mode'); this.showMenu = false; cache.remove('fullscreen-mode'); + document.getElementById('responsive-toggle-focusmode').style.display = 'none'; + document.body.style.display = null; + + const siteTitle = document.getElementById('site-title'); + if (siteTitle.dataset.originalTitle) { + siteTitle.textContent = siteTitle.dataset.originalTitle.trim(); + } + + sidebar.style.display = ''; + } this.isFullscreen = state; @@ -321,10 +346,10 @@ export default { this.avatarMenuOpen = false; this.currentNavigation = this.findItem(path ? path : '/', this.studipNavigation); this.$nextTick(() => { - const current = document.querySelector('.navigation-current') ?? document.querySelector('.navigation-item'); - if (current) { - current.focus(); - } + const current = document.querySelector('.navigation-current') + ? document.querySelector('.navigation-current .navigation-title button') + : document.querySelector('.navigation-item .navigation-title a'); + current.focus(); }) }, /** @@ -364,6 +389,13 @@ export default { */ toggleAvatarMenu() { this.avatarMenuOpen = !this.avatarMenuOpen; + + // Focus first menu entry. + if (this.avatarMenuOpen) { + this.$nextTick(() => { + document.querySelector('.avatar-navigation .navigation-item .navigation-title a').focus(); + }); + } }, onChangeViewMode(tagName, classes) { const classList = classes.split(' '); @@ -373,19 +405,19 @@ export default { case 'BODY': if (classList.includes('consuming_mode')) { this.isFocusMode = true; - STUDIP.Vue.emit('consuming-mode-enabled'); - this.setFullscreen(false); + STUDIP.eventBus.emit('consuming-mode-enabled'); + this.setCompactNavigation(false); } else { this.isFocusMode = false; - STUDIP.Vue.emit('consuming-mode-disabled'); + STUDIP.eventBus.emit('consuming-mode-disabled'); } if (classList.includes('fixed')) { this.headerMagic = true; - STUDIP.Vue.emit('header-magic-enabled'); + STUDIP.eventBus.emit('header-magic-enabled'); } else { this.headerMagic = false; this.showMenu = false; - STUDIP.Vue.emit('header-magic-disabled'); + STUDIP.eventBus.emit('header-magic-disabled'); } break; // Watch for "responsive-display" and "fullscreen-mode" class changes @@ -394,16 +426,16 @@ export default { this.isResponsive = true; if (classList.includes('fullscreen-mode')) { - this.setFullscreen(false); + this.setCompactNavigation(false); } - STUDIP.Vue.emit('responsive-display-enabled'); + STUDIP.eventBus.emit('responsive-display-enabled'); this.$nextTick(() => { this.moveHelpbar(); }) } else { this.isResponsive = false; - STUDIP.Vue.emit('responsive-display-disabled'); + STUDIP.eventBus.emit('responsive-display-disabled'); this.$nextTick(() => { this.moveHelpbar(); }) @@ -412,10 +444,12 @@ export default { if (classList.includes('fullscreen-mode')) { this.isFullscreen = true; - STUDIP.Vue.emit('fullscreen-enabled'); + STUDIP.eventBus.emit('fullscreen-enabled'); + document.getElementById('sidebar').style.display = 'none'; } else { this.isFullscreen = false; - STUDIP.Vue.emit('fullscreen-disabled'); + STUDIP.eventBus.emit('fullscreen-disabled'); + document.getElementById('sidebar').style.display = ''; } break; case 'HEADER': @@ -437,7 +471,7 @@ export default { return navigation.navigation; }, captureOutsideClick(target) { - if (target !== null) { + if (this.showMenu && target !== null) { if (!this.$refs.container.contains(target)) { this.toggleMenu(); } @@ -458,26 +492,27 @@ export default { }, mounted() { const cache = STUDIP.Cache.getInstance('responsive.'); - const html = document.querySelector('html'); - const body = document.querySelector('body'); const fullscreen = cache.get('fullscreen-mode') ?? false; - const fullscreenDocument = html.classList.contains('fullscreen-mode'); - - this.isFullscreen = fullscreenDocument || fullscreen; - if (this.isFullscreen && !fullscreenDocument) { - html.classList.add('fullscreen-mode'); - } + const fullscreenDocument = document.documentElement.classList.contains('fullscreen-mode'); - if (html.classList.contains('responsive-display')) { + if (document.documentElement.classList.contains('responsive-display')) { this.isResponsive = true; } + this.isFullscreen = !this.isResponsive && (fullscreenDocument || fullscreen); + if (this.isFullscreen && !fullscreenDocument) { + this.setCompactNavigation(true); + } // Re-structure some DOM elements this.$nextTick(() => { if (this.isResponsive || (this.isFullscreen && !this.isFocusMode)) { this.moveHelpbar(); - } + this.contentbarTitle = document.querySelector('.sidebar-image .sidebar-title').textContent; + const siteTitle = document.getElementById('site-title'); + siteTitle.dataset.originalTitle = siteTitle.textContent.trim(); + siteTitle.textContent = this.initialTitle; + } }); // Pressing escape should close an open navigation. @@ -490,13 +525,13 @@ export default { this.initialNavigation = this.currentNavigation; this.initialTitle = this.initialNavigation.title; - STUDIP.Vue.on('responsive-navigation-move-to', path => { + this.globalOn('responsive-navigation-move-to', path => { this.moveTo(path); }); // Listen to changes in fullscreen setting - STUDIP.Vue.on('toggle-fullscreen', value => { - this.setFullscreen(value); + this.globalOn('toggle-compact-navigation', value => { + this.setCompactNavigation(value); }); /* @@ -511,21 +546,31 @@ export default { }); // Observe for class changes. - this.observer.observe(html, { + this.observer.observe(document.documentElement, { attributes: true, attributeOldValue : false, attributeFilter: ['class'] }); // Observe for class changes. - this.observer.observe(body, { + this.observer.observe(document.body, { attributes: true, attributeOldValue : false, attributeFilter: ['class'] }); + this.globalOn('has-contentbar', value => { + this.hasContentbar = value; + if (value && this.isFullscreen) { + document.getElementById('responsive-toggle-focusmode').style.display = 'block'; + } + }); + // Observe courseware contentbar for consuming mode. - STUDIP.Vue.on('courseware-ribbon-mounted', element => { + this.globalOn('courseware-contentbar-mounted', element => { + if (this.isFullscreen) { + document.getElementById('responsive-toggle-focusmode').style.display = 'block'; + } this.observer.observe(element.$el.querySelector('header.cw-ribbon'), { attributes: true, attributeOldValue : false, @@ -536,6 +581,10 @@ export default { beforeDestroy() { this.observer.disconnect(); document.getElementById('header-links').style.display = null; + STUDIP.eventBus.off('responsive-navigation-move-to'); + STUDIP.eventBus.off('toggle-compact-navigation'); + STUDIP.eventBus.off('has-contentbar'); + STUDIP.eventBus.off('courseware-contentbar-mounted'); } } diff --git a/resources/vue/components/responsive/ResponsiveSkipLinks.vue b/resources/vue/components/responsive/ResponsiveSkipLinks.vue index 52f0bfc..7668191 100644 --- a/resources/vue/components/responsive/ResponsiveSkipLinks.vue +++ b/resources/vue/components/responsive/ResponsiveSkipLinks.vue @@ -37,7 +37,7 @@ export default { allButtons.forEach(button => { document.getElementById('skiplink_list').appendChild(button.parentNode); }); - }) + }); }, beforeDestroy() { const buttons = document.querySelectorAll('button.skiplink:not([data-in-fullscreen="1"])'); diff --git a/resources/vue/components/responsive/ToggleFullscreen.vue b/resources/vue/components/responsive/ToggleFullscreen.vue deleted file mode 100644 index 77ce8fb..0000000 --- a/resources/vue/components/responsive/ToggleFullscreen.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - diff --git a/templates/contentbar/contentbar.php b/templates/contentbar/contentbar.php index 9183516..a6e51a3 100644 --- a/templates/contentbar/contentbar.php +++ b/templates/contentbar/contentbar.php @@ -23,11 +23,6 @@ -
- -
-
render() ?> diff --git a/templates/header.php b/templates/header.php index d49b8ef..51620ce 100644 --- a/templates/header.php +++ b/templates/header.php @@ -203,7 +203,18 @@ if ($navigation) { -
  • +
  • + +
  • +
  • + +
  • diff --git a/templates/tabs.php b/templates/tabs.php index 0072705..e5b00a4 100644 --- a/templates/tabs.php +++ b/templates/tabs.php @@ -43,5 +43,12 @@ foreach (Navigation::getItem("/")->getSubNavigation() as $path => $nav) { have_perm('autor')) : ?> render() ?> -
    + +
    + +
    + -- cgit v1.0