mirror of
				https://github.com/hakimel/reveal.js.git
				synced 2025-10-26 11:46:32 +01:00 
			
		
		
		
	=== Do not change lines below ===
{
 "chain": [],
 "cmd": "codespell -w",
 "exit": 0,
 "extra_inputs": [],
 "inputs": [],
 "outputs": [],
 "pwd": "."
}
^^^ Do not change lines above ^^^
		
	
		
			
				
	
	
		
			197 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			197 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import {
 | |
| 	SLIDE_NUMBER_FORMAT_CURRENT,
 | |
| 	SLIDE_NUMBER_FORMAT_CURRENT_SLASH_TOTAL
 | |
| } from "../utils/constants";
 | |
| 
 | |
| /**
 | |
|  * Makes it possible to jump to a slide by entering its
 | |
|  * slide number or id.
 | |
|  */
 | |
| export default class JumpToSlide {
 | |
| 
 | |
| 	constructor( Reveal ) {
 | |
| 
 | |
| 		this.Reveal = Reveal;
 | |
| 
 | |
| 		this.onInput = this.onInput.bind( this );
 | |
| 		this.onBlur = this.onBlur.bind( this );
 | |
| 		this.onKeyDown = this.onKeyDown.bind( this );
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	render() {
 | |
| 
 | |
| 		this.element = document.createElement( 'div' );
 | |
| 		this.element.className = 'jump-to-slide';
 | |
| 
 | |
|     this.jumpInput = document.createElement( 'input' );
 | |
|     this.jumpInput.type = 'text';
 | |
|     this.jumpInput.className = 'jump-to-slide-input';
 | |
|     this.jumpInput.placeholder = 'Jump to slide';
 | |
| 		this.jumpInput.addEventListener( 'input', this.onInput );
 | |
| 		this.jumpInput.addEventListener( 'keydown', this.onKeyDown );
 | |
| 		this.jumpInput.addEventListener( 'blur', this.onBlur );
 | |
| 
 | |
|     this.element.appendChild( this.jumpInput );
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	show() {
 | |
| 
 | |
| 		this.indicesOnShow = this.Reveal.getIndices();
 | |
| 
 | |
| 		this.Reveal.getRevealElement().appendChild( this.element );
 | |
| 		this.jumpInput.focus();
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	hide() {
 | |
| 
 | |
| 		if( this.isVisible() ) {
 | |
| 			this.element.remove();
 | |
| 			this.jumpInput.value = '';
 | |
| 
 | |
| 			clearTimeout( this.jumpTimeout );
 | |
| 			delete this.jumpTimeout;
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	isVisible() {
 | |
| 
 | |
| 		return !!this.element.parentNode;
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Parses the current input and jumps to the given slide.
 | |
| 	 */
 | |
| 	jump() {
 | |
| 
 | |
| 		clearTimeout( this.jumpTimeout );
 | |
| 		delete this.jumpTimeout;
 | |
| 
 | |
| 		let query = this.jumpInput.value.trim( '' );
 | |
| 		let indices;
 | |
| 
 | |
| 		// When slide numbers are formatted to be a single linear number
 | |
| 		// (instead of showing a separate horizontal/vertical index) we
 | |
| 		// use the same format for slide jumps
 | |
| 		if( /^\d+$/.test( query ) ) {
 | |
| 			const slideNumberFormat = this.Reveal.getConfig().slideNumber;
 | |
| 			if( slideNumberFormat === SLIDE_NUMBER_FORMAT_CURRENT || slideNumberFormat === SLIDE_NUMBER_FORMAT_CURRENT_SLASH_TOTAL ) {
 | |
| 				const slide = this.Reveal.getSlides()[ parseInt( query, 10 ) - 1 ];
 | |
| 				if( slide ) {
 | |
| 					indices = this.Reveal.getIndices( slide );
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if( !indices ) {
 | |
| 			// If the query uses "horizontal.vertical" format, convert to
 | |
| 			// "horizontal/vertical" so that our URL parser can understand
 | |
| 			if( /^\d+\.\d+$/.test( query ) ) {
 | |
| 				query = query.replace( '.', '/' );
 | |
| 			}
 | |
| 
 | |
| 			indices = this.Reveal.location.getIndicesFromHash( query, { oneBasedIndex: true } );
 | |
| 		}
 | |
| 
 | |
| 		// Still no valid index? Fall back on a text search
 | |
| 		if( !indices && /\S+/i.test( query ) && query.length > 1 ) {
 | |
| 			indices = this.search( query );
 | |
| 		}
 | |
| 
 | |
| 		if( indices && query !== '' ) {
 | |
| 			this.Reveal.slide( indices.h, indices.v, indices.f );
 | |
| 			return true;
 | |
| 		}
 | |
| 		else {
 | |
| 			this.Reveal.slide( this.indicesOnShow.h, this.indicesOnShow.v, this.indicesOnShow.f );
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	jumpAfter( delay ) {
 | |
| 
 | |
| 		clearTimeout( this.jumpTimeout );
 | |
| 		this.jumpTimeout = setTimeout( () => this.jump(), delay );
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * A lofi search that looks for the given query in all
 | |
| 	 * of our slides and returns the first match.
 | |
| 	 */
 | |
| 	search( query ) {
 | |
| 
 | |
| 		const regex = new RegExp( '\\b' + query.trim() + '\\b', 'i' );
 | |
| 
 | |
| 		const slide = this.Reveal.getSlides().find( ( slide ) => {
 | |
| 			return regex.test( slide.innerText );
 | |
| 		} );
 | |
| 
 | |
| 		if( slide ) {
 | |
| 			return this.Reveal.getIndices( slide );
 | |
| 		}
 | |
| 		else {
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Reverts back to the slide we were on when jump to slide was
 | |
| 	 * invoked.
 | |
| 	 */
 | |
| 	cancel() {
 | |
| 
 | |
| 		this.Reveal.slide( this.indicesOnShow.h, this.indicesOnShow.v, this.indicesOnShow.f );
 | |
| 		this.hide();
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	confirm() {
 | |
| 
 | |
| 		this.jump();
 | |
| 		this.hide();
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	destroy() {
 | |
| 
 | |
| 		this.jumpInput.removeEventListener( 'input', this.onInput );
 | |
| 		this.jumpInput.removeEventListener( 'keydown', this.onKeyDown );
 | |
| 		this.jumpInput.removeEventListener( 'blur', this.onBlur );
 | |
| 
 | |
| 		this.element.remove();
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	onKeyDown( event ) {
 | |
| 
 | |
| 		if( event.keyCode === 13 ) {
 | |
| 			this.confirm();
 | |
| 		}
 | |
| 		else if( event.keyCode === 27 ) {
 | |
| 			this.cancel();
 | |
| 
 | |
| 			event.stopImmediatePropagation();
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	onInput( event ) {
 | |
| 
 | |
| 		this.jumpAfter( 200 );
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	onBlur() {
 | |
| 
 | |
| 		setTimeout( () => this.hide(), 1 );
 | |
| 
 | |
| 	}
 | |
| 
 | |
| } |