From de40a8fce2d2e70b747ba33c640700e23111fb26 Mon Sep 17 00:00:00 2001 From: Stefan Topfstedt Date: Sat, 9 Mar 2024 14:55:45 -0800 Subject: [PATCH] fixes up back-to-top button for M4.3 see the GH issue tracker for moodle_an_hochschulen/moodle-theme_boost_union, ticket number 419 for details. --- amd/build/backtotopbutton.min.js | 2 +- amd/build/backtotopbutton.min.js.map | 2 +- amd/src/backtotopbutton.js | 28 ++++++++++--- scss/components/backtotopbutton.scss | 62 +++++++++++++++++++--------- 4 files changed, 68 insertions(+), 26 deletions(-) diff --git a/amd/build/backtotopbutton.min.js b/amd/build/backtotopbutton.min.js index 6d81bae5..835e2536 100644 --- a/amd/build/backtotopbutton.min.js +++ b/amd/build/backtotopbutton.min.js @@ -8,6 +8,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @link https://moodle.org/plugins/theme_boost_union */ -define("theme_ucsf/backtotopbutton",["jquery","core/str","core/notification"],(function($,str,Notification){let buttonShown=!1;function initBackToTop(){let stringsPromise=str.get_string("backtotop","theme_ucsf");$.when(stringsPromise).then((function(string){return $("#page-footer").after(''),$("#page").on("scroll",(function(){$("#page").scrollTop()>220?!1===buttonShown&&$("#back-to-top").fadeIn(300,(function(){buttonShown=!0})):!0===buttonShown&&$("#back-to-top").fadeOut(100,(function(){buttonShown=!1}))})),$("#back-to-top").on("click",(function(event){event.preventDefault(),$("#page").animate({scrollTop:0},500),$("#back-to-top").blur()})),!0})).fail(Notification.exception)}return{init:function(){initBackToTop()}}})); +define("theme_ucsf/backtotopbutton",["jquery","core/str","core/notification"],(function($,str,Notification){let buttonShown=!1;function checkAndHide(){!0===buttonShown&&$("#back-to-top").fadeOut(100,(function(){buttonShown=!1}))}function checkAndShow(){!1===buttonShown&&$("#back-to-top").fadeIn(300,(function(){buttonShown=!0}))}return{init:function(){!function(){let stringsPromise=str.get_string("backtotop","theme_ucsf");$.when(stringsPromise).then((function(string){return $("#page-footer").after(''),$(window).scrollTop()>220?checkAndShow():checkAndHide(),$(window).on("scroll",(function(){$(window).scrollTop()>220?checkAndShow():checkAndHide()})),$("#back-to-top").on("click",(function(event){event.preventDefault(),$("html, body").animate({scrollTop:0},500),$("#back-to-top").blur()})),$("#page-footer .btn-footer-communication").length&&$("body").addClass("theme-ucsf-commincourse"),!0})).fail(Notification.exception)}()}}})); //# sourceMappingURL=backtotopbutton.min.js.map \ No newline at end of file diff --git a/amd/build/backtotopbutton.min.js.map b/amd/build/backtotopbutton.min.js.map index 8ee0fc78..282b3b5c 100644 --- a/amd/build/backtotopbutton.min.js.map +++ b/amd/build/backtotopbutton.min.js.map @@ -1 +1 @@ -{"version":3,"file":"backtotopbutton.min.js","sources":["../src/backtotopbutton.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * JS code back to top button.\n *\n * @module theme_ucsf/backtotopbutton\n * @copyright 2022 Alexander Bias, lern.link GmbH \n * @copyright on behalf of Zurich University of Applied Sciences (ZHAW)\n * @copyright based on code from theme_boost_campus by Kathrin Osswald.\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @link https://moodle.org/plugins/theme_boost_union\n */\n\ndefine(['jquery', 'core/str', 'core/notification'], function($, str, Notification) {\n \"use strict\";\n\n // Remember if the back to top button is shown currently.\n let buttonShown = false;\n\n /**\n * Initializing.\n */\n function initBackToTop() {\n // Get the string backtotop from language file.\n let stringsPromise = str.get_string('backtotop', 'theme_ucsf');\n\n // If the string has arrived, add backtotop button to DOM and add scroll and click handlers.\n $.when(stringsPromise).then(function(string) {\n // Add a fontawesome icon after the footer as the back to top button.\n $('#page-footer').after('');\n\n // This function fades the button in when the page is scrolled down or fades it out\n // if the user is at the top of the page again.\n // Please note that Boost in Moodle 4.0 does not scroll the window object / whole body tag anymore,\n // it scrolls the #page element instead.\n $('#page').on('scroll', function() {\n if ($('#page').scrollTop() > 220) {\n checkAndShow();\n } else {\n checkAndHide();\n }\n });\n\n // This function scrolls the page to top with a duration of 500ms.\n $('#back-to-top').on('click', function(event) {\n event.preventDefault();\n $('#page').animate({scrollTop: 0}, 500);\n $('#back-to-top').blur();\n });\n\n return true;\n }).fail(Notification.exception);\n }\n\n /**\n * Helper function to handle the button visibility when the page is scrolling up.\n */\n function checkAndHide() {\n // Check if the button is still shown.\n if (buttonShown === true) {\n // Fade it out and remember the status in the end.\n // To be precise, the faceOut() function will be called multiple times as buttonShown is not set until the button is\n // really faded out. However, as soon as it is faded out, it won't be called until the button is shown again.\n $('#back-to-top').fadeOut(100, function() {\n buttonShown = false;\n });\n }\n }\n\n /**\n * Helper function to handle the button visibility when the page is scrolling down.\n */\n function checkAndShow() {\n // Check if the button is not yet shown.\n if (buttonShown === false) {\n // Fade it in and remember the status in the end.\n $('#back-to-top').fadeIn(300, function() {\n buttonShown = true;\n });\n }\n }\n\n return {\n init: function() {\n initBackToTop();\n }\n };\n});\n"],"names":["define","$","str","Notification","buttonShown","initBackToTop","stringsPromise","get_string","when","then","string","after","on","scrollTop","fadeIn","fadeOut","event","preventDefault","animate","blur","fail","exception","init"],"mappings":";;;;;;;;;;AA0BAA,oCAAO,CAAC,SAAU,WAAY,sBAAsB,SAASC,EAAGC,IAAKC,kBAI/DC,aAAc,WAKTC,oBAEHC,eAAiBJ,IAAIK,WAAW,YAAa,cAGjDN,EAAEO,KAAKF,gBAAgBG,MAAK,SAASC,eAEnCT,EAAE,gBAAgBU,MAAM,qGAELD,OAFK,yEASxBT,EAAE,SAASW,GAAG,UAAU,WAClBX,EAAE,SAASY,YAAc,KAsCb,IAAhBT,aAEFH,EAAE,gBAAgBa,OAAO,KAAK,WAC5BV,aAAc,MAlBE,IAAhBA,aAIFH,EAAE,gBAAgBc,QAAQ,KAAK,WAC7BX,aAAc,QApBhBH,EAAE,gBAAgBW,GAAG,SAAS,SAASI,OACrCA,MAAMC,iBACNhB,EAAE,SAASiB,QAAQ,CAACL,UAAW,GAAI,KACnCZ,EAAE,gBAAgBkB,WAGb,KACNC,KAAKjB,aAAakB,iBA+BhB,CACLC,KAAM,WACJjB"} \ No newline at end of file +{"version":3,"file":"backtotopbutton.min.js","sources":["../src/backtotopbutton.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * JS code back to top button.\n *\n * @module theme_ucsf/backtotopbutton\n * @copyright 2022 Alexander Bias, lern.link GmbH \n * @copyright on behalf of Zurich University of Applied Sciences (ZHAW)\n * @copyright based on code from theme_boost_campus by Kathrin Osswald.\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @link https://moodle.org/plugins/theme_boost_union\n */\n\ndefine(['jquery', 'core/str', 'core/notification'], function($, str, Notification) {\n \"use strict\";\n\n // Remember if the back to top button is shown currently.\n let buttonShown = false;\n\n /**\n * Initializing.\n */\n function initBackToTop() {\n // Define the scroll distance after which the button will be shown.\n const scrolldistance = 220;\n\n // Get the string backtotop from language file.\n let stringsPromise = str.get_string('backtotop', 'theme_ucsf');\n\n // If the string has arrived, add backtotop button to DOM and add scroll and click handlers.\n $.when(stringsPromise).then(function(string) {\n // Add a fontawesome icon after the footer as the back to top button.\n $('#page-footer').after('');\n\n // Check directly if the button should be shown.\n // This is helpful for all cases when this code here runs _after_ the page has been scrolled,\n // especially by the scrollspy feature or by a simple browser page reload.\n if ($(window).scrollTop() > scrolldistance) {\n checkAndShow();\n } else {\n checkAndHide();\n }\n\n // This function fades the button in when the page is scrolled down or fades it out\n // if the user is at the top of the page again.\n $(window).on('scroll', function() {\n if ($(window).scrollTop() > scrolldistance) {\n checkAndShow();\n } else {\n checkAndHide();\n }\n });\n\n // This function scrolls the page to top with a duration of 500ms.\n $('#back-to-top').on('click', function(event) {\n event.preventDefault();\n $('html, body').animate({scrollTop: 0}, 500);\n $('#back-to-top').blur();\n });\n\n // This will check if there is a communication button shown on the page already.\n // If yes, it will add a class to the body tag which will be later used to align the back-to-top button\n // with the communications button.\n // This is necessary as the communications button would otherwise be overlaid by the back-to-top button.\n if ($('#page-footer .btn-footer-communication').length) {\n $('body').addClass('theme-ucsf-commincourse');\n }\n\n return true;\n }).fail(Notification.exception);\n }\n\n /**\n * Helper function to handle the button visibility when the page is scrolling up.\n */\n function checkAndHide() {\n // Check if the button is still shown.\n if (buttonShown === true) {\n // Fade it out and remember the status in the end.\n // To be precise, the faceOut() function will be called multiple times as buttonShown is not set until the button is\n // really faded out. However, as soon as it is faded out, it won't be called until the button is shown again.\n $('#back-to-top').fadeOut(100, function() {\n buttonShown = false;\n });\n }\n }\n\n /**\n * Helper function to handle the button visibility when the page is scrolling down.\n */\n function checkAndShow() {\n // Check if the button is not yet shown.\n if (buttonShown === false) {\n // Fade it in and remember the status in the end.\n $('#back-to-top').fadeIn(300, function() {\n buttonShown = true;\n });\n }\n }\n\n return {\n init: function() {\n initBackToTop();\n }\n };\n});\n"],"names":["define","$","str","Notification","buttonShown","checkAndHide","fadeOut","checkAndShow","fadeIn","init","stringsPromise","get_string","when","then","string","after","window","scrollTop","on","event","preventDefault","animate","blur","length","addClass","fail","exception","initBackToTop"],"mappings":";;;;;;;;;;AA0BAA,oCAAO,CAAC,SAAU,WAAY,sBAAsB,SAASC,EAAGC,IAAKC,kBAI/DC,aAAc,WA6DTC,gBAEa,IAAhBD,aAIFH,EAAE,gBAAgBK,QAAQ,KAAK,WAC7BF,aAAc,cAQXG,gBAEa,IAAhBH,aAEFH,EAAE,gBAAgBO,OAAO,KAAK,WAC5BJ,aAAc,WAKb,CACLK,KAAM,2BA7EFC,eAAiBR,IAAIS,WAAW,YAAa,cAGjDV,EAAEW,KAAKF,gBAAgBG,MAAK,SAASC,eAEnCb,EAAE,gBAAgBc,MAAM,qGAELD,OAFK,yEAQpBb,EAAEe,QAAQC,YAhBO,IAiBnBV,eAEAF,eAKFJ,EAAEe,QAAQE,GAAG,UAAU,WACjBjB,EAAEe,QAAQC,YAzBK,IA0BjBV,eAEAF,kBAKJJ,EAAE,gBAAgBiB,GAAG,SAAS,SAASC,OACrCA,MAAMC,iBACNnB,EAAE,cAAcoB,QAAQ,CAACJ,UAAW,GAAI,KACxChB,EAAE,gBAAgBqB,UAOhBrB,EAAE,0CAA0CsB,QAC9CtB,EAAE,QAAQuB,SAAS,4BAGd,KACNC,KAAKtB,aAAauB,WAiCnBC"} \ No newline at end of file diff --git a/amd/src/backtotopbutton.js b/amd/src/backtotopbutton.js index 98fd445d..bbfe4e9c 100644 --- a/amd/src/backtotopbutton.js +++ b/amd/src/backtotopbutton.js @@ -34,6 +34,9 @@ define(['jquery', 'core/str', 'core/notification'], function($, str, Notificatio * Initializing. */ function initBackToTop() { + // Define the scroll distance after which the button will be shown. + const scrolldistance = 220; + // Get the string backtotop from language file. let stringsPromise = str.get_string('backtotop', 'theme_ucsf'); @@ -45,12 +48,19 @@ define(['jquery', 'core/str', 'core/notification'], function($, str, Notificatio 'aria-label="' + string + '">' + ''); + // Check directly if the button should be shown. + // This is helpful for all cases when this code here runs _after_ the page has been scrolled, + // especially by the scrollspy feature or by a simple browser page reload. + if ($(window).scrollTop() > scrolldistance) { + checkAndShow(); + } else { + checkAndHide(); + } + // This function fades the button in when the page is scrolled down or fades it out // if the user is at the top of the page again. - // Please note that Boost in Moodle 4.0 does not scroll the window object / whole body tag anymore, - // it scrolls the #page element instead. - $('#page').on('scroll', function() { - if ($('#page').scrollTop() > 220) { + $(window).on('scroll', function() { + if ($(window).scrollTop() > scrolldistance) { checkAndShow(); } else { checkAndHide(); @@ -60,10 +70,18 @@ define(['jquery', 'core/str', 'core/notification'], function($, str, Notificatio // This function scrolls the page to top with a duration of 500ms. $('#back-to-top').on('click', function(event) { event.preventDefault(); - $('#page').animate({scrollTop: 0}, 500); + $('html, body').animate({scrollTop: 0}, 500); $('#back-to-top').blur(); }); + // This will check if there is a communication button shown on the page already. + // If yes, it will add a class to the body tag which will be later used to align the back-to-top button + // with the communications button. + // This is necessary as the communications button would otherwise be overlaid by the back-to-top button. + if ($('#page-footer .btn-footer-communication').length) { + $('body').addClass('theme-ucsf-commincourse'); + } + return true; }).fail(Notification.exception); } diff --git a/scss/components/backtotopbutton.scss b/scss/components/backtotopbutton.scss index b209c472..bedcfcc0 100644 --- a/scss/components/backtotopbutton.scss +++ b/scss/components/backtotopbutton.scss @@ -1,5 +1,7 @@ /*--------------------------------------- * Setting: Back to top button. + * Copied and adjusted from Boost Union theme. + * @see https://github.com/moodle-an-hochschulen/moodle-theme_boost_union --------------------------------------*/ #back-to-top { @@ -8,36 +10,58 @@ /* Place the back to top button at a fixed place. */ position: fixed; right: 2rem; - /* As a start = on really small screens, the back to top button is shown in the bottom right corner. */ - bottom: 2rem; - /* On larger screens, there is the footer button already in the bottom right corner and - the back to top button has to be shown above of the footer button. */ - @include media-breakpoint-up(sm) { - bottom: 5rem; - } + /* As a start, the back to top button is shown in the bottom right corner. */ + bottom: 5rem; /* Make sure that the back to top button is not covered by anything else. */ z-index: $zindex-dropdown; /* Animate position together with footer button. */ @include transition(0.2s); } - +/* If the sticky footer is shown by Moodle core, the back to top button has to have a higher starting position. */ +body.hasstickyfooter #back-to-top { + bottom: 10rem; +} #back-to-top i::before { /* Move the caret icon slightly up for a nicer look. */ vertical-align: 0.3rem; } -#page.drawers.show-drawer-right #back-to-top { - /* Move the back to top button when right drawer is shown. */ - right: calc(#{$drawer-right-width} + 2rem); -} +/* If the communications button is shown, the back to top button has to be moved more upwards. + To realize this, our back-to-top JS has added a class to the body tag. */ +body.theme-ucsf-commincourse { + /* If we are on a small screen, + we do not need to do anything (yet) as the communication button is not shown on small screens (yet). */ -/* As soon as the sticky footer is shown (especially in the database activity), - the back to top button has to be moved further up. - Again, we have to distinguish between really small screens and larger screens - (where the fotter button is shown as well). */ -body.hasstickyfooter #back-to-top { - bottom: 5rem; + /* We have to move the back to top button even more upwards.*/ @include media-breakpoint-up(sm) { - bottom: 9rem; + #back-to-top { + bottom: 8rem; + } + } + + /* And if the sticky footer is shown by Moodle core, move the back to top button more upwards. */ + body.hasstickyfooter { + @include media-breakpoint-up(sm) { + #back-to-top { + bottom: 13rem; + } + } } } + +/* If the right-hand drawer is opened. */ +#page.drawers.show-drawer-right #back-to-top { + /* On larger screens, the drawer opens near the main content. + The back to top button can be moved nicely to the left. */ + @include media-breakpoint-up(lg) { + /* Move the back to top button when right drawer is shown. */ + right: calc(#{$drawer-right-width} + 2rem); + } + /* On smaller screens, the drawer opens as an overlay over the main content. + The back to top button looks misplaced then. */ + @include media-breakpoint-down(lg) { + /* Hide the back to top button when right drawer is shown. */ + display: none; + } +} +