polyfill element.closest for ie11
This commit is contained in:
		
							parent
							
								
									e6244a57b5
								
							
						
					
					
						commit
						b7487b8b4f
					
				
					 10 changed files with 45 additions and 34 deletions
				
			
		
							
								
								
									
										2
									
								
								dist/reveal.esm.js
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/reveal.esm.js
									
										
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/reveal.js
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/reveal.js
									
										
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -36,6 +36,18 @@ | ||||||
| 					<audio src="assets/beeping.wav" data-autoplay></audio> | 					<audio src="assets/beeping.wav" data-autoplay></audio> | ||||||
| 				</section> | 				</section> | ||||||
| 
 | 
 | ||||||
|  | 				<section> | ||||||
|  | 					<h2>Audio inside slide fragments</h2> | ||||||
|  | 					<div class="fragment"> | ||||||
|  | 						Beep 1 | ||||||
|  | 						<audio src="assets/beeping.wav" data-autoplay></audio> | ||||||
|  | 					</div> | ||||||
|  | 					<div class="fragment"> | ||||||
|  | 						Beep 2 | ||||||
|  | 						<audio src="assets/beeping.wav" data-autoplay></audio> | ||||||
|  | 					</div> | ||||||
|  | 				</section> | ||||||
|  | 
 | ||||||
| 				<section> | 				<section> | ||||||
| 					<h2>Audio with controls</h2> | 					<h2>Audio with controls</h2> | ||||||
| 					<audio src="assets/beeping.wav" controls></audio> | 					<audio src="assets/beeping.wav" controls></audio> | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { queryAll, extend, createStyleSheet, matchesSelector } from '../utils/util.js' | import { queryAll, extend, createStyleSheet, matches, closest } from '../utils/util.js' | ||||||
| import { FRAGMENT_STYLE_REGEX } from '../utils/constants.js' | import { FRAGMENT_STYLE_REGEX } from '../utils/constants.js' | ||||||
| 
 | 
 | ||||||
| // Counter used to generate unique IDs for auto-animated elements
 | // Counter used to generate unique IDs for auto-animated elements
 | ||||||
