Преглед изворни кода

add focus controller, manages keyboard focus across multiple embedded decks

Hakim El Hattab пре 5 година
родитељ
комит
664beff715
6 измењених фајлова са 123 додато и 4 уклоњено
  1. 1 1
      dist/reveal.esm.js
  2. 1 1
      dist/reveal.js
  3. 13 2
      examples/multiple-presentations.html
  4. 95 0
      js/controllers/focus.js
  5. 6 0
      js/controllers/keyboard.js
  6. 7 0
      js/reveal.js

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/reveal.esm.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/reveal.js


+ 13 - 2
examples/multiple-presentations.html

@@ -57,6 +57,15 @@
 			</div>
 		</div>
 
+		<style>
+			.reveal {
+				border: 4px solid #ccc;
+			}
+			.reveal.focused {
+				border-color: #94b5ff;
+			}
+		</style>
+
 		<script src="../dist/reveal.js"></script>
 		<script src="../dist/plugin/highlight.js"></script>
 		<script src="../dist/plugin/markdown.js"></script>
@@ -65,7 +74,8 @@
 
 			let deck1 = new Reveal( document.querySelector( '.deck1' ), {
 				embedded: true,
-				keyboard: false,
+				progress: false,
+				keyboardCondition: 'focused',
 				plugins: [ RevealHighlight ]
 			} );
 			deck1.on( 'slidechanged', () => {
@@ -75,7 +85,8 @@
 
 			let deck2 = new Reveal( document.querySelector( '.deck2' ), {
 				embedded: true,
-				keyboard: true,
+				progress: false,
+				keyboardCondition: 'focused',
 				plugins: [ RevealMarkdown, RevealMath ]
 			} );
 			deck2.initialize().then( () => {

+ 95 - 0
js/controllers/focus.js

@@ -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();
+		}
+
+	}
+
+}

+ 6 - 0
js/controllers/keyboard.js

@@ -151,6 +151,12 @@ export default class Keyboard {
 			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
 		let keyCode = event.keyCode;
 

+ 7 - 0
js/reveal.js

@@ -12,6 +12,7 @@ import Pointer from './controllers/pointer.js'
 import Plugins from './controllers/plugins.js'
 import Print from './controllers/print.js'
 import Touch from './controllers/touch.js'
+import Focus from './controllers/focus.js'
 import Notes from './controllers/notes.js'
 import Playback from './components/playback.js'
 import defaultConfig from './config.js'
@@ -111,6 +112,7 @@ export default function( revealElement, options ) {
 		pointer = new Pointer( Reveal ),
 		plugins = new Plugins( Reveal ),
 		print = new Print( Reveal ),
+		focus = new Focus( Reveal ),
 		touch = new Touch( Reveal ),
 		notes = new Notes( Reveal );
 
@@ -464,6 +466,7 @@ export default function( revealElement, options ) {
 		}
 
 		notes.configure( config, oldConfig );
+		focus.configure( config, oldConfig );
 		pointer.configure( config, oldConfig );
 		controls.configure( config, oldConfig );
 		progress.configure( config, oldConfig );
@@ -489,6 +492,7 @@ export default function( revealElement, options ) {
 		if( config.progress ) progress.bind();
 		if( config.respondToHashChanges ) location.bind();
 		controls.bind();
+		focus.bind();
 
 		dom.slides.addEventListener( 'transitionend', onTransitionEnd, false );
 		dom.pauseOverlay.addEventListener( 'click', resume, false );
@@ -507,6 +511,7 @@ export default function( revealElement, options ) {
 		eventsAreBound = false;
 
 		touch.unbind();
+		focus.unbind();
 		keyboard.unbind();
 		controls.unbind();
 		progress.unbind();
@@ -2438,6 +2443,7 @@ export default function( revealElement, options ) {
 		isAutoSliding,
 		isSpeakerNotes: notes.isSpeakerNotesWindow.bind( notes ),
 		isOverview: overview.isActive.bind( overview ),
+		isFocused: focus.isFocused.bind( focus ),
 		isPrintingPDF: print.isPrintingPDF.bind( print ),
 
 		// Checks if reveal.js has been loaded and is ready for use
@@ -2548,6 +2554,7 @@ export default function( revealElement, options ) {
 
 		// Controllers
 		print,
+		focus,
 		progress,
 		controls,
 		location,

Неке датотеке нису приказане због велике количине промена