From e5c605a0d6850d969a4f4ade4154ebc8d430b675 Mon Sep 17 00:00:00 2001 From: Stephen Cameron Date: Thu, 2 Jul 2020 19:59:33 +0200 Subject: [PATCH] WIP #3673 @8 --- js/libs/fluidbook/fluidbook.menu.js | 91 +++++++++++++++--------- js/libs/fluidbook/fluidbook.slideshow.js | 77 +++++++++----------- style/fluidbook.slideshow.less | 26 +++---- 3 files changed, 101 insertions(+), 93 deletions(-) diff --git a/js/libs/fluidbook/fluidbook.menu.js b/js/libs/fluidbook/fluidbook.menu.js index c51e286d..5b9bb6dc 100644 --- a/js/libs/fluidbook/fluidbook.menu.js +++ b/js/libs/fluidbook/fluidbook.menu.js @@ -246,13 +246,16 @@ FluidbookMenu.prototype = { // TODO: check which type should be passed to fluidbook.stats.track() ??? // this.fluidbook.stats.track(11); + this.fluidbook.slideshow.initSlideshow('slideshow_' + slideshow); + + var $this = this; - var times = [250, 500, 750, 1000, 1250]; - $.each(times, function (k, v) { - setTimeout(function () { - $this.resize(); - }, v); - }); + // var times = [250, 500, 750, 1000, 1250]; + // $.each(times, function (k, v) { + // setTimeout(function () { + // $this.resize(); + // }, v); + // }); if (callback != undefined) { callback(); @@ -837,57 +840,81 @@ FluidbookMenu.prototype = { }).css('text-align', 'left'); break; case 'slideshow': - var w = Math.max(ww * 0.8); - var h = Math.max(hh * 0.8); - if (ww < 800) { - w = ww; - h = hh; - fullscreen = true; - $(".fb-slideshow").addClass('fb-slideshow-fullscreen'); - } else { - $(".fb-slideshow").removeClass('fb-slideshow-fullscreen'); + + var horizontalPadding = fluidbook.slideshow.$slideshow.outerWidth() - fluidbook.slideshow.$slideshow.width(); + var verticalPadding = fluidbook.slideshow.$slideshow.outerHeight() - fluidbook.slideshow.$slideshow.height(); + + // When resizing the slideshow, the goal is to fit it into the maxModalHeight. + // The thumbnails and caption can't be scaled so we must scale the height of the main image + // (it is already scaled for max-width via CSS) + var headerHeight = m.find('.caption').outerHeight(); // Height of title section that also contains close button + var thumbnailsHeight = 0; + if (m.find('.fb-slideshow-thumbnails').length > 0) { + thumbnailsHeight = m.find('.fb-slideshow-thumbnails').outerHeight(); // Thumbnail slider height } + // On small/short screens, thumbnails are hidden and close icon / header is reduced var optimizeHeight = (h < 600); + if (optimizeHeight) { - $(".fb-slideshow-thumbnails").addClass('fb-slideshow-nothumbs'); + fluidbook.slideshow.$thumbnails.hide(); + thumbnailsHeight = 0; m.find('.caption, .back').addClass('small'); } else { - $(".fb-slideshow-thumbnails").removeClass('fb-slideshow-nothumbs'); + fluidbook.slideshow.$thumbnails.show(); m.find('.caption, .back').removeClass('small'); } - // When resizing the slideshow, the goal is to fit it into the maximum modal height (stored in 'h'). - // The thumbnails and caption can't be scaled so we must scale the height of the main image - // (it is already scaled for max-width via CSS) + // Default on larger screens is for modal to cover 80% of area but only if image is large enough + w = Math.min(ww * 0.8, fluidbook.slideshow.maxImageWidth + horizontalPadding); + h = Math.min(hh * 0.8, fluidbook.slideshow.maxImageHeight + verticalPadding + headerHeight + thumbnailsHeight); - var headerHeight = m.find('.caption').outerHeight(); // Height of title section that also contains close button - var thumbnailsHeight = 0; - if (m.find('.fb-slideshow-thumbnails').length > 0) { - thumbnailsHeight = m.find('.fb-slideshow-thumbnails').outerHeight(); // Thumbnail slider height + if (optimizeHeight) { + // ToDo: test this more with and without captions activated. Needs refactoring for better transparency of logic + //var contentHeight = h; + var contentHeight = hh; } - if (optimizeHeight) { - thumbnailsHeight = 0; - var contentHeight = h; + // On smaller screens, modal covers full available space + if (ww < 800) { + w = ww; + h = hh; + fullscreen = true; + $(".fb-slideshow").addClass('fb-slideshow-fullscreen'); + } else { + $(".fb-slideshow").removeClass('fb-slideshow-fullscreen'); } + var slideMaxWidth = w - horizontalPadding; var slideMaxHeight = h - headerHeight - thumbnailsHeight; // Remaining height that main image + caption has to fit into + var maxCaptionHeight = 0; // Process each slide and calculate optimal height for image and slide container - m.find('.fb-slideshow-slide').each(function () { + fluidbook.slideshow.$slideshow.find('.fb-slideshow-slide').each(function () { // Set the height on this container so flexbox can vertically center // the contents when they don't take up the full height available - $(this).css('height', slideMaxHeight); + //$(this).find('.splide__slide__container').css('height', slideMaxHeight); + //console.log('setting h', slideMaxHeight); + + // The caption normally provides the space needed + // but if it's not present, we still count 30px of padding for the bottom var captionHeight = $(this).find('.fb-slideshow-slide-caption').outerHeight() || 0; + maxCaptionHeight = Math.max(captionHeight, maxCaptionHeight); + console.log('captionHeight | maxCaptionHeight', captionHeight, maxCaptionHeight); // Allow image to take up whatever height is left after accounting for the caption // This is only the max-height so the image might not end up being this tall... - $(this).find('.fb-slideshow-slide-image').css({ - 'max-height': slideMaxHeight - captionHeight - }); + // $(this).find('.fb-slideshow-slide-image').css({ + // 'max-height': slideMaxHeight - captionHeight + // }); }); + + fluidbook.slideshow.primarySlider.options.fixedHeight = slideMaxHeight - maxCaptionHeight; + fluidbook.slideshow.primarySlider.options.fixedWidth = slideMaxWidth; + + fluidbook.slideshow.primarySlider.refresh(); + break; case 'print': case 'download': diff --git a/js/libs/fluidbook/fluidbook.slideshow.js b/js/libs/fluidbook/fluidbook.slideshow.js index ca6c85a7..f44f8638 100644 --- a/js/libs/fluidbook/fluidbook.slideshow.js +++ b/js/libs/fluidbook/fluidbook.slideshow.js @@ -1,45 +1,58 @@ function FluidbookSlideshow(fluidbook) { this.fluidbook = fluidbook; - this.numSlides = 0; } FluidbookSlideshow.prototype = { initSlideshow: function (id) { - var $this = this; - var slideshowID = '#' + id; - var $slideshow = $(slideshowID); - var thumbnailsID = slideshowID + '_thumbnails'; - if ($slideshow.length === 0) { - console.warn('Slideshow not found: ' + slideshowID); + var $this = this; + this.slideshowID = '#' + id; + this.$slideshow = $(this.slideshowID); + this.thumbnailsID = this.slideshowID + '_thumbnails'; + this.$thumbnails = $(this.thumbnailsID); + this.showThumbnails = this.$slideshow.attr('data-thumbnails') === '1'; + this.maxImageHeight = 0; // Tallest image + this.maxImageWidth = 0; // Widest image + this.maxImageRatio = 0; // Largest aspect ratio among all images + + + if (this.$slideshow.length === 0) { + console.warn('Slideshow not found: ' + this.slideshowID); return false; } // Open slideshow at a specific image // Ref: https://team.cubedesigners.com/redmine/issues/3131 - var openIndex = parseInt($slideshow.attr('data-open-index')); + var openIndex = parseInt(this.$slideshow.attr('data-open-index')); if (isNaN(openIndex)) { openIndex = 1; } openIndex--; // Convert to zero-based index - var showThumbnails = $slideshow.attr('data-thumbnails') === '1'; + // Determine the maximum width, height and ratio for all images + this.$slideshow.find('img').each(function() { + var meta = $(this).data('meta'); + $this.maxImageHeight = Math.max(meta.height, $this.maxImageHeight); + $this.maxImageWidth = Math.max(meta.width, $this.maxImageWidth); + $this.maxImageRatio = Math.max(meta.width / meta.height, $this.maxImageRatio); + }); + // Height and width are set by fluidbook.menu resize function + // ToDo: see if it's better setting these options as a data attribute from the PHP side? Then certain options like type / start could be set from PHP directly. var slideshowSettings = { - type : 'loop', - height : showThumbnails ? '80%' : '100%', + type : 'loop', // slide | loop | fade start : openIndex, pagination : false, arrows : true, cover : true, // Will be set to 'contain' in CSS }; - var primarySlider = new Splide(slideshowID, slideshowSettings); + this.primarySlider = new Splide(this.slideshowID, slideshowSettings); - if (showThumbnails) { + if (this.showThumbnails) { - var thumbSlider = new Splide(thumbnailsID, { + this.thumbSlider = new Splide(this.thumbnailsID, { autoWidth : true, // Height is handled by the CSS start : openIndex, gap : 10, @@ -47,41 +60,15 @@ FluidbookSlideshow.prototype = { isNavigation: true, arrows : false, pagination : false, - focus : 'center', - // breakpoints : { - // '600': { - // fixedWidth: 100, - // height : 66, - // } - // }, + // ToDo: consider setting focus: 'center' dynamically in resize function only when the width of all thumbnails is wider than the modal width... + //focus : 'center', // Center mode doesn't work well when there aren't many thumbs } ); - thumbSlider.mount(); - - primarySlider.sync(thumbSlider); - - } - - - primarySlider.mount(); - - - /* - // Dynamically add thumbnails from full sized images - // Images have to load anyway so we can reuse full images for thumbnails - showThumbnails = showThumbnails && this.numSlides > 1; - - if (showThumbnails) { - $('
').appendTo($slideshow.parent()); - $thumbnails = $('#' + thumbnailsID); - - $slideshow.find('img').each(function () { - var img = $(this).clone(); - $thumbnails.append(img); - }); + this.thumbSlider.mount(); + this.primarySlider.sync(this.thumbSlider); } - */ + this.primarySlider.mount(); } /* diff --git a/style/fluidbook.slideshow.less b/style/fluidbook.slideshow.less index c6bcee55..c823217f 100644 --- a/style/fluidbook.slideshow.less +++ b/style/fluidbook.slideshow.less @@ -38,7 +38,7 @@ //=== List &__list { - margin: 0 !important; + margin: 0 auto !important; padding: 0 !important; width: max-content; will-change: transform; @@ -334,20 +334,20 @@ } &-slide { - position: relative; - display: flex !important; - flex-direction: column; - justify-content: center; - text-align: center; + //position: relative; + //display: flex !important; + //flex-direction: column; + //justify-content: center; + //text-align: center; //visibility: hidden; // Hide until JS can resize the images to avoid flicker - &-image { - margin: 0 auto; - } + //&-image { + // margin: 0 auto; + //} &-caption { font-size: 75%; - padding: 1em 0; + padding: 1em; } } @@ -364,12 +364,6 @@ width: auto; cursor: pointer; } - - .slick-current { - // Using outline so it doesn't affect layout or image size - outline: 5px solid @menu-select-background; - outline-offset: -5px; - } } } -- 2.39.5