|  | @ -299,8 +299,8 @@ export default class AutoAnimate { | ||||||
| 		options = extend( options, inheritedOptions ); | 		options = extend( options, inheritedOptions ); | ||||||
| 
 | 
 | ||||||
| 		// Inherit options from parent elements
 | 		// Inherit options from parent elements
 | ||||||
| 		if( element.closest && element.parentNode ) { | 		if( element.parentNode ) { | ||||||
| 			let autoAnimatedParent = element.parentNode.closest( '[data-auto-animate-target]' ); | 			let autoAnimatedParent = closest( element.parentNode, '[data-auto-animate-target]' ); | ||||||
| 			if( autoAnimatedParent ) { | 			if( autoAnimatedParent ) { | ||||||
| 				options = this.getAutoAnimateOptions( autoAnimatedParent, options ); | 				options = this.getAutoAnimateOptions( autoAnimatedParent, options ); | ||||||
| 			} | 			} | ||||||
|  | @ -463,11 +463,11 @@ export default class AutoAnimate { | ||||||
| 
 | 
 | ||||||
| 			// Disable scale transformations on text nodes, we transiition
 | 			// Disable scale transformations on text nodes, we transiition
 | ||||||
| 			// each individual text property instead
 | 			// each individual text property instead
 | ||||||
| 			if( matchesSelector( pair.from, textNodes ) ) { | 			if( matches( pair.from, textNodes ) ) { | ||||||
| 				pair.options = { scale: false }; | 				pair.options = { scale: false }; | ||||||
| 			} | 			} | ||||||
| 			// Animate individual lines of code
 | 			// Animate individual lines of code
 | ||||||
| 			else if( matchesSelector( pair.from, codeNodes ) ) { | 			else if( matches( pair.from, codeNodes ) ) { | ||||||
| 
 | 
 | ||||||
| 				// Transition the code block's width and height instead of scaling
 | 				// Transition the code block's width and height instead of scaling
 | ||||||
| 				// to prevent its content from being squished
 | 				// to prevent its content from being squished
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,5 @@ | ||||||
|  | import { closest } from '../utils/util.js' | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Manages focus when a presentation is embedded. This |  * Manages focus when a presentation is embedded. This | ||||||
|  * helps us only capture keyboard from the presentation |  * helps us only capture keyboard from the presentation | ||||||
|  | @ -85,7 +87,7 @@ export default class Focus { | ||||||
| 
 | 
 | ||||||
| 	onDocumentPointerDown( event ) { | 	onDocumentPointerDown( event ) { | ||||||
| 
 | 
 | ||||||
| 		let revealElement = event.target.closest( '.reveal' ); | 		let revealElement = closest( event.target, '.reveal' ); | ||||||
| 		if( !revealElement || revealElement !== this.Reveal.getRevealElement() ) { | 		if( !revealElement || revealElement !== this.Reveal.getRevealElement() ) { | ||||||
| 			this.blur(); | 			this.blur(); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import { HORIZONTAL_SLIDES_SELECTOR, VERTICAL_SLIDES_SELECTOR } from '../utils/constants.js' | import { HORIZONTAL_SLIDES_SELECTOR, VERTICAL_SLIDES_SELECTOR } from '../utils/constants.js' | ||||||
| import { extend, queryAll, closestParent } from '../utils/util.js' | import { extend, queryAll, closest } from '../utils/util.js' | ||||||
| import { isMobile } from '../utils/device.js' | import { isMobile } from '../utils/device.js' | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | @ -240,7 +240,7 @@ export default class SlideContent { | ||||||
| 
 | 
 | ||||||
| 			// HTML5 media elements
 | 			// HTML5 media elements
 | ||||||
| 			queryAll( element, 'video, audio' ).forEach( el => { | 			queryAll( element, 'video, audio' ).forEach( el => { | ||||||
| 				if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { | 				if( closest( el, '.fragment' ) && !closest( el, '.fragment.visible' ) ) { | ||||||
| 					return; | 					return; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  | @ -250,7 +250,7 @@ export default class SlideContent { | ||||||
| 				// If no global setting is available, fall back on the element's
 | 				// If no global setting is available, fall back on the element's
 | ||||||
| 				// own autoplay setting
 | 				// own autoplay setting
 | ||||||
| 				if( typeof autoplay !== 'boolean' ) { | 				if( typeof autoplay !== 'boolean' ) { | ||||||
| 					autoplay = el.hasAttribute( 'data-autoplay' ) || !!closestParent( el, '.slide-background' ); | 					autoplay = el.hasAttribute( 'data-autoplay' ) || !!closest( el, '.slide-background' ); | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				if( autoplay && typeof el.play === 'function' ) { | 				if( autoplay && typeof el.play === 'function' ) { | ||||||
|  | @ -288,7 +288,7 @@ export default class SlideContent { | ||||||
| 
 | 
 | ||||||
| 			// Normal iframes
 | 			// Normal iframes
 | ||||||
| 			queryAll( element, 'iframe[src]' ).forEach( el => { | 			queryAll( element, 'iframe[src]' ).forEach( el => { | ||||||
| 				if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { | 				if( closest( el, '.fragment' ) && !closest( el, '.fragment.visible' ) ) { | ||||||
| 					return; | 					return; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  | @ -297,7 +297,7 @@ export default class SlideContent { | ||||||
| 
 | 
 | ||||||
| 			// Lazy loading iframes
 | 			// Lazy loading iframes
 | ||||||
| 			queryAll( element, 'iframe[data-src]' ).forEach( el => { | 			queryAll( element, 'iframe[data-src]' ).forEach( el => { | ||||||
| 				if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { | 				if( closest( el, '.fragment' ) && !closest( el, '.fragment.visible' ) ) { | ||||||
| 					return; | 					return; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  | @ -320,8 +320,8 @@ export default class SlideContent { | ||||||
| 	 */ | 	 */ | ||||||
| 	startEmbeddedMedia( event ) { | 	startEmbeddedMedia( event ) { | ||||||
| 
 | 
 | ||||||
| 		let isAttachedToDOM = !!closestParent( event.target, 'html' ), | 		let isAttachedToDOM = !!closest( event.target, 'html' ), | ||||||
| 			isVisible  		= !!closestParent( event.target, '.present' ); | 			isVisible  		= !!closest( event.target, '.present' ); | ||||||
| 
 | 
 | ||||||
| 		if( isAttachedToDOM && isVisible ) { | 		if( isAttachedToDOM && isVisible ) { | ||||||
| 			event.target.currentTime = 0; | 			event.target.currentTime = 0; | ||||||
|  | @ -344,8 +344,8 @@ export default class SlideContent { | ||||||
| 
 | 
 | ||||||
| 		if( iframe && iframe.contentWindow ) { | 		if( iframe && iframe.contentWindow ) { | ||||||
| 
 | 
 | ||||||
| 			let isAttachedToDOM = !!closestParent( event.target, 'html' ), | 			let isAttachedToDOM = !!closest( event.target, 'html' ), | ||||||
| 				isVisible  		= !!closestParent( event.target, '.present' ); | 				isVisible  		= !!closest( event.target, '.present' ); | ||||||
| 
 | 
 | ||||||
| 			if( isAttachedToDOM && isVisible ) { | 			if( isAttachedToDOM && isVisible ) { | ||||||
| 
 | 
 | ||||||
|  | @ -355,7 +355,7 @@ export default class SlideContent { | ||||||
| 				// If no global setting is available, fall back on the element's
 | 				// If no global setting is available, fall back on the element's
 | ||||||
| 				// own autoplay setting
 | 				// own autoplay setting
 | ||||||
| 				if( typeof autoplay !== 'boolean' ) { | 				if( typeof autoplay !== 'boolean' ) { | ||||||
| 					autoplay = iframe.hasAttribute( 'data-autoplay' ) || !!closestParent( iframe, '.slide-background' ); | 					autoplay = iframe.hasAttribute( 'data-autoplay' ) || !!closest( iframe, '.slide-background' ); | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				// YouTube postMessage API
 | 				// YouTube postMessage API
 | ||||||
|  |  | ||||||
|  | @ -148,7 +148,7 @@ export default function( revealElement, options ) { | ||||||
| 
 | 
 | ||||||
| 		// Embedded decks use the reveal element as their viewport
 | 		// Embedded decks use the reveal element as their viewport
 | ||||||
| 		if( config.embedded === true ) { | 		if( config.embedded === true ) { | ||||||
| 			dom.viewport = revealElement.closest( '.reveal-viewport' ) || revealElement; | 			dom.viewport = Util.closest( revealElement, '.reveal-viewport' ) || revealElement; | ||||||
| 		} | 		} | ||||||
| 		// Full-page decks use the body as their viewport
 | 		// Full-page decks use the body as their viewport
 | ||||||
| 		else { | 		else { | ||||||
|  |  | ||||||
|  | @ -94,14 +94,10 @@ export const transformElement = ( element, transform ) => { | ||||||
|  * |  * | ||||||
|  * @return {Boolean} |  * @return {Boolean} | ||||||
|  */ |  */ | ||||||
| export const matchesSelector = ( target, selector ) => { | export const matches = ( target, selector ) => { | ||||||
| 
 | 
 | ||||||
| 	// There's some overhead doing this each time, we don't
 | 	let matchesMethod = target.matches || target.matchesSelector || target.msMatchesSelector; | ||||||
| 	// want to rewrite the element prototype but should still
 |  | ||||||
| 	// be enough to feature detect once at startup...
 |  | ||||||
| 	let matchesMethod = parent.matches || parent.matchesSelector || parent.msMatchesSelector; |  | ||||||
| 
 | 
 | ||||||
| 	// If we find a match, we're all set
 |  | ||||||
| 	return !!( matchesMethod && matchesMethod.call( target, selector ) ); | 	return !!( matchesMethod && matchesMethod.call( target, selector ) ); | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | @ -117,20 +113,21 @@ export const matchesSelector = ( target, selector ) => { | ||||||
|  * @return {HTMLElement} The matched parent or null |  * @return {HTMLElement} The matched parent or null | ||||||
|  * if no matching parent was found |  * if no matching parent was found | ||||||
|  */ |  */ | ||||||
| export const closestParent = ( target, selector ) => { | export const closest = ( target, selector ) => { | ||||||
| 
 | 
 | ||||||
| 	let parent = target.parentNode; | 	// Native Element.closest
 | ||||||
|  | 	if( typeof target.closest === 'function' ) { | ||||||
|  | 		return target.closest( selector ); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	while( parent ) { | 	// Polyfill
 | ||||||
| 
 | 	while( target ) { | ||||||
| 		// If we find a match, we're all set
 | 		if( matches( target, selector ) ) { | ||||||
| 		if( matchesSelector( parent, selector ) ) { | 			return target; | ||||||
| 			return parent; |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// Keep searching
 | 		// Keep searching
 | ||||||
| 		parent = parent.parentNode; | 		target = target.parentNode; | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return null; | 	return null; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue