]> _ Git - fluidbook-html5.git/commitdiff
wip #4083 @3
authorVincent Vanwaelscappel <vincent@cubedesigners.com>
Fri, 20 Nov 2020 19:03:17 +0000 (20:03 +0100)
committerVincent Vanwaelscappel <vincent@cubedesigners.com>
Fri, 20 Nov 2020 19:03:17 +0000 (20:03 +0100)
js/libs/fluidbook/fluidbook.js
js/libs/fluidbook/fluidbook.menu.js
js/libs/fluidbook/fluidbook.slideshow.js [deleted file]
js/libs/fluidbook/slideshow/fluidbook.slideshow.dummy.js [new file with mode: 0644]
js/libs/fluidbook/slideshow/fluidbook.slideshow.js [new file with mode: 0644]
js/libs/fluidbook/slideshow/fluidbook.slideshow.splide.js [new file with mode: 0644]
js/libs/fluidbook/slideshow/fluidbook.slideshow.vacheron.js [new file with mode: 0644]

index ad63f3b8b0ec9ac87c26a017b1f51a9ec3191bb0..3e43737cc9953764b60ca2091f25313977b3e880 100644 (file)
@@ -83,7 +83,9 @@ Fluidbook.prototype = {
         this.tooltip = new FluidbookTooltip(this);
         this.accessibility = new FluidbookAccessibility(this);
         this.sound = new FluidbookSound(this);
-        this.slideshow = new FluidbookSlideshow(this);
+        if (window.FluidbookSlideshow) {
+            this.slideshow = new FluidbookSlideshow(this);
+        }
         this.printing = new FluidbookPrint(this);
         this.posad = new FluidbookPOSAd(this);
         this.notes = new FluidbookNotes(this);
index 191f235e337a5f2cabe80d290359ef0565699639..214dc6345dacb9b799b8faf37aeb5a1a9d0ee9bc 100644 (file)
@@ -313,7 +313,7 @@ FluidbookMenu.prototype = {
         // TODO: check which type should be passed to fluidbook.stats.track() ???
         // this.fluidbook.stats.track(11);
 
-        this.fluidbook.slideshow.initSlideshow('slideshow_' + slideshow);
+        this.fluidbook.slideshow.initPopupSlideshow('slideshow_' + slideshow);
 
         // var $this = this;
         // var times = [250, 500, 750, 1000, 1250];
@@ -909,151 +909,10 @@ FluidbookMenu.prototype = {
                 }).css('text-align', 'left');
                 break;
             case 'slideshow':
-
-                // The slideshow should scale to the optimium size: no larger than 80% of screen width or height
-                // but also only as large as necessary for the included images (which are scaled to fit the screen ratio)
-
-                // When the resize function fires, the slideshow might not yet be fully ready so the heights
-                // 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) {
-                    m.addClass('hidden');
-                } else {
-                    m.removeClass('hidden');
-                }
-
-                var horizontalPadding = fluidbook.slideshow.$slideshow.outerWidth() - fluidbook.slideshow.$slideshow.width();
-                var verticalPadding = fluidbook.slideshow.$wrapper.outerHeight() - fluidbook.slideshow.$wrapper.height();
-
-                // var lcss = 'color:#fff;padding:0.5em;background:';
-                // console.log('%cWRAPPER: '+ fluidbook.slideshow.$wrapper.height() +' | ' + fluidbook.slideshow.$wrapper.outerHeight(), lcss+'dodgerblue');
-                // console.log('%cVPad: '+ verticalPadding + ' | HPad: '+ horizontalPadding, lcss+'green');
-
-                var headerHeight = m.find('.caption').outerHeight(); // Height of title section that also contains close button
-                var thumbnailsPresent = false;
-                var thumbnailsHeight = 0;
-                if (m.find('.fb-slideshow-thumbnails').length > 0) {
-                    thumbnailsPresent = true;
-                    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) {
-                    fluidbook.slideshow.$thumbnails.hide();
-                    thumbnailsHeight = 0;
-                    m.find('.caption, .back, .fb-slideshow-wrapper').addClass('small');
-                } else {
-                    fluidbook.slideshow.$thumbnails.show();
-                    m.find('.caption, .back, .fb-slideshow-wrapper').removeClass('small');
-                }
-
-                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 || 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');
-                }
-
-                // 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');
-
-                // Process each slide and calculate optimal height for image and slide container
-                fluidbook.slideshow.$slideshow.find('.fb-slideshow-slide').each(function () {
-                    // Get slide's caption height, if present
-                    var captionHeight = $(this).find('.fb-slideshow-slide-caption').outerHeight() || 0;
-
-                    // 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...
-                    var slideHeight = $(this).outerHeight();
-                    $(this).find('.fb-slideshow-slide-image').css({
-                        'max-height': slideMaxHeight - captionHeight
-                    });
-                });
-
-                // Don't attempt to interact with slider if it's not ready (resize function may run early)
-                if (!fluidbook.slideshow.primarySlider) break;
-
-                fluidbook.slideshow.primarySlider.options.fixedHeight = slideMaxHeight;
-                fluidbook.slideshow.primarySlider.options.fixedWidth = slideMaxWidth;
-
-                // If thumbnail slider content is wider than available space, enable dragging and focus:center mode
-                if (thumbnailsPresent) {
-                    if (fluidbook.slideshow.$thumbnails.find('.splide__list').width() >= slideMaxWidth) {
-                        fluidbook.slideshow.thumbSlider.options = {
-                            drag: true,
-                            focus: 'center',
-                        }
-                    } else {
-                        fluidbook.slideshow.thumbSlider.options = {
-                            drag: false,
-                            focus: false,
-                        }
-                    }
-                    fluidbook.slideshow.thumbSlider.refresh();
-                }
-
-                fluidbook.slideshow.primarySlider.refresh();
-
+                var res = this.fluidbook.slideshow.popupInstance.resize(ww, hh, m);
+                w = res.w;
+                h = res.h;
+                fullscreen = res.fullscreen;
                 break;
             case 'print':
             case 'download':
