add focus controller, manages keyboard focus across multiple embedded decks
This commit is contained in:
parent
57107ebe4c
commit
664beff715
6 changed files with 125 additions and 6 deletions
4
dist/reveal.esm.js
vendored
4
dist/reveal.esm.js
vendored
File diff suppressed because one or more lines are too long
4
dist/reveal.js
vendored
4
dist/reveal.js
vendored
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( () => {
|
||||||
|
|
95
js/controllers/focus.js
Normal file
95
js/controllers/focus.js
Normal file
|
@ -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 a new issue