diff --git a/CHANGES.md b/CHANGES.md index ce82f9ce479..f042158af69 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ Changes ### Unreleased +* 2023-12-28 - Feature: Add slider which can be displayed on site home, solves #162. * 2023-12-27 - Improvement: Add content style setting to the advertisement tiles, solves #519. * 2023-12-27 - Test: Always reactivate debugging during Behat tests, solves #521. * 2023-12-26 - Improvement: Do not add the advertisement tiles div to the frontpage if no tile is activated, solves #516. diff --git a/README.md b/README.md index 103114b763c..a2a10965555 100644 --- a/README.md +++ b/README.md @@ -467,6 +467,10 @@ In this tab, you can enable and configure multiple information banners to be sho In this tab, you can enable and configure multiple advertisement tiles to be shown on site home. +#### Tab "Slider" + +In this tab, you can enable and configure multiple slides to be shown on site home. + ### Settings page "Functionality" #### Tab "Courses" @@ -666,8 +670,9 @@ Moodle an Hochschulen e.V. would like to thank these main contributors (in alpha * Käferfreie Software, Nina Herrmann: Code * lern.link GmbH, Alexander Bias: Code, Peer Review, Ideating, Funding * lern.link GmbH, Beata Waloszczyk: Code -* Moodle.NRW / Ruhr University Bochum, Tim Trappen: Code, Ideating +* Moodle.NRW / Ruhr University Bochum, Annika Lambert: Code * Moodle.NRW / Ruhr University Bochum, Matthias Buttgereit: Code, Ideating +* Moodle.NRW / Ruhr University Bochum, Tim Trappen: Code, Ideating * moodleSCHULE e.V., Ralf Krause: German translation and curation, Ideating * Ruhr University Bochum, Melanie Treitinger: Code, Ideating * RWTH Aachen, Amrita Deb Dutta: Code diff --git a/lang/en/theme_boost_union.php b/lang/en/theme_boost_union.php index 87ec767ca7c..89c15052ed5 100644 --- a/lang/en/theme_boost_union.php +++ b/lang/en/theme_boost_union.php @@ -746,6 +746,71 @@ $string['tileordersetting_desc'] = 'With this setting, you define the order position of the advertisement tile {$a->no}. By default, the advertisement tiles are ordered from top to bottom and left to right like you see them on this settings page here. However, you can decide to assign another order position with this setting. If you assign the same order position to two or more advertisement tiles, they will be ordered again according to the order on this settings page.'; $string['tiletitlesetting'] = 'Advertisement tile {$a->no} title'; $string['tiletitlesetting_desc'] = 'Here, you enter the title which should be displayed in the advertisement tile {$a->no}. This is an optional setting, the advertisement tile will be shown even if you do not set a title.'; +// Settings: Slider tab. +$string['slidertab'] = 'Slider'; +// ... Section: Slider general. +$string['slidergeneralheading'] = 'Slider general'; +$string['slideranimationsetting'] = 'Slider animation type'; +$string['slideranimationsetting_desc'] = 'With this setting, you control the slider animation. \'Slide\' applies a sliding animation, \'Fade\' applies a fading animation and \'None\' removes all animations.'; +$string['slideranimationsetting_fade'] = 'Fade'; +$string['slideranimationsetting_none'] = 'None'; +$string['slideranimationsetting_slide'] = 'Slide'; +$string['sliderarrownavsetting'] = 'Enable arrow navigation'; +$string['sliderarrownavsetting_desc'] = 'With this setting, you can add navigation arrows on both sides of the slider.'; +$string['sliderfrontpagepositionsetting'] = 'Position of the slider on site home'; +$string['sliderfrontpagepositionsetting_desc'] = 'The slider is shown on site home only. With this setting, you control if the slider is displayed before the site home content or after the site home content. If you want to show only the slider on site home and nothing else, all other site home content can be removed by changing the site home settings.'; +$string['sliderfrontpagepositionsetting_afterafter'] = 'After the site home content (and after the advertisement tiles)'; +$string['sliderfrontpagepositionsetting_afterbefore'] = 'After the site home content (but before the advertisement tiles)'; +$string['sliderfrontpagepositionsetting_beforeafter'] = 'Before the site home content (and after the advertisement tiles)'; +$string['sliderfrontpagepositionsetting_beforebefore'] = 'Before the site home content (but before the advertisement tiles)'; +$string['sliderindicatornavsetting'] = 'Enable slider indicator navigation'; +$string['sliderindicatornavsetting_desc'] = 'With this setting, you can add navigation indicators on the bottom of the slider.'; +$string['sliderintervalsetting'] = 'Slider interval speed'; +$string['sliderintervalsetting_desc'] = 'With this setting, you control how long a slide is displayed in milliseconds. The minimum value is 1000 (one second) and the maximum value is 10000 (10 seconds).'; +$string['sliderkeyboardsetting'] = 'Allow slider keyboard interaction'; +$string['sliderkeyboardsetting_desc'] = 'With this setting, you enable keyboard inputs (arrow keys) to control the slider. Please note that disabling this lowers accessibility.'; +$string['sliderpausesetting'] = 'Pause slider on mouseover'; +$string['sliderpausesetting_desc'] = 'With this setting, you prevent the slider from cycling through the slides when a user hovers over a slide. Please note that disabling this lowers accessibility.'; +$string['sliderridesetting'] = 'Cycle through slides'; +$string['sliderridesetting_desc'] = 'With this setting, you control the cycling behaviour of the slider. \'On page load\' begins cycling through slides after the page has finished loading, \'After interaction\' will start cycling after a user has interacted with the slider. \'Never\' disables the automatic cycling of slides altogether, requiring user input to cycle through slides.'; +$string['sliderridesetting_afterinteraction'] = 'After interaction'; +$string['sliderridesetting_never'] = 'Never'; +$string['sliderridesetting_onpageload'] = 'On page load'; +$string['sliderwrapsetting'] = 'Continuously cycle through slides'; +$string['sliderwrapsetting_desc'] = 'With this setting, you make the slider cycling through all slides. If you disable this, the slider will stop cycling at the last slide.'; +// ... Section: Slides. +$string['slideheading'] = 'Slide {$a->no}'; +$string['slidebackgroundimagealtsetting'] = 'Slide {$a->no} background image alt attribute'; +$string['slidebackgroundimagealtsetting_desc'] = 'Here, you can set an alt attribute for the image of slide {$a->no}. This is an optional setting, the slide will be shown even if you do not set an alt attribute. Please note that not providing an alt attribute lowers accessibility.'; +$string['slidebackgroundimagesetting'] = 'Slide {$a->no} background image'; +$string['slidebackgroundimagesetting_desc'] = 'Here, you can upload an image file which will be shown as background image behind the content of slide {$a->no}. Please make sure or check that the content is still readable on the background image. Please also try to make sure that the aspect ratio of all slides\' background images is equal (as the background image aspect ratio controls the height of the slide and you might want to avoid flickering when the slides are changed). This is a mandatory setting, the slide will not be shown if you do not upload any background image.'; +$string['slidecaptionsetting'] = 'Slide {$a->no} caption'; +$string['slidecaptionsetting_desc'] = 'Here, you enter the caption which should be displayed in slide {$a->no}. The caption is displayed at the bottom center of the slide. This is an optional setting, the slide will be shown even if you do not set a caption.'; +$string['slidecontentsetting'] = 'Slide {$a->no} content'; +$string['slidecontentsetting_desc'] = 'Here, you enter the content which should be displayed in slide {$a->no}. The content is displayed at the bottom center of the slide. If a caption is set, the content is displayed below the caption. Please note that the rich-text editor produces left-aligned text by default, but you might want to change that to centered text for a nicer look. Please also refrain from adding too much content to the slide and please test your content on small devices as content which overflows the slide will simply be hidden. This is an optional setting, the slide will be shown even if you do not set any content.'; +$string['slidecontentstylesetting'] = 'Slide {$a->no} content style'; +$string['slidecontentstylesetting_dark'] = 'Dark (black font color for light background images)'; +$string['slidecontentstylesetting_darkshadow'] = 'Dark & Shadow (black font color with a light shadow for light background images)'; +$string['slidecontentstylesetting_desc'] = 'Here, you can modify the style of the content of slide {$a->no}. By default, the content style is a white font color for dark background images. However, to allow consistent and easy styling on all kinds of background images, you can override the style here. Please note that this setting will overrrule the font color which you set in the rich-text editor above in any case.'; +$string['slidecontentstylesetting_light'] = 'Light (white font color for dark background images)'; +$string['slidecontentstylesetting_lightshadow'] = 'Light & Shadow (white font color with a dark shadow for dark background images)'; +$string['slideenabledsetting'] = 'Enable slide {$a->no}'; +$string['slideenabledsetting_desc'] = 'With this setting, you can enable slide {$a->no}.'; +$string['slidelinksetting'] = 'Slide {$a->no} link URL'; +$string['slidelinksetting_desc'] = 'Here, you can set a (Moodle-internal or external) URL which the slide content of slide {$a->no} will link to. This is an optional setting, the slide will be shown even if you do not set a link URL.'; +$string['slidelinktitlesetting'] = 'Slide {$a->no} link title'; +$string['slidelinktitlesetting_desc'] = 'Here, you can set a link title which is presented as tooltip as soon as the user hovers over slide {$a->no}. This is an optional setting, the slide will be linked even if you do not set a link title. Please note that not providing a link title lowers accessibility.'; +$string['slidelinksourcesetting'] = 'Slide {$a->no} link source'; +$string['slidelinksourcesetting_desc'] = 'Here, you can control which elements of the slider link to the given link URL. You can choose between linking the background image only, linking the slide\'s text elements (caption and content) only or linking both of these.'; +$string['slidelinksourcesetting_both'] = 'Background image and text elements'; +$string['slidelinksourcesetting_image'] = 'Background image only'; +$string['slidelinksourcesetting_text'] = 'Text elements only'; +$string['slidelinktargetsetting'] = 'Slide {$a->no} link target'; +$string['slidelinktargetsetting_desc'] = 'Here, you can set the link target which is set for the slide link as soon as you set a link URL in the slide {$a->no}.'; +$string['slidelinktargetsetting_samewindow'] = 'Same window'; +$string['slidelinktargetsetting_newtab'] = 'New tab'; +$string['slideordersetting'] = 'Slide {$a->no} order position'; +$string['slideordersetting_desc'] = 'With this setting, you define the order position of the slide {$a->no}. By default, the slides are ordered as you see them on this settings page here. However, you can decide to assign another order position with this setting. If you assign the same order position to two or more slides, they will be ordered again according to the order on this settings page.'; // Settings: Functionality page. $string['configtitlefunctionality'] = 'Functionality'; diff --git a/layout/drawers.php b/layout/drawers.php index ff6c3936667..bf4810fbc9b 100644 --- a/layout/drawers.php +++ b/layout/drawers.php @@ -28,6 +28,7 @@ * * Include static pages * * Include Jvascript disabled hint * * Include advertisement tiles + * * Include slider * * Include info banners * * Include additional block regions * * Handle admin setting for right-hand block drawer of site home @@ -202,6 +203,11 @@ require_once(__DIR__ . '/includes/advertisementtiles.php'); } +// Include the template content for the slider, but only if we are on the frontpage. +if ($PAGE->pagelayout == 'frontpage') { + require_once(__DIR__ . '/includes/slider.php'); +} + // Include the template content for the smart menus. require_once(__DIR__ . '/includes/smartmenus.php'); diff --git a/layout/includes/slider.php b/layout/includes/slider.php new file mode 100644 index 00000000000..1a1dcd77230 --- /dev/null +++ b/layout/includes/slider.php @@ -0,0 +1,255 @@ +. + +/** + * Theme Boost Union - slider layout include. + * + * @package theme_boost_union + * @copyright 2023 Annika Lambert + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Require the necessary libraries. +require_once($CFG->dirroot.'/theme/boost_union/locallib.php'); + +// Get theme config. +$config = get_config('theme_boost_union'); + +// Initialize templatecontext flag to show the slider or not. +$templatecontext['showslider'] = false; + +// Initialize slides data for templatecontext. +$slides = []; + +// Iterate over all slides. +for ($i = 1; $i <= THEME_BOOST_UNION_SETTING_SLIDES_COUNT; $i++) { + // If the slide is enabled? (regardless if it contains any content). + if ($config->{'slide' . $i . 'enabled'} == THEME_BOOST_UNION_SETTING_SELECT_YES) { + // Get and set the slide's background image. + $bgimage = theme_boost_union_get_urlofslidebackgroundimage($i); + + // If the slide does not have a background image set, skip it. + if ($bgimage == null) { + continue; + } + + // Flip the show-slider flag to true. + $templatecontext['showslider'] = true; + + // Get and set the background image alt attribute. + $backgroundimagealt = format_string(trim($config->{'slide'.$i.'backgroundimagealt'})); + + // Get and set the slide's content. + $formatoptions = ['noclean' => true]; + $content = format_text($config->{'slide'.$i.'content'}, FORMAT_HTML, $formatoptions); + + // Get and set the slide's link. + $link = $config->{'slide'.$i.'link'}; + $linktitle = format_string(trim($config->{'slide'.$i.'linktitle'})); + if ($config->{'slide'.$i.'linktarget'} == THEME_BOOST_UNION_SETTING_LINKTARGET_NEWTAB) { + $linktargetnewtab = true; + } else { + $linktargetnewtab = false; + } + + // Get and set the slide's caption. + $caption = format_string(trim($config->{'slide'.$i.'caption'})); + + // Get and set the slide's order. + // The order is not needed for the mustache template, but the usort() method will need it later. + $order = $config->{'slide'.$i.'order'}; + + // Get and set the slide's content style class. + switch ($config->{'slide'.$i.'contentstyle'}) { + case THEME_BOOST_UNION_SETTING_CONTENTSTYLE_LIGHT: + $contentstyleclass = 'slide-light'; + break; + case THEME_BOOST_UNION_SETTING_CONTENTSTYLE_LIGHTSHADOW: + $contentstyleclass = 'slide-lightshadow'; + break; + case THEME_BOOST_UNION_SETTING_CONTENTSTYLE_DARK: + $contentstyleclass = 'slide-dark'; + break; + case THEME_BOOST_UNION_SETTING_CONTENTSTYLE_DARKSHADOW: + $contentstyleclass = 'slide-darkshadow'; + break; + } + + // Get and set the slide's link source. + switch ($config->{'slide'.$i.'linksource'}) { + case THEME_BOOST_UNION_SETTING_SLIDER_LINKSOURCE_BOTH: + $linkimage = true; + $linktext = true; + break; + case THEME_BOOST_UNION_SETTING_SLIDER_LINKSOURCE_IMAGE: + $linkimage = true; + $linktext = false; + break; + case THEME_BOOST_UNION_SETTING_SLIDER_LINKSOURCE_TEXT: + $linkimage = false; + $linktext = true; + break; + } + + // Deduce if a caption or content is set. + if (!empty($caption) || !empty($content)) { + $captionorcontent = true; + } else { + $captionorcontent = false; + } + + // Compose and remember this slide as templatecontext object. + $slide = new stdClass(); + $slide->content = $content; + $slide->linktitle = $linktitle; + $slide->link = $link; + $slide->linktargetnewtab = $linktargetnewtab; + $slide->backgroundimageurl = $bgimage; + $slide->backgroundimagealt = $backgroundimagealt; + $slide->caption = $caption; + $slide->no = $i; + $slide->order = $order; + $slide->contentstyleclass = $contentstyleclass; + $slide->captionorcontent = $captionorcontent; + $slide->linkimage = $linkimage; + $slide->linktext = $linktext; + $slide->isfirstslide = false; // Here, all slides are marked with false. This will be changed after ordering shortly. + $slides[$i] = $slide; + } +} + +// Only if we have any slide to show. +if ($templatecontext['showslider'] == true) { + // Getting and setting the slider position on the frontpage. + switch ($config->{'sliderfrontpageposition'}) { + case THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_BEFOREBEFORE: + $templatecontext['sliderpositionbeforebefore'] = true; + $templatecontext['sliderpositionbeforeafter'] = false; + $templatecontext['sliderpositionafterbefore'] = false; + $templatecontext['sliderpositionafterafter'] = false; + break; + case THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_BEFOREAFTER: + $templatecontext['sliderpositionbeforebefore'] = false; + $templatecontext['sliderpositionbeforeafter'] = true; + $templatecontext['sliderpositionafterbefore'] = false; + $templatecontext['sliderpositionafterafter'] = false; + break; + case THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_AFTERBEFORE: + $templatecontext['sliderpositionbeforebefore'] = false; + $templatecontext['sliderpositionbeforeafter'] = false; + $templatecontext['sliderpositionafterbefore'] = true; + $templatecontext['sliderpositionafterafter'] = false; + break; + case THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_AFTERAFTER: + $templatecontext['sliderpositionbeforebefore'] = false; + $templatecontext['sliderpositionbeforeafter'] = false; + $templatecontext['sliderpositionafterbefore'] = false; + $templatecontext['sliderpositionafterafter'] = true; + break; + } + + // Initialize general slider settings object. + $generalslidersettings = new stdClass(); + + // Getting and setting the slider's navigation settings. + switch ($config->{'sliderarrownav'}) { + case THEME_BOOST_UNION_SETTING_SELECT_YES: + $generalslidersettings->showarrownav = true; + break; + case THEME_BOOST_UNION_SETTING_SELECT_NO: + $generalslidersettings->showarrownav = false; + break; + } + switch ($config->{'sliderindicatornav'}) { + case THEME_BOOST_UNION_SETTING_SELECT_YES: + $generalslidersettings->showindicatornav = true; + break; + case THEME_BOOST_UNION_SETTING_SELECT_NO: + $generalslidersettings->showindicatornav = false; + break; + } + + // Getting and setting the slider's animation setting. + switch ($config->{'slideranimation'}) { + case THEME_BOOST_UNION_SETTING_SLIDER_ANIMATIONTYPE_SLIDE: + $generalslidersettings->animation = 'slide'; + break; + case THEME_BOOST_UNION_SETTING_SLIDER_ANIMATIONTYPE_FADE: + $generalslidersettings->animation = 'slide carousel-fade'; + break; + case THEME_BOOST_UNION_SETTING_SLIDER_ANIMATIONTYPE_NONE: + $generalslidersettings->animation = ''; + break; + } + + // Getting and setting the slider's animation interval setting. + if ($config->{'sliderinterval'} < 1000) { + $generalslidersettings->interval = 1000; + } else if ($config->{'sliderinterval'} > 10000) { + $generalslidersettings->interval = 10000; + } else { + $generalslidersettings->interval = $config->{'sliderinterval'}; + } + + // Getting and setting the slider's cycle setting. + switch ($config->{'sliderride'}) { + case THEME_BOOST_UNION_SETTING_SLIDER_RIDE_ONPAGELOAD: + $generalslidersettings->ride = 'carousel'; + break; + case THEME_BOOST_UNION_SETTING_SLIDER_RIDE_AFTERINTERACTION: + $generalslidersettings->ride = 'true'; + break; + case THEME_BOOST_UNION_SETTING_SLIDER_RIDE_NEVER: + $generalslidersettings->ride = 'false'; + break; + } + + // Getting and setting the slider's pause setting. + switch ($config->{'sliderpause'}) { + case THEME_BOOST_UNION_SETTING_SELECT_YES: + $generalslidersettings->pause = 'hover'; + break; + case THEME_BOOST_UNION_SETTING_SELECT_NO: + $generalslidersettings->pause = 'false'; + break; + } + + // Getting and setting the slider's keyboard setting. + $generalslidersettings->keyboard = theme_boost_union_yesno_to_boolstring($config->{'sliderkeyboard'}); + + // Getting and setting the slider's wrap setting. + $generalslidersettings->wrap = theme_boost_union_yesno_to_boolstring($config->{'sliderwrap'}); + + // Add general slider settings to templatecontext. + $templatecontext['slidergeneralsettings'] = $generalslidersettings; + + // Reorder the slides based on their order settings. + usort($slides, 'theme_boost_union_compare_order'); + + // Add a slideto attribute to each slide. + // This is needed for the slide controls, based on the latest ordering and starting from 0. + foreach ($slides as $key => $notneeded) { + $slides[$key]->slideto = $key; + } + + // Mark the first slide as first slide. + $slides[0]->isfirstslide = true; + + // Add slides data to templatecontext. + $templatecontext['slides'] = $slides; +} diff --git a/lib.php b/lib.php index 9c41f2348bf..2ae714970e4 100644 --- a/lib.php +++ b/lib.php @@ -50,6 +50,21 @@ define('THEME_BOOST_UNION_SETTING_ADVERTISEMENTTILES_FRONTPAGEPOSITION_BEFORE', 1); define('THEME_BOOST_UNION_SETTING_ADVERTISEMENTTILES_FRONTPAGEPOSITION_AFTER', 2); +define('THEME_BOOST_UNION_SETTING_SLIDES_COUNT', 6); +define('THEME_BOOST_UNION_SETTING_SLIDER_ANIMATIONTYPE_NONE', 0); +define('THEME_BOOST_UNION_SETTING_SLIDER_ANIMATIONTYPE_SLIDE', 1); +define('THEME_BOOST_UNION_SETTING_SLIDER_ANIMATIONTYPE_FADE', 2); +define('THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_BEFOREBEFORE', 1); +define('THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_BEFOREAFTER', 2); +define('THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_AFTERBEFORE', 3); +define('THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_AFTERAFTER', 4); +define('THEME_BOOST_UNION_SETTING_SLIDER_RIDE_ONPAGELOAD', 0); +define('THEME_BOOST_UNION_SETTING_SLIDER_RIDE_AFTERINTERACTION', 1); +define('THEME_BOOST_UNION_SETTING_SLIDER_RIDE_NEVER', 2); +define('THEME_BOOST_UNION_SETTING_SLIDER_LINKSOURCE_BOTH', 0); +define('THEME_BOOST_UNION_SETTING_SLIDER_LINKSOURCE_IMAGE', 1); +define('THEME_BOOST_UNION_SETTING_SLIDER_LINKSOURCE_TEXT', 2); + define('THEME_BOOST_UNION_SETTING_HEIGHT_100PX', '100px'); define('THEME_BOOST_UNION_SETTING_HEIGHT_150PX', '150px'); define('THEME_BOOST_UNION_SETTING_HEIGHT_200PX', '200px'); @@ -405,7 +420,8 @@ function theme_boost_union_pluginfile($course, $cm, $context, $filearea, $args, $filearea === 'loginbackgroundimage' || $filearea === 'additionalresources' || $filearea === 'customfonts' || $filearea === 'courseheaderimagefallback' || $filearea === 'touchiconsios' || - preg_match("/tilebackgroundimage[2-9]|1[0-2]?/", $filearea))) { + preg_match("/tilebackgroundimage[2-9]|1[0-2]?/", $filearea) || + preg_match("/slidebackgroundimage[2-9]|1[0-2]?/", $filearea))) { $theme = theme_config::load('boost_union'); // By default, theme files must be cache-able by both browsers and proxies. if (!array_key_exists('cacheability', $options)) { diff --git a/locallib.php b/locallib.php index 5bf586129ca..488217d5f1e 100644 --- a/locallib.php +++ b/locallib.php @@ -403,7 +403,7 @@ function theme_boost_union_infobanner_is_shown_on_page($bannerno) { } /** - * Helper function to compare either infobanner or tiles orders. + * Helper function to compare either infobanner or tiles or slides orders. * * @param int $a The first value * @param int $b The second value @@ -587,6 +587,52 @@ function theme_boost_union_get_urloftilebackgroundimage($tileno) { return null; } +/** + * Get the slider's background image URL from the filearea 'slidebackgroundimage'.tileno. + * + * Note: + * Calling this function for each slide separately is maybe not performant. Originally it was planed to put + * all files in one filearea. However, at the time of development + * https://github.com/moodle/moodle/blob/master/lib/outputlib.php#L2062 + * did not support itemids in setting-files of themes. + * + * @param int $slideno The slide number. + * @return string|null + */ +function theme_boost_union_get_urlofslidebackgroundimage($slideno) { + // If the slide number is apparently not valid, return. + // Note: We just check the slide's number, we do not check if the slide is enabled or not. + if ($slideno < 0 || $slideno > THEME_BOOST_UNION_SETTING_SLIDES_COUNT) { + return null; + } + + // Get the background image config for this slide. + $bgconfig = get_config('theme_boost_union', 'slide'.$slideno.'backgroundimage'); + + // If a background image is configured. + if (!empty($bgconfig)) { + // Get the system context. + $systemcontext = context_system::instance(); + + // Get filearea. + $fs = get_file_storage(); + + // Get all files from filearea. + $files = $fs->get_area_files($systemcontext->id, 'theme_boost_union', 'slidebackgroundimage'.$slideno, + false, 'itemid', false); + + // Just pick the first file - we are sure that there is just one file. + $file = reset($files); + + // Build and return the image URL. + return moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(), $file->get_filearea(), + $file->get_itemid(), $file->get_filepath(), $file->get_filename()); + } + + // As no image was found, return null. + return null; +} + /** * Add background images from setting 'loginbackgroundimage' to SCSS. * @@ -1672,7 +1718,7 @@ function theme_boost_union_get_touchicons_html_for_page() { // If the file exists (i.e. it has been uploaded). if ($file->exists == true) { // Build the file URL. - $fileurl = new moodle_url('/pluginfile.php/1/theme_boost_union/touchiconsios/'. + $fileurl = new moodle_url('/pluginfile.php/1/theme_boost_union/touchiconsios/' . theme_get_revision().'/'.$file->filename); // Compose and append the HTML tag. @@ -1686,3 +1732,17 @@ function theme_boost_union_get_touchicons_html_for_page() { // Return the string. return $touchiconstring; } + +/** + * Helper function to map Boost Union settings ('yes'/'no') to corresponding string values ('true'/'false') + * This is needed for Bootstrap which expects string boolean values. + * + * @param string $var Either 'yes' or 'no' + */ +function theme_boost_union_yesno_to_boolstring($var) { + if ($var == THEME_BOOST_UNION_SETTING_SELECT_YES) { + return 'true'; + } else { + return 'false'; + } +} diff --git a/scss/boost_union/post.scss b/scss/boost_union/post.scss index ff13225a71a..3a207fddc2a 100644 --- a/scss/boost_union/post.scss +++ b/scss/boost_union/post.scss @@ -1016,14 +1016,6 @@ body.theme_boost-union-footerbuttonnone.jsenabled { * Settings: Content -> Advertisement tiles. ======================================*/ -/* Remove horizontal paddings on the tile container on smaller screens to align it with the main frontpage content. */ -@include media-breakpoint-down(sm) { - #themeboostunionadvtiles { - padding-left: 0; - padding-right: 0; - } -} - /* Style the advertisement tile cards. */ #themeboostunionadvtiles [class*="col-"] .card { background-size: cover; @@ -1067,6 +1059,75 @@ body.theme_boost-union-footerbuttonnone.jsenabled { } +/*======================================= + * Settings: Content -> Slider. + ======================================*/ + +/* Style the slider. */ +#themeboostunionslider { + /* Remove the link color and styling for links in the slider as, otherwise, the linked caption and content + would be colored and styled which does not make much sense here. */ + a { + color: inherit; + } + a:hover { + text-decoration: inherit; + } + + /* Remove the focus border which would appear around slider controls which have been clicked. + These do not look nice within the slider. */ + a:focus { + box-shadow: none; + } + + /* Remove the font color from the caption to allow styling based on the slider settings. */ + .carousel-caption { + color: inherit; + } + + /* Add an unobtrusive shadow to the carousel controls to make them visible on all kinds of backgrounds. */ + .carousel-control-prev, + .carousel-control-next { + filter: drop-shadow(0 0 2px rgb(0, 0, 0)); + } + .carousel-indicators { + filter: drop-shadow(0 0 1px rgb(0, 0, 0)); + } +} + +/* Classes for the content style of slides. */ +#themeboostunionslider { + .slide-dark { + color: black; + } + .slide-light { + color: white; + } + .slide-darkshadow { + color: black; + text-shadow: 0 0 5px white; + } + .slide-lightshadow { + color: white; + text-shadow: 0 0 5px black; + } +} + + +/*======================================= + * Settings: Content -> Advertisement tiles & Slider (Common settings for both features). + ======================================*/ + +/* Remove horizontal paddings on the tile / slider container on smaller screens to align it with the main frontpage content. */ +@include media-breakpoint-down(sm) { + #themeboostunionadvtiles, + #themeboostunionslider-wrapper { + padding-left: 0; + padding-right: 0; + } +} + + /*======================================= * Settings: Functionality -> Courses. ======================================*/ diff --git a/settings.php b/settings.php index a5571b7f2fb..2487b8a70b0 100644 --- a/settings.php +++ b/settings.php @@ -1967,6 +1967,260 @@ $page->add($tab); + // Create slider tab. + $tab = new admin_settingpage('theme_boost_union_slider', + get_string('slidertab', 'theme_boost_union', null, true)); + + // Create slider general heading. + $name = 'theme_boost_union/slidergeneralheading'; + $title = get_string('slidergeneralheading', 'theme_boost_union', null, true); + $setting = new admin_setting_heading($name, $title, null); + $tab->add($setting); + + // Setting: Position of the slider on the frontpage. + $sliderfrontpagepositionoptions = [ + THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_BEFOREBEFORE => + get_string('sliderfrontpagepositionsetting_beforebefore', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_BEFOREAFTER => + get_string('sliderfrontpagepositionsetting_beforeafter', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_AFTERBEFORE => + get_string('sliderfrontpagepositionsetting_afterbefore', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_AFTERAFTER => + get_string('sliderfrontpagepositionsetting_afterafter', 'theme_boost_union'), + ]; + $name = 'theme_boost_union/sliderfrontpageposition'; + $title = get_string('sliderfrontpagepositionsetting', 'theme_boost_union', null, true); + $url = new moodle_url('/admin/settings.php', ['section' => 'frontpagesettings']); + $description = get_string('sliderfrontpagepositionsetting_desc', 'theme_boost_union', ['url' => $url], true); + $setting = new admin_setting_configselect($name, $title, $description, + THEME_BOOST_UNION_SETTING_SLIDER_FRONTPAGEPOSITION_BEFOREBEFORE, $sliderfrontpagepositionoptions); + $tab->add($setting); + + // Setting: Enable arrow navigation. + $name = 'theme_boost_union/sliderarrownav'; + $title = get_string('sliderarrownavsetting', 'theme_boost_union', null, true); + $description = get_string('sliderarrownavsetting_desc', 'theme_boost_union', null, true); + $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_SELECT_NO, + $yesnooption); + $tab->add($setting); + + // Setting: Enable slider indicator navigation. + $name = 'theme_boost_union/sliderindicatornav'; + $title = get_string('sliderindicatornavsetting', 'theme_boost_union', null, true); + $description = get_string('sliderindicatornavsetting_desc', 'theme_boost_union', null, true); + $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_SELECT_NO, + $yesnooption); + $tab->add($setting); + + // Setting: Slider animation type. + $slideranimationoptions = [ + THEME_BOOST_UNION_SETTING_SLIDER_ANIMATIONTYPE_NONE => + get_string('slideranimationsetting_none', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_SLIDER_ANIMATIONTYPE_FADE => + get_string('slideranimationsetting_fade', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_SLIDER_ANIMATIONTYPE_SLIDE => + get_string('slideranimationsetting_slide', 'theme_boost_union'), + ]; + $name = 'theme_boost_union/slideranimation'; + $title = get_string('slideranimationsetting', 'theme_boost_union', null, true); + $description = get_string('slideranimationsetting_desc', 'theme_boost_union', null, true); + $setting = new admin_setting_configselect($name, $title, $description, + THEME_BOOST_UNION_SETTING_SLIDER_ANIMATIONTYPE_SLIDE, $slideranimationoptions); + $tab->add($setting); + + // Setting: Slider interval speed. + $name = 'theme_boost_union/sliderinterval'; + $title = get_string('sliderintervalsetting', 'theme_boost_union', null, true); + $description = get_string('sliderintervalsetting_desc', 'theme_boost_union', null, true); + $setting = new admin_setting_configtext($name, $title, $description, 5000, PARAM_INT, 6); + $tab->add($setting); + + // Setting: Allow slider keyboard interaction. + $name = 'theme_boost_union/sliderkeyboard'; + $title = get_string('sliderkeyboardsetting', 'theme_boost_union', null, true); + $description = get_string('sliderkeyboardsetting_desc', 'theme_boost_union', null, true); + $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_SELECT_YES, + $yesnooption); + $tab->add($setting); + + // Setting: Pause slider on mouseover. + $name = 'theme_boost_union/sliderpause'; + $title = get_string('sliderpausesetting', 'theme_boost_union', null, true); + $description = get_string('sliderpausesetting_desc', 'theme_boost_union', null, true); + $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_SELECT_YES, + $yesnooption); + $tab->add($setting); + + // Setting: Cycle through slides. + $sliderrideoptions = [ + THEME_BOOST_UNION_SETTING_SLIDER_RIDE_ONPAGELOAD => + get_string('sliderridesetting_onpageload', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_SLIDER_RIDE_AFTERINTERACTION => + get_string('sliderridesetting_afterinteraction', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_SLIDER_RIDE_NEVER => + get_string('sliderridesetting_never', 'theme_boost_union'), + ]; + $name = 'theme_boost_union/sliderride'; + $title = get_string('sliderridesetting', 'theme_boost_union', null, true); + $description = get_string('sliderridesetting_desc', 'theme_boost_union', null, true); + $setting = new admin_setting_configselect($name, $title, $description, + THEME_BOOST_UNION_SETTING_SLIDER_RIDE_ONPAGELOAD, $sliderrideoptions); + $tab->add($setting); + + // Setting: Continuously cycle through slides. + $name = 'theme_boost_union/sliderwrap'; + $title = get_string('sliderwrapsetting', 'theme_boost_union', null, true); + $description = get_string('sliderwrapsetting_desc', 'theme_boost_union', null, true); + $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_SELECT_YES, + $yesnooption); + $tab->add($setting); + + // Prepare options for the order settings. + $slidesorders = []; + for ($i = 1; $i <= THEME_BOOST_UNION_SETTING_SLIDES_COUNT; $i++) { + $slidesorders[$i] = $i; + } + + // Create a hardcoded amount of slides without code duplication. + for ($i = 1; $i <= THEME_BOOST_UNION_SETTING_SLIDES_COUNT; $i++) { + + // Create slide heading. + $name = 'theme_boost_union/slide'.$i.'heading'; + $title = get_string('slideheading', 'theme_boost_union', ['no' => $i], true); + $setting = new admin_setting_heading($name, $title, null); + $tab->add($setting); + + // Setting: Slide enabled. + $name = 'theme_boost_union/slide'.$i.'enabled'; + $title = get_string('slideenabledsetting', 'theme_boost_union', ['no' => $i], true); + $description = get_string('slideenabledsetting_desc', 'theme_boost_union', ['no' => $i], true); + $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_SELECT_NO, + $yesnooption); + $tab->add($setting); + + // Setting: Slide background image. + $name = 'theme_boost_union/slide'.$i.'backgroundimage'; + $title = get_string('slidebackgroundimagesetting', 'theme_boost_union', ['no' => $i], true); + $description = get_string('slidebackgroundimagesetting_desc', 'theme_boost_union', ['no' => $i], true); + $setting = new admin_setting_configstoredfile($name, $title, $description, 'slidebackgroundimage'.$i, 0, + ['maxfiles' => 1, 'accepted_types' => 'web_image']); + $setting->set_updatedcallback('theme_reset_all_caches'); + $tab->add($setting); + $page->hide_if('theme_boost_union/slide'.$i.'backgroundimage', 'theme_boost_union/slide'.$i.'enabled', + 'neq', THEME_BOOST_UNION_SETTING_SELECT_YES); + + // Setting: Slide background image alt attribute. + $name = 'theme_boost_union/slide'.$i.'backgroundimagealt'; + $title = get_string('slidebackgroundimagealtsetting', 'theme_boost_union', ['no' => $i], true); + $description = get_string('slidebackgroundimagealtsetting_desc', 'theme_boost_union', ['no' => $i], true); + $setting = new admin_setting_configtext($name, $title, $description, ''); + $tab->add($setting); + $page->hide_if('theme_boost_union/slide'.$i.'backgroundimagealt', 'theme_boost_union/slide'.$i.'enabled', 'neq', + THEME_BOOST_UNION_SETTING_SELECT_YES); + + // Setting: Slide caption. + $name = 'theme_boost_union/slide'.$i.'caption'; + $title = get_string('slidecaptionsetting', 'theme_boost_union', ['no' => $i], true); + $description = get_string('slidecaptionsetting_desc', 'theme_boost_union', ['no' => $i], true); + $setting = new admin_setting_configtext($name, $title, $description, ''); + $tab->add($setting); + $page->hide_if('theme_boost_union/slide'.$i.'caption', 'theme_boost_union/slide'.$i.'enabled', 'neq', + THEME_BOOST_UNION_SETTING_SELECT_YES); + + // Setting: Slide content. + $name = 'theme_boost_union/slide'.$i.'content'; + $title = get_string('slidecontentsetting', 'theme_boost_union', ['no' => $i], true); + $description = get_string('slidecontentsetting_desc', 'theme_boost_union', ['no' => $i], true); + $setting = new admin_setting_confightmleditor($name, $title, $description, ''); + $tab->add($setting); + $page->hide_if('theme_boost_union/slide'.$i.'content', 'theme_boost_union/slide'.$i.'enabled', 'neq', + THEME_BOOST_UNION_SETTING_SELECT_YES); + + // Setting: Slide content style. + $name = 'theme_boost_union/slide'.$i.'contentstyle'; + $title = get_string('slidecontentstylesetting', 'theme_boost_union', ['no' => $i], true); + $description = get_string('slidecontentstylesetting_desc', 'theme_boost_union', ['no' => $i], true); + $slidecontentstyleoptions = [ + THEME_BOOST_UNION_SETTING_CONTENTSTYLE_LIGHT => + get_string('slidecontentstylesetting_light', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_CONTENTSTYLE_LIGHTSHADOW => + get_string('slidecontentstylesetting_lightshadow', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_CONTENTSTYLE_DARK => + get_string('slidecontentstylesetting_dark', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_CONTENTSTYLE_DARKSHADOW => + get_string('slidecontentstylesetting_darkshadow', 'theme_boost_union'), + ]; + $setting = new admin_setting_configselect($name, $title, $description, + THEME_BOOST_UNION_SETTING_CONTENTSTYLE_LIGHT, $slidecontentstyleoptions); + $tab->add($setting); + $page->hide_if('theme_boost_union/slide'.$i.'contentstyle', 'theme_boost_union/slide'.$i.'enabled', 'neq', + THEME_BOOST_UNION_SETTING_SELECT_YES); + + // Setting: Slide link URL. + $name = 'theme_boost_union/slide'.$i.'link'; + $title = get_string('slidelinksetting', 'theme_boost_union', ['no' => $i], true); + $description = get_string('slidelinksetting_desc', 'theme_boost_union', ['no' => $i], true); + $setting = new admin_setting_configtext($name, $title, $description, '', PARAM_URL); + $tab->add($setting); + $page->hide_if('theme_boost_union/slide'.$i.'link', 'theme_boost_union/slide'.$i.'enabled', 'neq', + THEME_BOOST_UNION_SETTING_SELECT_YES); + + // Setting: Slide link title. + $name = 'theme_boost_union/slide'.$i.'linktitle'; + $title = get_string('slidelinktitlesetting', 'theme_boost_union', ['no' => $i], true); + $description = get_string('slidelinktitlesetting_desc', 'theme_boost_union', ['no' => $i], true); + $setting = new admin_setting_configtext($name, $title, $description, ''); + $tab->add($setting); + $page->hide_if('theme_boost_union/slide'.$i.'linktitle', 'theme_boost_union/slide'.$i.'enabled', 'neq', + THEME_BOOST_UNION_SETTING_SELECT_YES); + + // Setting: Slide link source. + $name = 'theme_boost_union/slide'.$i.'linksource'; + $title = get_string('slidelinksourcesetting', 'theme_boost_union', ['no' => $i], true); + $description = get_string('slidelinksourcesetting_desc', 'theme_boost_union', ['no' => $i], true); + $slidelinksourceoptions = [ + THEME_BOOST_UNION_SETTING_SLIDER_LINKSOURCE_BOTH => + get_string('slidelinksourcesetting_both', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_SLIDER_LINKSOURCE_IMAGE => + get_string('slidelinksourcesetting_image', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_SLIDER_LINKSOURCE_TEXT => + get_string('slidelinksourcesetting_text', 'theme_boost_union'), + ]; + $setting = new admin_setting_configselect($name, $title, $description, + THEME_BOOST_UNION_SETTING_SLIDER_LINKSOURCE_BOTH, $slidelinksourceoptions); + $tab->add($setting); + $page->hide_if('theme_boost_union/slide'.$i.'linksource', 'theme_boost_union/slide'.$i.'enabled', 'neq', + THEME_BOOST_UNION_SETTING_SELECT_YES); + + // Setting: Slide link target. + $name = 'theme_boost_union/slide'.$i.'linktarget'; + $title = get_string('slidelinktargetsetting', 'theme_boost_union', ['no' => $i], true); + $description = get_string('slidelinktargetsetting_desc', 'theme_boost_union', ['no' => $i], true); + $slidelinktargetnoptions = [ + THEME_BOOST_UNION_SETTING_LINKTARGET_SAMEWINDOW => + get_string('slidelinktargetsetting_samewindow', 'theme_boost_union'), + THEME_BOOST_UNION_SETTING_LINKTARGET_NEWTAB => + get_string('slidelinktargetsetting_newtab', 'theme_boost_union'), ]; + $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_LINKTARGET_SAMEWINDOW, + $slidelinktargetnoptions); + $tab->add($setting); + $page->hide_if('theme_boost_union/slide'.$i.'linktarget', 'theme_boost_union/slide'.$i.'enabled', 'neq', + THEME_BOOST_UNION_SETTING_SELECT_YES); + + // Setting: Slide order position. + $name = 'theme_boost_union/slide'.$i.'order'; + $title = get_string('slideordersetting', 'theme_boost_union', ['no' => $i], true); + $description = get_string('slideordersetting_desc', 'theme_boost_union', ['no' => $i], true); + $setting = new admin_setting_configselect($name, $title, $description, $i, $slidesorders); + $tab->add($setting); + $page->hide_if('theme_boost_union/slide'.$i.'order', 'theme_boost_union/slide'.$i.'enabled', 'neq', + THEME_BOOST_UNION_SETTING_SELECT_YES); + } + + // Add tab to settings page. + $page->add($tab); + + // Add settings page to the admin settings category. $ADMIN->add('theme_boost_union', $page); diff --git a/templates/slider.mustache b/templates/slider.mustache new file mode 100644 index 00000000000..1d735472f8e --- /dev/null +++ b/templates/slider.mustache @@ -0,0 +1,166 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template theme_boost_union/slider + + Boost Union slider layout template. + + Context variables required for this template: + * showslider - The flag to show the slider or not + * slidergeneralsettings - The slider configuration object + * animation - The slider animation type + * interval - The slider interval speed + * keyboard - Allow slider keyboard interaction + * pause - Pause slider on mouseover + * ride - Cycle through slides + * showindicatornav - The flag if the slider indicator should be shown + * showarrownav - The flag if the slider arrows should be shown + * wrap - Continuously cycle through slides + * slides - The configured slides list with: + * backgroundimageurl - Image to be displayed behind the content + * backgroundimagealt - The alt attribute for the background image + * captionorcontent - The flag if caption or content is provided + * caption - The slide's caption (might be empty) + * content - The slide's content (might be empty) + * contentstyleclass - The CSS class for the slide + * isfirstslide - The flag if this is the first slide + * linkimage - The flag if the slide's background image should be linked + * linktext - The flag if the slide's text (caption + content) should be linked + * linktitle - The link title which is displayed (might be empty) + * link - The actual URL (might be empty) + * linktargetnewtab - The flag if the link should open in a new tab + * no - The number of the slide (according to the settings) + * slideto - The index of the slide (according to the order) + + Example context (json): + { + "showslider": true, + "slidergeneralsettings": { + "animation": "slide carousel-fade", + "interval": 5000, + "keyboard": "true", + "pause": "false", + "ride": "carousel", + "showindicatornav": true, + "showarrownav": true, + "wrap": "true" + }, + "slides": [ + { + "backgroundimageurl": "https://raw.githubusercontent.com/moodle-an-hochschulen/moodle-theme_boost_union/master/tests/fixtures/login_bg1.jpg", + "backgroundimagealt": "The background image 1", + "captionorcontent": true, + "caption": "The caption 1", + "content": "The content 1", + "contentstyleclass": "slide-lightshadow", + "isfirstslide": true, + "linkimage": true, + "linktext": true, + "linktitle": "The link", + "link": "https://the-link.org/", + "linktargetnewtab": true, + "no": 1, + "slideto": 0 + }, + { + "backgroundimageurl": "https://raw.githubusercontent.com/moodle-an-hochschulen/moodle-theme_boost_union/master/tests/fixtures/login_bg2.jpg", + "backgroundimagealt": "The background image 2", + "captionorcontent": true, + "caption": "The caption 2", + "content": "The content 2", + "contentstyleclass": "slide-lightshadow", + "isfirstslide": false, + "linkimage": true, + "linktext": true, + "linktitle": "The link", + "link": "https://the-link.org/", + "linktargetnewtab": false, + "no": 2, + "slideto": 1 + }, + { + "backgroundimageurl": "https://raw.githubusercontent.com/moodle-an-hochschulen/moodle-theme_boost_union/master/tests/fixtures/login_bg3.jpg", + "backgroundimagealt": "The background image 3", + "captionorcontent": true, + "caption": "The caption 3", + "content": "The content 3", + "contentstyleclass": "slide-lightshadow", + "isfirstslide": false, + "linkimage": true, + "linktext": true, + "linktitle": "The link", + "link": "https://the-link.org/", + "linktargetnewtab": false, + "no": 3, + "slideto": 2 + } + ] + } +}} +{{#showslider}} +
+ +
+ +{{#js}} +require(['jquery', 'theme_boost/bootstrap/carousel'], function($) { + if (document.getElementById('themeboostunionslider')) { + $('#themeboostunionslider').carousel(); + } +}); +{{/js}} +{{/showslider}} diff --git a/templates/theme_boost/drawers.mustache b/templates/theme_boost/drawers.mustache index 5a034fe6de8..414eb6d0741 100644 --- a/templates/theme_boost/drawers.mustache +++ b/templates/theme_boost/drawers.mustache @@ -59,6 +59,7 @@ * Added the possibility to show course related hints. * Added the possibility to show info banners. * Include theme_boost_union/advertisementtiles template + * Include theme_boost_union/slider template * Added additional block regions (including JS for offcanvas region) * Added smartmenu js to support third level submenus. }} @@ -206,9 +207,15 @@ {{/regions.contentupper.hasblocks}}
+ {{#sliderpositionbeforebefore}} + {{> theme_boost_union/slider }} + {{/sliderpositionbeforebefore}} {{#advtilespositionbefore}} {{> theme_boost_union/advertisementtiles }} {{/advtilespositionbefore}} + {{#sliderpositionbeforeafter}} + {{> theme_boost_union/slider }} + {{/sliderpositionbeforeafter}} {{#hasregionmainsettingsmenu}}
{{{ regionmainsettingsmenu }}}
@@ -236,9 +243,15 @@ {{{ output.course_content_footer }}} + {{#sliderpositionafterbefore}} + {{> theme_boost_union/slider }} + {{/sliderpositionafterbefore}} {{#advtilespositionafter}} {{> theme_boost_union/advertisementtiles }} {{/advtilespositionafter}} + {{#sliderpositionafterafter}} + {{> theme_boost_union/slider }} + {{/sliderpositionafterafter}}
{{#regions.contentlower.hasblocks}} diff --git a/tests/behat/theme_boost_union_contentsettings_slider.feature b/tests/behat/theme_boost_union_contentsettings_slider.feature new file mode 100644 index 00000000000..8abf020b48a --- /dev/null +++ b/tests/behat/theme_boost_union_contentsettings_slider.feature @@ -0,0 +1,419 @@ +@theme @theme_boost_union @theme_boost_union_contentsettings @theme_boost_union_contentsettings_slider @javascript @_file_upload + +Feature: Configuring the theme_boost_union plugin for the "Slider" tab on the "Content" page + In order to use the features + As admin + I need to be able to configure the theme Boost Union plugin + + Background: + Given the following "users" exist: + | username | + | teacher1 | + And the following config values are set as admin: + | config | value | plugin | + | slide1enabled | yes | theme_boost_union | + | slide1caption | Slide 1 | theme_boost_union | + | slide1content | This is a test content for slide 1 | theme_boost_union | + When I log in as "admin" + # We deactivate debugging for a while as the Behat step would otherwise fail due to the + # stupid 'Too much data passed as arguments to js_call_amd' debugging message which can't be avoided + # on this settings page. This debugging message can't be avoided as we simple use too much hide_if() there. + And the following config values are set as admin: + | debug | 0 | + | debugdisplay | 0 | + And I navigate to "Appearance > Boost Union > Content" in site administration + And I click on "Slider" "link" in the "#adminsettings .nav-tabs" "css_element" + And I upload "theme/boost_union/tests/fixtures/login_bg1.jpg" file to "Slide 1 background image" filemanager + And I press "Save changes" + And I am on site homepage + # We reactivate debugging again. + And the following config values are set as admin: + | debug | 32767 | + | debugdisplay | 1 | + And I log out + + Scenario: Setting: Slider - Display the slider on the frontpage only and nowhere else + Given the following "courses" exist: + | fullname | shortname | + | Course 1 | C1 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + When I log in as "teacher1" + And I am on site homepage + Then "#themeboostunionslide1" "css_element" should exist + And I follow "Dashboard" + Then "#themeboostunionslide1" "css_element" should not exist + And I follow "My courses" + Then "#themeboostunionslide1" "css_element" should not exist + When I am on "Course 1" course homepage + Then "#themeboostunionslide1" "css_element" should not exist + When I log out + And I click on "Log in" "link" in the ".logininfo" "css_element" + Then "#themeboostunionslide1" "css_element" should not exist + + Scenario Outline: Setting: Slider - Display the slider wrapper and the individual slide only if it is enabled + Given the following config values are set as admin: + | config | value | plugin | + | slide1enabled | | theme_boost_union | + When I log in as "teacher1" + And I am on site homepage + Then "#themeboostunionslider-wrapper" "css_element" + And "#themeboostunionslide1" "css_element" + + Examples: + | enabled | shouldexist | + | yes | should exist | + | no | should not exist | + + Scenario Outline: Setting: Slider - Display the slider before or after the main output of site home + Given the following config values are set as admin: + | config | value | plugin | + | sliderfrontpageposition | | theme_boost_union | + | tilefrontpageposition | | theme_boost_union | + | tile1enabled | yes | theme_boost_union | + | tile1title | Tile 1 | theme_boost_union | + | tile1content | This is a test content for tile 1 | theme_boost_union | + When I log in as "teacher1" + And I am on site homepage + Then "#themeboostunionslider" "css_element" should appear "#region-main" "css_element" + And "#themeboostunionslider" "css_element" should appear "#themeboostunionadvtiles" "css_element" + + Examples: + | sliderposition | advtileposition | beforeafter1 | beforeafter2 | + | 1 | 1 | before | before | + | 2 | 1 | before | after | + | 3 | 2 | after | before | + | 4 | 2 | after | after | + + Scenario Outline: Setting: Slider - Enable arrow navigation + Given the following config values are set as admin: + | config | value | plugin | + | sliderarrownav | | theme_boost_union | + When I log in as "teacher1" + And I am on site homepage + Then "#themeboostunionslider .carousel-control-next" "css_element" exist + And "#themeboostunionslider .carousel-control-prev" "css_element" exist + + Examples: + | setting | shouldornot | + | yes | should | + | no | should not | + + Scenario Outline: Setting: Slider - Enable slider indicator navigation + Given the following config values are set as admin: + | config | value | plugin | + | sliderindicatornav | | theme_boost_union | + When I log in as "teacher1" + And I am on site homepage + Then "#themeboostunionslider .carousel-indicators" "css_element" exist + + Examples: + | setting | shouldornot | + | yes | should | + | no | should not | + + Scenario Outline: Setting: Slider - Slider animation type + Given the following config values are set as admin: + | config | value | plugin | + | slideranimation | | theme_boost_union | + When I log in as "teacher1" + And I am on site homepage + Then "#themeboostunionslider.slide" "css_element" exist + And "#themeboostunionslider.carousel-fade" "css_element" exist + + Examples: + | setting | slideshouldornot | carouselshouldornot | + | 0 | should not | should not | + | 1 | should | should not | + | 2 | should | should | + + Scenario Outline: Setting: Slider - Slider interval speed + Given the following config values are set as admin: + | config | value | plugin | + | sliderinterval | | theme_boost_union | + When I log in as "teacher1" + And I am on site homepage + Then the "data-interval" attribute of "#themeboostunionslider" "css_element" should contain "" + + Examples: + | setting | speed | + | 500 | 1000 | + | 4321 | 4321 | + | 10001 | 10000 | + + Scenario Outline: Setting: Slider - Allow slider keyboard interaction + Given the following config values are set as admin: + | config | value | plugin | + | sliderkeyboard | | theme_boost_union | + When I log in as "teacher1" + And I am on site homepage + Then the "data-keyboard" attribute of "#themeboostunionslider" "css_element" should contain "" + + Examples: + | setting | keyboard | + | yes | true | + | no | false | + + Scenario Outline: Setting: Slider - Pause slider on mouseover + Given the following config values are set as admin: + | config | value | plugin | + | sliderpause | | theme_boost_union | + When I log in as "teacher1" + And I am on site homepage + Then the "data-pause" attribute of "#themeboostunionslider" "css_element" should contain "" + + Examples: + | setting | pause | + | yes | hover | + | no | false | + + Scenario Outline: Setting: Slider - Cycle through slides + Given the following config values are set as admin: + | config | value | plugin | + | sliderride | | theme_boost_union | + When I log in as "teacher1" + And I am on site homepage + Then the "data-ride" attribute of "#themeboostunionslider" "css_element" should contain "" + + Examples: + | setting | ride | + | 0 | carousel | + | 1 | true | + | 2 | false | + + Scenario Outline: Setting: Slider - Continuously cycle through slides + Given the following config values are set as admin: + | config | value | plugin | + | sliderwrap | | theme_boost_union | + When I log in as "teacher1" + And I am on site homepage + Then the "data-wrap" attribute of "#themeboostunionslider" "css_element" should contain "" + + Examples: + | setting | wrap | + | yes | true | + | no | false | + + Scenario: Setting: Slider - Display the uploaded background image within a slide + Given the following config values are set as admin: + | config | value | plugin | + | slide1backgroundimagealt | This is the image description | theme_boost_union | + When I log in as "teacher1" + And I am on site homepage + Then "#themeboostunionslide1 > img" "css_element" should exist + And the "src" attribute of "#themeboostunionslide1 > img" "css_element" should contain "pluginfile.php/1/theme_boost_union/slidebackgroundimage1/0/login_bg1.jpg" + And the "alt" attribute of "#themeboostunionslide1 > img" "css_element" should contain "This is the image description" + + Scenario: Setting: Slider - Display an individual slide only if an image is uploaded + Given the following config values are set as admin: + | config | value | plugin | + | slide2enabled | yes | theme_boost_union | + | slide2caption | Slide 2 | theme_boost_union | + | slide2content | This is a test content for slide 2 | theme_boost_union | + When I log in as "teacher1" + And I am on site homepage + Then "#themeboostunionslider-wrapper" "css_element" should exist + And "#themeboostunionslide1" "css_element" should exist + And "#themeboostunionslide2" "css_element" should not exist + + Scenario: Setting: Slider - Display the caption and the content in the corresponding HTML elements + Given the following config values are set as admin: + | config | value | plugin | + | slide1enabled | yes | theme_boost_union | + | slide1caption | Slide 1Folie 1 | theme_boost_union | + | slide1content | This is a test content for slide 1Dies ist Testinhalt für Folie 1 | theme_boost_union | + And the "multilang" filter is "on" + And the "multilang" filter applies to "content and headings" + When I log in as "teacher1" + And I am on site homepage + Then "#themeboostunionslider #themeboostunionslide1" "css_element" should exist + And I should see "This is a test content for slide 1" in the "#themeboostunionslide1 .carousel-caption" "css_element" + And I should not see "This is a test content for slide 1" in the "#themeboostunionslide1 .carousel-caption" "css_element" + And I should not see "This is a test content for slide 1Dies ist Testinhalt für Folie 1" in the "#themeboostunionslide1 .carousel-caption" "css_element" + And I should see "Slide 1" in the "#themeboostunionslide1 .carousel-caption h5" "css_element" + And I should not see "Slide 1" in the "#themeboostunionslide1 .carousel-caption h5" "css_element" + And I should not see "Slide 1Folie 1" in the "#themeboostunionslide1 .carousel-caption h5" "css_element" + + Scenario: Setting: Slider - Use the links in the slider + Given the following config values are set as admin: + | config | value | plugin | + | slide1enabled | yes | theme_boost_union | + | slide1caption | Slide 1 | theme_boost_union | + | slide1content | This is a test content for slide 1 | theme_boost_union | + | slide1link | | theme_boost_union | + | slide1linktitle | | theme_boost_union | + | slide1linksource | 0 | theme_boost_union | + | slide1linktarget | same | theme_boost_union | + | slide2enabled | yes | theme_boost_union | + | slide2caption | Slide 2 | theme_boost_union | + | slide2content | This is a test content for slide 2 | theme_boost_union | + | slide2link | www.behat.de | theme_boost_union | + | slide2linktitle | | theme_boost_union | + | slide2linksource | 0 | theme_boost_union | + | slide2linktarget | same | theme_boost_union | + | slide3enabled | yes | theme_boost_union | + | slide3caption | Slide 3 | theme_boost_union | + | slide3content | This is a test content for slide 3 | theme_boost_union | + | slide3link | www.behat.com | theme_boost_union | + | slide3linktitle | Link to Behat | theme_boost_union | + | slide3linksource | 1 | theme_boost_union | + | slide3linktarget | same | theme_boost_union | + | slide4enabled | yes | theme_boost_union | + | slide4caption | Slide 4 | theme_boost_union | + | slide4content | This is a test content for slide 4 | theme_boost_union | + | slide4link | www.google.com | theme_boost_union | + | slide4linktitle | Link to Google | theme_boost_union | + | slide4linksource | 2 | theme_boost_union | + | slide4linktarget | new | theme_boost_union | + And I log in as "admin" + # We deactivate debugging for a while as the Behat step would otherwise fail due to the + # stupid 'Too much data passed as arguments to js_call_amd' debugging message which can't be avoided + # on this settings page. This debugging message can't be avoided as we simple use too much hide_if() there. + And the following config values are set as admin: + | debug | 0 | + | debugdisplay | 0 | + And I navigate to "Appearance > Boost Union > Content" in site administration + And I click on "Slider" "link" in the "#adminsettings .nav-tabs" "css_element" + And I upload "theme/boost_union/tests/fixtures/login_bg1.jpg" file to "Slide 2 background image" filemanager + # For a strange reason, Behat fails if we upload all images at once. So we simply save the form after each upload. + And I press "Save changes" + And I navigate to "Appearance > Boost Union > Content" in site administration + And I click on "Slider" "link" in the "#adminsettings .nav-tabs" "css_element" + And I upload "theme/boost_union/tests/fixtures/login_bg1.jpg" file to "Slide 3 background image" filemanager + And I press "Save changes" + And I navigate to "Appearance > Boost Union > Content" in site administration + And I click on "Slider" "link" in the "#adminsettings .nav-tabs" "css_element" + And I upload "theme/boost_union/tests/fixtures/login_bg1.jpg" file to "Slide 4 background image" filemanager + And I press "Save changes" + And I am on site homepage + # We reactivate debugging again. + And the following config values are set as admin: + | debug | 32767 | + | debugdisplay | 1 | + And I log out + When I log in as "teacher1" + And I am on site homepage + Then "#themeboostunionslide1 > a" "css_element" should not exist + And "#themeboostunionslide1 > .carousel-caption > a" "css_element" should not exist + And "#themeboostunionslide2 > a" "css_element" should exist + And "#themeboostunionslide2 > .carousel-caption > a" "css_element" should exist + And the "href" attribute of "#themeboostunionslide2 > a" "css_element" should contain "www.behat.de" + And the "href" attribute of "#themeboostunionslide2 > .carousel-caption > a" "css_element" should contain "www.behat.de" + And the "title" attribute of "#themeboostunionslide2 > a" "css_element" should not be set + And the "title" attribute of "#themeboostunionslide2 > .carousel-caption > a" "css_element" should not be set + And the "target" attribute of "#themeboostunionslide2 > a" "css_element" should not be set + And the "target" attribute of "#themeboostunionslide2 > .carousel-caption > a" "css_element" should not be set + And the "rel" attribute of "#themeboostunionslide2 > a" "css_element" should not be set + And the "rel" attribute of "#themeboostunionslide2 > .carousel-caption > a" "css_element" should not be set + And "#themeboostunionslide3 > a" "css_element" should exist + And "#themeboostunionslide3 > .carousel-caption > a" "css_element" should not exist + And the "href" attribute of "#themeboostunionslide3 > a" "css_element" should contain "www.behat.com" + And the "title" attribute of "#themeboostunionslide3 > a" "css_element" should contain "Link to Behat" + And the "target" attribute of "#themeboostunionslide3 > a" "css_element" should not be set + And the "rel" attribute of "#themeboostunionslide3 > a" "css_element" should not be set + And "#themeboostunionslide4 > a" "css_element" should not exist + And "#themeboostunionslide4 > .carousel-caption > a" "css_element" should exist + And the "href" attribute of "#themeboostunionslide4 > .carousel-caption > a" "css_element" should contain "www.google.com" + And the "title" attribute of "#themeboostunionslide4 > .carousel-caption > a" "css_element" should contain "Link to Google" + And the "target" attribute of "#themeboostunionslide4 > .carousel-caption > a" "css_element" should contain "_blank" + And the "rel" attribute of "#themeboostunionslide4 > .carousel-caption > a" "css_element" should contain "noreferrer" + And the "rel" attribute of "#themeboostunionslide4 > .carousel-caption > a" "css_element" should contain "noreferrer" + + Scenario Outline: Setting: Slider - Display the slides according to the configured orders + Given the following config values are set as admin: + | config | value | plugin | + | slide1enabled | yes | theme_boost_union | + | slide1content | This is a test content for tile 1 | theme_boost_union | + | slide1order | | theme_boost_union | + | slide2enabled | yes | theme_boost_union | + | slide2content | This is a test content for tile 2 | theme_boost_union | + | slide2order | | theme_boost_union | + | slide4enabled | yes | theme_boost_union | + | slide4content | This is a test content for tile 4 | theme_boost_union | + | slide4order | | theme_boost_union | + | slide6enabled | yes | theme_boost_union | + | slide6content | This is a test content for tile 6 | theme_boost_union | + | slide6order | | theme_boost_union | + And I log in as "admin" + # We deactivate debugging for a while as the Behat step would otherwise fail due to the + # stupid 'Too much data passed as arguments to js_call_amd' debugging message which can't be avoided + # on this settings page. This debugging message can't be avoided as we simple use too much hide_if() there. + And the following config values are set as admin: + | debug | 0 | + | debugdisplay | 0 | + And I navigate to "Appearance > Boost Union > Content" in site administration + And I click on "Slider" "link" in the "#adminsettings .nav-tabs" "css_element" + And I upload "theme/boost_union/tests/fixtures/login_bg1.jpg" file to "Slide 2 background image" filemanager + # For a strange reason, Behat fails if we upload all images at once. So we simply save the form after each upload. + And I press "Save changes" + And I navigate to "Appearance > Boost Union > Content" in site administration + And I click on "Slider" "link" in the "#adminsettings .nav-tabs" "css_element" + And I upload "theme/boost_union/tests/fixtures/login_bg1.jpg" file to "Slide 4 background image" filemanager + And I press "Save changes" + And I navigate to "Appearance > Boost Union > Content" in site administration + And I click on "Slider" "link" in the "#adminsettings .nav-tabs" "css_element" + And I upload "theme/boost_union/tests/fixtures/login_bg1.jpg" file to "Slide 6 background image" filemanager + And I press "Save changes" + And I am on site homepage + # We reactivate debugging again. + And the following config values are set as admin: + | debug | 32767 | + | debugdisplay | 1 | + And I log out + When I log in as "teacher1" + And I am on site homepage + Then "//div[@id='themeboostunionslider']/div[contains(@class, 'carousel-inner')]/*[][@id='themeboostunionslide1']" "xpath_element" should exist + And "//div[@id='themeboostunionslider']/div[contains(@class, 'carousel-inner')]/*[][@id='themeboostunionslide2']" "xpath_element" should exist + And "//div[@id='themeboostunionslider']/div[contains(@class, 'carousel-inner')]/*[][@id='themeboostunionslide4']" "xpath_element" should exist + And "//div[@id='themeboostunionslider']/div[contains(@class, 'carousel-inner')]/*[][@id='themeboostunionslide6']" "xpath_element" should exist + + Examples: + | orders1 | positions1 | orders2 | positions2 | orders4 | positions4 | orders6 | positions6 | + | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 4 | + | 2 | 2 | 4 | 4 | 3 | 3 | 1 | 1 | + | 1 | 1 | 4 | 4 | 3 | 3 | 1 | 2 | + | 1 | 1 | 1 | 2 | 2 | 3 | 3 | 4 | + | 5 | 2 | 6 | 3 | 3 | 1 | 8 | 4 | + + Scenario: Setting: Slider - Show and hide the admin settings based on the main "Enable slide x" setting + Given the following config values are set as admin: + | config | value | plugin | + | slide1enabled | yes | theme_boost_union | + When I log in as "admin" + # We deactivate debugging for a while as the Behat step would otherwise fail due to the + # stupid 'Too much data passed as arguments to js_call_amd' debugging message which can't be avoided + # on this settings page. This debugging message can't be avoided as we simple use too much hide_if() there. + And the following config values are set as admin: + | debug | 0 | + | debugdisplay | 0 | + And I navigate to "Appearance > Boost Union > Content" in site administration + And I click on "Slider" "link" in the "#adminsettings .nav-tabs" "css_element" + Then "#admin-slide1backgroundimage" "css_element" should be visible + Then "#admin-slide3backgroundimage" "css_element" should not be visible + Then "#admin-slide4backgroundimage" "css_element" should not be visible + And I select "Yes" from the "Enable slide 4" singleselect + Then "#admin-slide1backgroundimage" "css_element" should be visible + Then "#admin-slide3backgroundimage" "css_element" should not be visible + Then "#admin-slide4backgroundimage" "css_element" should be visible + And I select "No" from the "Enable slide 1" singleselect + Then "#admin-slide1backgroundimage" "css_element" should not be visible + Then "#admin-slide3backgroundimage" "css_element" should not be visible + Then "#admin-slide4backgroundimage" "css_element" should be visible + + Scenario Outline: Setting: Slider - Display the configured content style + Given the following config values are set as admin: + | config | value | plugin | + | slide1contentstyle |