diff --git a/js/libs/fluidbook/fluidbook.slideshow.js b/js/libs/fluidbook/fluidbook.slideshow.js
deleted file mode 100644 (file)
index 609ce90..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-function FluidbookSlideshow(fluidbook) {
-    this.fluidbook = fluidbook;
-}
-
-FluidbookSlideshow.prototype = {
-    initSlideshow: function (id) {
-
-        var $this = this;
-        this.slideshowID = '#' + id;
-        this.$slideshow = $(this.slideshowID);
-        this.$wrapper = this.$slideshow.parent();
-        this.thumbnailsID = this.slideshowID + '_thumbnails';
-        this.$thumbnails = $(this.thumbnailsID);
-        this.showThumbnails = this.$slideshow.attr('data-thumbnails') === '1';
-
-
-        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(this.$slideshow.attr('data-open-index'));
-        if (isNaN(openIndex)) {
-            openIndex = 1;
-        }
-        openIndex--; // Convert to zero-based index
-
-        // 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 = {
-            type       : 'loop', // slide | loop | fade
-            start      : openIndex,
-            pagination : false,
-            arrows     : true,
-        };
-
-        this.primarySlider = new Splide(this.slideshowID, slideshowSettings);
-
-
-        if (this.showThumbnails) {
-
-            this.thumbSlider = new Splide(this.thumbnailsID, {
-                autoWidth   : true, // Height is handled by the CSS
-                start       : openIndex,
-                gap         : 10,
-                cover       : false,
-                isNavigation: true,
-                arrows      : false,
-                pagination  : false,
-                drag        : false, // Will be enabled along with focus:center if thumbs are wider than available space
-            } );
-
-            this.thumbSlider.mount();
-            this.primarySlider.sync(this.thumbSlider);
-        }
-
-        this.primarySlider.mount();
-    }
-};
diff --git a/js/libs/fluidbook/slideshow/fluidbook.slideshow.dummy.js b/js/libs/fluidbook/slideshow/fluidbook.slideshow.dummy.js
new file mode 100644 (file)
index 0000000..eb8423b
--- /dev/null
@@ -0,0 +1,8 @@
+function FluidbookVacheronSlideshow(fluidbook) {
+    this.fluidbook = fluidbook;
+}
+
+FluidbookVacheronSlideshow.prototype = {
+    initSlideshow: function (id) {
+    }
+};
diff --git a/js/libs/fluidbook/slideshow/fluidbook.slideshow.js b/js/libs/fluidbook/slideshow/fluidbook.slideshow.js
new file mode 100644 (file)
index 0000000..962f54a
--- /dev/null
@@ -0,0 +1,43 @@
+function FluidbookSlideshow(fluidbook) {
+    this.fluidbook = fluidbook;
+    this.instances = {inline: null, popup: null};
+
+    var $this = this;
+
+    $.each(this.instances, function (k, v) {
+        var s = (k === 'inline' ? $this.fluidbook.settings.slideshowInlineLibrary : $this.fluidbook.settings.slideshowPopupLibrary);
+        switch (s) {
+            case 'dummy':
+                $this.instances[k] = new FluidbookDummySlideshow($this.fluidbook);
+            case 'vacheron':
+                $this.instances[k] = new FluidbookVacheronSlideshow($this.fluidbook);
+                break;
+            case undefined:
+            case null:
+            case 'splide':
+            default:
+                $this.instances[k] = new FluidbookSplideSlideshow($this.fluidbook);
+                break;
+        }
+    });
+
+    this.popupInstance = $this.instances['popup'];
+    this.inlineInstance = $this.instances['inline'];
+}
+
+FluidbookSlideshow.prototype = {
+    initPopupSlideshow: function (id) {
+        this.popupInstance.initSlideshow(id);
+    },
+
+    initInlineSlideshow: function (id) {
+        this.inlineInstance.initSlideshow(id);
+    },
+    initSlideshow: function (id, context) {
+        if (context === 'popup') {
+            this.initPopupSlideshow(id);
+        } else if (context === 'inline') {
+            this.initInlineSlideshow(id);
+        }
+    }
+};
diff --git a/js/libs/fluidbook/slideshow/fluidbook.slideshow.splide.js b/js/libs/fluidbook/slideshow/fluidbook.slideshow.splide.js
new file mode 100644 (file)
index 0000000..66b3bfb
--- /dev/null
@@ -0,0 +1,211 @@
+function FluidbookSplideSlideshow(fluidbook) {
+    this.fluidbook = fluidbook;
+}
+
+FluidbookSplideSlideshow.prototype = {
+    initSlideshow: function (id) {
+        this.slideshowID = '#' + id;
+        this.$slideshow = $(this.slideshowID);
+        this.$wrapper = this.$slideshow.parent();
+        this.thumbnailsID = this.slideshowID + '_thumbnails';
+        this.$thumbnails = $(this.thumbnailsID);
+        this.showThumbnails = this.$slideshow.attr('data-thumbnails') === '1';
+
+        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(this.$slideshow.attr('data-open-index'));
+        if (isNaN(openIndex)) {
+            openIndex = 1;
+        }
+        openIndex--; // Convert to zero-based index
+
+        // 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 = {
+            type: 'loop', // slide | loop | fade
+            start: openIndex,
+            pagination: false,
+            arrows: true,
+        };
+
+        this.primarySlider = new Splide(this.slideshowID, slideshowSettings);
+
+        if (this.showThumbnails) {
+            this.thumbSlider = new Splide(this.thumbnailsID, {
+                autoWidth: true, // Height is handled by the CSS
+                start: openIndex,
+                gap: 10,
+                cover: false,
+                isNavigation: true,
+                arrows: false,
+                pagination: false,
+                drag: false, // Will be enabled along with focus:center if thumbs are wider than available space
+            });
+
+            this.thumbSlider.mount();
+            this.primarySlider.sync(this.thumbSlider);
+        }
+
+        this.primarySlider.mount();
+    },
+
+    resize: function (ww, hh, m) {
+        var w = ww * 0.8;
+        var h = hh * 0.8;
+        var fullscreen = false;
+
+        // The slideshow should scale to the optimium size: no larger than 80% of screen width or height
+        // but also only as large as necessary for the included images (which are scaled to fit the screen ratio)
+
+        // When the resize function fires, the slideshow might not yet be fully ready so the heights
+        // 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 (this.$wrapper === undefined) {
+            return {w: w, h: h, fullscreen: fullscreen};
+        }
+        if (this.$wrapper.height() <= 0) {
+            m.addClass('hidden');
+        } else {
+            m.removeClass('hidden');
+        }
+
+        var horizontalPadding = this.$slideshow.outerWidth() - this.$slideshow.width();
+        var verticalPadding = this.$wrapper.outerHeight() - this.$wrapper.height();
+
+        // var lcss = 'color:#fff;padding:0.5em;background:';
+        // console.log('%cWRAPPER: '+ this.$wrapper.height() +' | ' + this.$wrapper.outerHeight(), lcss+'dodgerblue');
+        // console.log('%cVPad: '+ verticalPadding + ' | HPad: '+ horizontalPadding, lcss+'green');
+
+        var headerHeight = m.find('.caption').outerHeight(); // Height of title section that also contains close button
+        var thumbnailsPresent = false;
+        var thumbnailsHeight = 0;
+        if (m.find('.fb-slideshow-thumbnails').length > 0) {
+            thumbnailsPresent = true;
+            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) {
+            this.$thumbnails.hide();
+            thumbnailsHeight = 0;
+            m.find('.caption, .back, .fb-slideshow-wrapper').addClass('small');
+        } else {
+            this.$thumbnails.show();
+            m.find('.caption, .back, .fb-slideshow-wrapper').removeClass('small');
+        }
+
+        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
+        this.$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 || 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');
+        }
+
+        // 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');
+
+        // Process each slide and calculate optimal height for image and slide container
+        this.$slideshow.find('.fb-slideshow-slide').each(function () {
+            // Get slide's caption height, if present
+            var captionHeight = $(this).find('.fb-slideshow-slide-caption').outerHeight() || 0;
+
+            // 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...
+            var slideHeight = $(this).outerHeight();
+            $(this).find('.fb-slideshow-slide-image').css({
+                'max-height': slideMaxHeight - captionHeight
+            });
+        });
+
+        // Don't attempt to interact with slider if it's not ready (resize function may run early)
+        if (!this.primarySlider) {
+            return {w: w, h: h, fullscreen: fullscreen};
+        }
+
+        this.primarySlider.options.fixedHeight = slideMaxHeight;
+        this.primarySlider.options.fixedWidth = slideMaxWidth;
+
+        // If thumbnail slider content is wider than available space, enable dragging and focus:center mode
+        if (thumbnailsPresent) {
+            if (this.$thumbnails.find('.splide__list').width() >= slideMaxWidth) {
+                this.thumbSlider.options = {
+                    drag: true,
+                    focus: 'center',
+                }
+            } else {
+                this.thumbSlider.options = {
+                    drag: false,
+                    focus: false,
+                }
+            }
+            this.thumbSlider.refresh();
+        }
+
+        this.primarySlider.refresh();
+        return {w: w, h: h, fullscreen: fullscreen};
+    }
+};
diff --git a/js/libs/fluidbook/slideshow/fluidbook.slideshow.vacheron.js b/js/libs/fluidbook/slideshow/fluidbook.slideshow.vacheron.js
new file mode 100644 (file)
index 0000000..1017856
--- /dev/null
@@ -0,0 +1,8 @@
+function FluidbookDummySlideshow(fluidbook) {
+    this.fluidbook = fluidbook;
+}
+
+FluidbookDummySlideshow.prototype = {
+    initSlideshow: function (id) {
+    }
+};