add focus controller, manages keyboard focus across multiple embedded decks
parent
57107ebe4c
commit
664beff715
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -57,6 +57,15 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.reveal {
|
||||||
|
border: 4px solid #ccc;
|
||||||
|
}
|
||||||
|
.reveal.focused {
|
||||||
|
border-color: #94b5ff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script src="../dist/reveal.js"></script>
|
<script src="../dist/reveal.js"></script>
|
||||||
<script src="../dist/plugin/highlight.js"></script>
|
<script src="../dist/plugin/highlight.js"></script>
|
||||||
<script src="../dist/plugin/markdown.js"></script>
|
<script src="../dist/plugin/markdown.js"></script>
|
||||||
|
@ -65,7 +74,8 @@
|
||||||
|
|
||||||
let deck1 = new Reveal( document.querySelector( '.deck1' ), {
|
let deck1 = new Reveal( document.querySelector( '.deck1' ), {
|
||||||
embedded: true,
|
embedded: true,
|
||||||
keyboard: false,
|
progress: false,
|
||||||
|
keyboardCondition: 'focused',
|
||||||
plugins: [ RevealHighlight ]
|
plugins: [ RevealHighlight ]
|
||||||
} );
|
} );
|
||||||
deck1.on( 'slidechanged', () => {
|
deck1.on( 'slidechanged', () => {
|
||||||
|
@ -75,7 +85,8 @@
|
||||||
|
|
||||||
let deck2 = new Reveal( document.querySelector( '.deck2' ), {
|
let deck2 = new Reveal( document.querySelector( '.deck2' ), {
|
||||||
embedded: true,
|
embedded: true,
|
||||||
keyboard: true,
|
progress: false,
|
||||||
|
keyboardCondition: 'focused',
|
||||||
plugins: [ RevealMarkdown, RevealMath ]
|
plugins: [ RevealMarkdown, RevealMath ]
|
||||||
} );
|
} );
|
||||||
deck2.initialize().then( () => {
|
deck2.initialize().then( () => {
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
/**
|
||||||
|
* Manages focus when a presentation is embedded. This
|
||||||
|
* helps us only capture keyboard from the presentation
|
||||||
|
* a user is currently interacting with in a page where
|
||||||
|
* multiple presentations are embedded.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const STATE_FOCUS = 'focus';
|
||||||
|
const STATE_BLUR = 'blur';
|
||||||
|
|
||||||
|
export default class Focus {
|
||||||
|
|
||||||
|
constructor( Reveal ) {
|
||||||
|
|
||||||
|
this.Reveal = Reveal;
|
||||||
|
|
||||||
|
this.onRevealPointerDown = this.onRevealPointerDown.bind( this );
|
||||||
|
this.onDocumentPointerDown = this.onDocumentPointerDown.bind( this );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the reveal.js config is updated.
|
||||||
|
*/
|
||||||
|
configure( config, oldConfig ) {
|
||||||
|
|
||||||
|
if( config.embedded ) {
|
||||||
|
this.blur();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.focus();
|
||||||
|
this.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bind() {
|
||||||
|
|
||||||
|
if( this.Reveal.getConfig().embedded ) {
|
||||||
|
this.Reveal.getRevealElement().addEventListener( 'pointerdown', this.onRevealPointerDown, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
unbind() {
|
||||||
|
|
||||||
|
this.Reveal.getRevealElement().removeEventListener( 'pointerdown', this.onRevealPointerDown, false );
|
||||||
|
document.removeEventListener( 'pointerdown', this.onDocumentPointerDown, false );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
|
||||||
|
if( this.state !== STATE_FOCUS ) {
|
||||||
|
this.Reveal.getRevealElement().classList.add( 'focused' );
|
||||||
|
document.addEventListener( 'pointerdown', this.onDocumentPointerDown, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = STATE_FOCUS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
blur() {
|
||||||
|
|
||||||
|
if( this.state !== STATE_BLUR ) {
|
||||||
|
this.Reveal.getRevealElement().classList.remove( 'focused' );
|
||||||
|
document.removeEventListener( 'pointerdown', this.onDocumentPointerDown, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = STATE_BLUR;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
isFocused() {
|
||||||
|
|
||||||
|
return this.state === STATE_FOCUS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onRevealPointerDown( event ) {
|
||||||
|
|
||||||
|
this.focus();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onDocumentPointerDown( event ) {
|
||||||
|
|
||||||
|
let revealElement = event.target.closest( '.reveal' );
|
||||||
|
if( !revealElement || revealElement !== this.Reveal.getRevealElement() ) {
|
||||||
|
this.blur();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -151,6 +151,12 @@ export default class Keyboard {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If keyboardCondition is set, only capture keyboard events
|
||||||
|
// for embedded decks when they are focused
|
||||||
|
if( config.keyboardCondition === 'focused' && !this.Reveal.isFocused() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Shorthand
|
// Shorthand
|
||||||
let keyCode = event.keyCode;
|
let keyCode = event.keyCode;
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import Pointer from './controllers/pointer.js'
|
||||||
import Plugins from './controllers/plugins.js'
|
import Plugins from './controllers/plugins.js'
|
||||||
import Print from './controllers/print.js'
|
import Print from './controllers/print.js'
|
||||||
import Touch from './controllers/touch.js'
|
import Touch from './controllers/touch.js'
|
||||||
|
import Focus from './controllers/focus.js'
|
||||||
import Notes from './controllers/notes.js'
|
import Notes from './controllers/notes.js'
|
||||||
import Playback from './components/playback.js'
|
import Playback from './components/playback.js'
|
||||||
import defaultConfig from './config.js'
|
import defaultConfig from './config.js'
|
||||||
|
@ -111,6 +112,7 @@ export default function( revealElement, options ) {
|
||||||
pointer = new Pointer( Reveal ),
|
pointer = new Pointer( Reveal ),
|
||||||
plugins = new Plugins( Reveal ),
|
plugins = new Plugins( Reveal ),
|
||||||
print = new Print( Reveal ),
|
print = new Print( Reveal ),
|
||||||
|
focus = new Focus( Reveal ),
|
||||||
touch = new Touch( Reveal ),
|
touch = new Touch( Reveal ),
|
||||||
notes = new Notes( Reveal );
|
notes = new Notes( Reveal );
|
||||||
|
|
||||||
|
@ -464,6 +466,7 @@ export default function( revealElement, options ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
notes.configure( config, oldConfig );
|
notes.configure( config, oldConfig );
|
||||||
|
focus.configure( config, oldConfig );
|
||||||
pointer.configure( config, oldConfig );
|
pointer.configure( config, oldConfig );
|
||||||
controls.configure( config, oldConfig );
|
controls.configure( config, oldConfig );
|
||||||
progress.configure( config, oldConfig );
|
progress.configure( config, oldConfig );
|
||||||
|
@ -489,6 +492,7 @@ export default function( revealElement, options ) {
|
||||||
if( config.progress ) progress.bind();
|
if( config.progress ) progress.bind();
|
||||||
if( config.respondToHashChanges ) location.bind();
|
if( config.respondToHashChanges ) location.bind();
|
||||||
controls.bind();
|
controls.bind();
|
||||||
|
focus.bind();
|
||||||
|
|
||||||
dom.slides.addEventListener( 'transitionend', onTransitionEnd, false );
|
dom.slides.addEventListener( 'transitionend', onTransitionEnd, false );
|
||||||
dom.pauseOverlay.addEventListener( 'click', resume, false );
|
dom.pauseOverlay.addEventListener( 'click', resume, false );
|
||||||
|
@ -507,6 +511,7 @@ export default function( revealElement, options ) {
|
||||||
eventsAreBound = false;
|
eventsAreBound = false;
|
||||||
|
|
||||||
touch.unbind();
|
touch.unbind();
|
||||||
|
focus.unbind();
|
||||||
keyboard.unbind();
|
keyboard.unbind();
|
||||||
controls.unbind();
|
controls.unbind();
|
||||||
progress.unbind();
|
progress.unbind();
|
||||||
|
@ -2438,6 +2443,7 @@ export default function( revealElement, options ) {
|
||||||
isAutoSliding,
|
isAutoSliding,
|
||||||
isSpeakerNotes: notes.isSpeakerNotesWindow.bind( notes ),
|
isSpeakerNotes: notes.isSpeakerNotesWindow.bind( notes ),
|
||||||
isOverview: overview.isActive.bind( overview ),
|
isOverview: overview.isActive.bind( overview ),
|
||||||
|
isFocused: focus.isFocused.bind( focus ),
|
||||||
isPrintingPDF: print.isPrintingPDF.bind( print ),
|
isPrintingPDF: print.isPrintingPDF.bind( print ),
|
||||||
|
|
||||||
// Checks if reveal.js has been loaded and is ready for use
|
// Checks if reveal.js has been loaded and is ready for use
|
||||||
|
@ -2548,6 +2554,7 @@ export default function( revealElement, options ) {
|
||||||
|
|
||||||
// Controllers
|
// Controllers
|
||||||
print,
|
print,
|
||||||
|
focus,
|
||||||
progress,
|
progress,
|
||||||
controls,
|
controls,
|
||||||
location,
|
location,
|
||||||
|
|
Loading…
Reference in New Issue