123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- 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 );
- }
- }
|