From 8c0461603e06d659d98a4f46ae8028ba0ea1025a Mon Sep 17 00:00:00 2001 From: Stephen Cameron Date: Mon, 28 Sep 2020 16:33:01 +0200 Subject: [PATCH] WIP #3881 @4 --- js/libs/fluidbook/fluidbook.menu.js | 62 +++++++++++++++++++----- js/libs/fluidbook/fluidbook.slideshow.js | 11 ----- style/fluidbook.less | 2 +- style/fluidbook.slideshow.less | 8 +++ 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/js/libs/fluidbook/fluidbook.menu.js b/js/libs/fluidbook/fluidbook.menu.js index f96079bd..6dbc4435 100644 --- a/js/libs/fluidbook/fluidbook.menu.js +++ b/js/libs/fluidbook/fluidbook.menu.js @@ -919,9 +919,9 @@ FluidbookMenu.prototype = { // can be zero or negative. This causes an ugly jump with the thumbnails and a content redraw // so we make it invisible until it is ready (resize function runs more than once) if (fluidbook.slideshow.$wrapper.height() <= 0) { - fluidbook.slideshow.$wrapper.css('opacity', 0); + m.addClass('hidden'); } else { - fluidbook.slideshow.$wrapper.css('opacity', 1); + m.removeClass('hidden'); } var horizontalPadding = fluidbook.slideshow.$slideshow.outerWidth() - fluidbook.slideshow.$slideshow.width(); @@ -951,30 +951,70 @@ FluidbookMenu.prototype = { m.find('.caption, .back, .fb-slideshow-wrapper').removeClass('small'); } - // Default on larger screens is for modal to cover 80% of area but only if image is large enough - w = Math.round(Math.min(ww * 0.8, fluidbook.slideshow.maxImageWidth + horizontalPadding)); - h = Math.round(Math.min(hh * 0.8, fluidbook.slideshow.maxImageHeight + verticalPadding + headerHeight + thumbnailsHeight)); - - //console.log('%cMODAL W: '+ w +' | H: '+ h, lcss+'orangered'); - if (optimizeHeight) { // ToDo: test this more with and without captions activated. Needs refactoring for better transparency of logic //var contentHeight = h; var contentHeight = hh; } + // On larger screens, the modal is sized based on a best fit for all images so that they are + // as large as possible but not so large that the modal exceeds 80% of the screen width and height. + // The modal should never be larger than necessary for the images + var maxModalWidth = Math.round(ww * 0.8); // Hard limit for modal width + var maxModalHeight = Math.round(hh * 0.8); // Hard limit for modal height + var maxImageWidth = maxModalWidth - horizontalPadding; // Hard limit for slideshow image width + var maxImageHeight = maxModalHeight - verticalPadding - headerHeight - thumbnailsHeight; // Hard limit for slideshow image height + var targetRatio = maxImageWidth / maxImageHeight; + var slideMaxWidth = 0; // Stores the largest scaled image width found + var slideMaxHeight = 0; // Stores the largest scaled image height found + + // console.log('%cmaxImgW: '+ maxImageWidth +' | maxImageH: '+ maxImageHeight, lcss+'blueviolet') + + // Process each image to determine dimensions and how big it will be once scaled onto the screen + fluidbook.slideshow.$slideshow.find('img').each(function() { + var meta = $(this).data('meta'); + var scaledWidth = 0; + var scaledHeight = 0; + + if (meta.width > maxImageWidth || meta.height > maxImageHeight) { // Does it need scaling? + // Scale to fit depending on ratio (best fit for box) + if (targetRatio > meta.ratio) { + scaledWidth = Math.round(meta.width * maxImageHeight / meta.height); + scaledHeight = maxImageHeight + } else { + scaledWidth = maxImageWidth; + scaledHeight = Math.round(meta.height * maxImageWidth / meta.width); + } + + } else { + scaledWidth = meta.width; + scaledHeight = meta.height; + } + + // console.log('%cscaledW: '+ scaledWidth +' | ScaledH: '+ scaledHeight, lcss+'crimson') + + slideMaxWidth = Math.max(scaledWidth, slideMaxWidth); + slideMaxHeight = Math.max(scaledHeight, slideMaxHeight); + }); + + w = slideMaxWidth + horizontalPadding; + h = slideMaxHeight + headerHeight + thumbnailsHeight + verticalPadding; + + // On smaller screens, modal covers full available space - if (ww < 800) { + if (ww < 800 || hh < 500) { w = ww; h = hh; fullscreen = true; + slideMaxWidth = w - horizontalPadding; + slideMaxHeight = h - headerHeight - thumbnailsHeight - verticalPadding; $('.fb-slideshow, .fb-slideshow-thumbnails').addClass('fb-slideshow-fullscreen'); } else { $('.fb-slideshow, .fb-slideshow-thumbnails').removeClass('fb-slideshow-fullscreen'); } - var slideMaxWidth = w - horizontalPadding; - var slideMaxHeight = h - headerHeight - thumbnailsHeight - verticalPadding; // Remaining height that main image + caption has to fit into + // console.log('%cMODAL W: '+ w +' | H: '+ h, lcss+'orangered'); + // console.log('%cslideMaxWidth: '+ slideMaxWidth +' %cslideMaxHeight: '+ slideMaxHeight, lcss+'teal', lcss+'dodgerblue'); // console.log('%cslideMaxHeight: '+ slideMaxHeight +' %cheaderHeight: '+ headerHeight +' %cthumbnailsHeight: '+thumbnailsHeight, lcss+'teal', lcss+'blueviolet', lcss+'crimson'); // console.log('%cMain slideshow height: '+ $('.fb-slideshow').height(), lcss+'hotpink'); diff --git a/js/libs/fluidbook/fluidbook.slideshow.js b/js/libs/fluidbook/fluidbook.slideshow.js index fa8b1511..609ce906 100644 --- a/js/libs/fluidbook/fluidbook.slideshow.js +++ b/js/libs/fluidbook/fluidbook.slideshow.js @@ -12,9 +12,6 @@ FluidbookSlideshow.prototype = { 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) { @@ -30,14 +27,6 @@ FluidbookSlideshow.prototype = { } openIndex--; // Convert to zero-based index - // 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 // Note: certain settings are set via the data-splide attribute, generated on the server-side var slideshowSettings = { diff --git a/style/fluidbook.less b/style/fluidbook.less index e204264b..157092f0 100644 --- a/style/fluidbook.less +++ b/style/fluidbook.less @@ -2929,4 +2929,4 @@ body > input { @import "tabs.less"; @import "widget.less"; @import "menu-articles.less"; -@import "nointerface.less"; \ No newline at end of file +@import "nointerface.less"; diff --git a/style/fluidbook.slideshow.less b/style/fluidbook.slideshow.less index 75eba7b5..f783e0d1 100644 --- a/style/fluidbook.slideshow.less +++ b/style/fluidbook.slideshow.less @@ -328,6 +328,10 @@ // Slideshow Module +[data-menu="slideshow"].hidden { + opacity: 0 !important; +} + .fb-slideshow-wrapper { padding-bottom: 60px; transition: opacity 0.15s; @@ -335,6 +339,10 @@ &.small { padding-bottom: 30px; } + + @media (max-width: 799px) { + padding-bottom: 30px; + } } .fb-slideshow { -- 2.39.5