No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 

170 líneas
3.2 KiB

  1. /**
  2. * Makes it possible to jump to a slide by entering its
  3. * slide number or id.
  4. */
  5. export default class JumpToSlide {
  6. constructor( Reveal ) {
  7. this.Reveal = Reveal;
  8. this.onInput = this.onInput.bind( this );
  9. this.onBlur = this.onBlur.bind( this );
  10. this.onKeyDown = this.onKeyDown.bind( this );
  11. }
  12. render() {
  13. this.element = document.createElement( 'div' );
  14. this.element.className = 'jump-to-slide';
  15. this.jumpInput = document.createElement( 'input' );
  16. this.jumpInput.type = 'text';
  17. this.jumpInput.className = 'jump-to-slide-input';
  18. this.jumpInput.placeholder = 'Jump to slide';
  19. this.jumpInput.addEventListener( 'input', this.onInput );
  20. this.jumpInput.addEventListener( 'keydown', this.onKeyDown );
  21. this.jumpInput.addEventListener( 'blur', this.onBlur );
  22. this.element.appendChild( this.jumpInput );
  23. }
  24. show() {
  25. this.indicesOnShow = this.Reveal.getIndices();
  26. this.Reveal.getRevealElement().appendChild( this.element );
  27. this.jumpInput.focus();
  28. }
  29. hide() {
  30. if( this.isVisible() ) {
  31. this.element.remove();
  32. this.jumpInput.value = '';
  33. clearTimeout( this.jumpTimeout );
  34. delete this.jumpTimeout;
  35. }
  36. }
  37. isVisible() {
  38. return !!this.element.parentNode;
  39. }
  40. /**
  41. * Parses the current input and jumps to the given slide.
  42. */
  43. jump() {
  44. clearTimeout( this.jumpTimeout );
  45. delete this.jumpTimeout;
  46. const query = this.jumpInput.value.trim( '' );
  47. let indices = this.Reveal.location.getIndicesFromHash( query, { oneBasedIndex: true } );
  48. // If no valid index was found and the input query is a
  49. // string, fall back on a simple search
  50. if( !indices && /\S+/i.test( query ) && query.length > 1 ) {
  51. indices = this.search( query );
  52. }
  53. if( indices && query !== '' ) {
  54. this.Reveal.slide( indices.h, indices.v, indices.f );
  55. return true;
  56. }
  57. else {
  58. this.Reveal.slide( this.indicesOnShow.h, this.indicesOnShow.v, this.indicesOnShow.f );
  59. return false;
  60. }
  61. }
  62. jumpAfter( delay ) {
  63. clearTimeout( this.jumpTimeout );
  64. this.jumpTimeout = setTimeout( () => this.jump(), delay );
  65. }
  66. /**
  67. * A lofi search that looks for the given query in all
  68. * of our slides and returns the first match.
  69. */
  70. search( query ) {
  71. const regex = new RegExp( '\\b' + query.trim() + '\\b', 'i' );
  72. const slide = this.Reveal.getSlides().find( ( slide ) => {
  73. return regex.test( slide.innerText );
  74. } );
  75. if( slide ) {
  76. return this.Reveal.getIndices( slide );
  77. }
  78. else {
  79. return null;
  80. }
  81. }
  82. /**
  83. * Reverts back to the slide we were on when jump to slide was
  84. * invoked.
  85. */
  86. cancel() {
  87. this.Reveal.slide( this.indicesOnShow.h, this.indicesOnShow.v, this.indicesOnShow.f );
  88. this.hide();
  89. }
  90. confirm() {
  91. this.jump();
  92. this.hide();
  93. }
  94. destroy() {
  95. this.jumpInput.removeEventListener( 'input', this.onInput );
  96. this.jumpInput.removeEventListener( 'keydown', this.onKeyDown );
  97. this.jumpInput.removeEventListener( 'blur', this.onBlur );
  98. this.element.remove();
  99. }
  100. onKeyDown( event ) {
  101. if( event.keyCode === 13 ) {
  102. this.confirm();
  103. }
  104. else if( event.keyCode === 27 ) {
  105. this.cancel();
  106. event.stopImmediatePropagation();
  107. }
  108. }
  109. onInput( event ) {
  110. this.jumpAfter( 200 );
  111. }
  112. onBlur() {
  113. setTimeout( () => this.hide(), 1 );
  114. }
  115. }