lightbox refactor

This commit is contained in:
Hakim El Hattab
2025-03-25 11:14:46 +01:00
parent aa9dfc7eb8
commit 1923a5c7a4
10 changed files with 56 additions and 38 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+38 -24
View File
@@ -10,8 +10,8 @@ export default class Overlay {
this.onSlidesClicked = this.onSlidesClicked.bind( this ); this.onSlidesClicked = this.onSlidesClicked.bind( this );
this.linkPreviewSelector = null; this.iframeTriggerSelector = null;
this.mediaPreviewSelector = '[data-preview-image], [data-preview-video]'; this.mediaTriggerSelector = '[data-preview-image], [data-preview-video]';
this.state = {}; this.state = {};
@@ -21,18 +21,18 @@ export default class Overlay {
// Enable link previews globally // Enable link previews globally
if( this.Reveal.getConfig().previewLinks ) { if( this.Reveal.getConfig().previewLinks ) {
this.linkPreviewSelector = 'a[href]:not([data-preview-link=false]), [data-preview-link]:not(a):not([data-preview-link=false])'; this.iframeTriggerSelector = 'a[href]:not([data-preview-link=false]), [data-preview-link]:not(a):not([data-preview-link=false])';
} }
// Enable link previews for individual elements // Enable link previews for individual elements
else { else {
this.linkPreviewSelector = '[data-preview-link]:not([data-preview-link=false])'; this.iframeTriggerSelector = '[data-preview-link]:not([data-preview-link=false])';
} }
this.hasLinkPreviews = this.Reveal.getSlidesElement().querySelectorAll( this.linkPreviewSelector ).length > 0; const hasLinkPreviews = this.Reveal.getSlidesElement().querySelectorAll( this.iframeTriggerSelector ).length > 0;
this.hasMediaPreviews = this.Reveal.getSlidesElement().querySelectorAll( this.mediaPreviewSelector ).length > 0; const hasMediaPreviews = this.Reveal.getSlidesElement().querySelectorAll( this.mediaTriggerSelector ).length > 0;
// Only add the listener when there are previewable elements in the slides // Only add the listener when there are previewable elements in the slides
if( this.hasLinkPreviews || this.hasMediaPreviews ) { if( hasLinkPreviews || hasMediaPreviews ) {
this.Reveal.getSlidesElement().addEventListener( 'click', this.onSlidesClicked, false ); this.Reveal.getSlidesElement().addEventListener( 'click', this.onSlidesClicked, false );
} }
else { else {
@@ -56,11 +56,11 @@ export default class Overlay {
} }
/** /**
* Opens a preview window for the target URL. * Opens a lightbox that previews the target URL.
* *
* @param {string} url - url for preview iframe src * @param {string} url - url for lightbox iframe src
*/ */
showIframePreview( url ) { previewIframe( url ) {
this.close(); this.close();
@@ -95,19 +95,19 @@ export default class Overlay {
this.close(); this.close();
}, false ); }, false );
this.Reveal.dispatchEvent({ type: 'showiframepreview', data: { url } }); this.Reveal.dispatchEvent({ type: 'previewiframe', data: { url } });
} }
/** /**
* Opens a preview window that provides a larger view of the * Opens a lightbox window that provides a larger view of the
* given image/video. * given image/video.
* *
* @param {string} url - url to the image/video to preview * @param {string} url - url to the image/video to preview
* @param {image|video} mediaType * @param {image|video} mediaType
* @param {string} [fitMode] - the fit mode to use for the preview * @param {string} [fitMode] - the fit mode to use for the preview
*/ */
showMediaPreview( url, mediaType, fitMode ) { previewMedia( url, mediaType, fitMode ) {
if( mediaType !== 'image' && mediaType !== 'video' ) { if( mediaType !== 'image' && mediaType !== 'video' ) {
console.warn( 'Please specify a valid media type to preview (image|video)' ); console.warn( 'Please specify a valid media type to preview (image|video)' );
@@ -155,6 +155,8 @@ export default class Overlay {
this.close(); this.close();
}, false ); }, false );
this.Reveal.dispatchEvent({ type: 'previewimage', data: { url } });
} }
else if( mediaType === 'video' ) { else if( mediaType === 'video' ) {
@@ -179,6 +181,8 @@ export default class Overlay {
`<span class="r-overlay-error">Unable to load video.</span>`; `<span class="r-overlay-error">Unable to load video.</span>`;
}, false ); }, false );
this.Reveal.dispatchEvent({ type: 'previewvideo', data: { url } });
} }
else { else {
throw new Error( 'Please specify a valid media type to preview' ); throw new Error( 'Please specify a valid media type to preview' );
@@ -189,7 +193,17 @@ export default class Overlay {
event.preventDefault(); event.preventDefault();
}, false ); }, false );
this.Reveal.dispatchEvent({ type: 'showmediapreview', data: { mediaType, url } }); }
previewImage( url, fitMode ) {
this.previewMedia( url, 'image', fitMode );
}
previewVideo( url, fitMode ) {
this.previewMedia( url, 'video', fitMode );
} }
@@ -300,13 +314,13 @@ export default class Overlay {
setState( state ) { setState( state ) {
if( state.previewIframe ) { if( state.previewIframe ) {
this.showIframePreview( state.previewIframe ); this.previewIframe( state.previewIframe );
} }
else if( state.previewImage ) { else if( state.previewImage ) {
this.showMediaPreview( state.previewImage, 'image', state.previewFit ); this.previewImage( state.previewImage, state.previewFit );
} }
else if( state.previewVideo ) { else if( state.previewVideo ) {
this.showMediaPreview( state.previewVideo, 'video', state.previewFit ); this.previewVideo( state.previewVideo, state.previewFit );
} }
else { else {
this.close(); this.close();
@@ -318,10 +332,10 @@ export default class Overlay {
const target = event.target; const target = event.target;
const linkTarget = target.closest( this.linkPreviewSelector ); const linkTarget = target.closest( this.iframeTriggerSelector );
const mediaTarget = target.closest( this.mediaPreviewSelector ); const mediaTarget = target.closest( this.mediaTriggerSelector );
// Was a link preview clicked? // Was an iframe lightbox trigger clicked?
if( linkTarget ) { if( linkTarget ) {
if( event.metaKey || event.shiftKey || event.altKey ) { if( event.metaKey || event.shiftKey || event.altKey ) {
// Let the browser handle meta keys naturally so users can cmd+click, cmd+shift+click, shift+click, alt+click, etc. // Let the browser handle meta keys naturally so users can cmd+click, cmd+shift+click, shift+click, alt+click, etc.
@@ -329,16 +343,16 @@ export default class Overlay {
} }
let url = linkTarget.getAttribute( 'href' ) || linkTarget.getAttribute( 'data-preview-link' ); let url = linkTarget.getAttribute( 'href' ) || linkTarget.getAttribute( 'data-preview-link' );
if( url ) { if( url ) {
this.showIframePreview( url ); this.previewIframe( url );
event.preventDefault(); event.preventDefault();
} }
} }
// Was a media preview clicked? // Was a media lightbox trigger clicked?
else if( mediaTarget ) { else if( mediaTarget ) {
if( mediaTarget.hasAttribute( 'data-preview-image' ) ) { if( mediaTarget.hasAttribute( 'data-preview-image' ) ) {
let url = mediaTarget.dataset.previewImage || mediaTarget.getAttribute( 'src' ); let url = mediaTarget.dataset.previewImage || mediaTarget.getAttribute( 'src' );
if( url ) { if( url ) {
this.showMediaPreview( url, 'image', mediaTarget.dataset.previewFit ); this.previewImage( url, mediaTarget.dataset.previewFit );
event.preventDefault(); event.preventDefault();
} }
} }
@@ -351,7 +365,7 @@ export default class Overlay {
} }
} }
if( url ) { if( url ) {
this.showMediaPreview( url, 'video', mediaTarget.dataset.previewFit ); this.previewVideo( url, mediaTarget.dataset.previewFit );
event.preventDefault(); event.preventDefault();
} }
} }
+6 -4
View File
@@ -2766,10 +2766,12 @@ export default function( revealElement, options ) {
startEmbeddedContent: () => slideContent.startEmbeddedContent( currentSlide ), startEmbeddedContent: () => slideContent.startEmbeddedContent( currentSlide ),
stopEmbeddedContent: () => slideContent.stopEmbeddedContent( currentSlide, { unloadIframes: false } ), stopEmbeddedContent: () => slideContent.stopEmbeddedContent( currentSlide, { unloadIframes: false } ),
// Preview management // Lightbox previews
showIframePreview: overlay.showIframePreview.bind( overlay ), previewIframe: overlay.previewIframe.bind( overlay ),
showMediaPreview: overlay.showMediaPreview.bind( overlay ), previewImage: overlay.previewImage.bind( overlay ),
showPreview: overlay.showIframePreview.bind( overlay ), // deprecated in favor of showIframePreview previewVideo: overlay.previewVideo.bind( overlay ),
showPreview: overlay.previewIframe.bind( overlay ), // deprecated in favor of showIframeLightbox
hidePreview: overlay.close.bind( overlay ), hidePreview: overlay.close.bind( overlay ),
// Adds or removes all internal event listeners // Adds or removes all internal event listeners
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -2
View File
@@ -209,8 +209,9 @@ const Plugin = () => {
deck.on( 'overviewshown', post ); deck.on( 'overviewshown', post );
deck.on( 'paused', post ); deck.on( 'paused', post );
deck.on( 'resumed', post ); deck.on( 'resumed', post );
deck.on( 'showmediapreview', post ); deck.on( 'previewiframe', post );
deck.on( 'showiframepreview', post ); deck.on( 'previewimage', post );
deck.on( 'previewvideo', post );
deck.on( 'closeoverlay', post ); deck.on( 'closeoverlay', post );
// Post the initial state // Post the initial state
+3 -2
View File
@@ -420,8 +420,9 @@
'fragmenthidden', 'fragmenthidden',
'paused', 'paused',
'resumed', 'resumed',
'showiframepreview', 'previewiframe',
'showmediapreview', 'previewimage',
'previewvideo',
'closeoverlay' 'closeoverlay'
]; ];