polyfill element.closest for ie11
This commit is contained in:
parent
e6244a57b5
commit
b7487b8b4f
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…
Reference in New Issue
Block a user