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);
// 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];
}).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':
+++ /dev/null
-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();
- }
-};
--- /dev/null
+function FluidbookVacheronSlideshow(fluidbook) {
+ this.fluidbook = fluidbook;
+}
+
+FluidbookVacheronSlideshow.prototype = {
+ initSlideshow: function (id) {
+ }
+};
--- /dev/null
+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);
+ }
+ }
+};
--- /dev/null
+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};
+ }
+};
--- /dev/null
+function FluidbookDummySlideshow(fluidbook) {
+ this.fluidbook = fluidbook;
+}
+
+FluidbookDummySlideshow.prototype = {
+ initSlideshow: function (id) {
+ }
+};