123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- import { SLIDES_SELECTOR } from '../utils/constants.js'
- import { extend, queryAll, transformElement } from '../utils/util.js'
-
- /**
- * Handles all logic related to the overview mode
- * (birds-eye view of all slides).
- */
- export default class Overview {
-
- constructor( Reveal ) {
-
- this.Reveal = Reveal;
-
- this.active = false;
-
- this.onSlideClicked = this.onSlideClicked.bind( this );
-
- }
-
- /**
- * Displays the overview of slides (quick nav) by scaling
- * down and arranging all slide elements.
- */
- activate() {
-
- // Only proceed if enabled in config
- if( this.Reveal.getConfig().overview && !this.isActive() ) {
-
- this.active = true;
-
- this.Reveal.getRevealElement().classList.add( 'overview' );
-
- // Don't auto-slide while in overview mode
- this.Reveal.cancelAutoSlide();
-
- // Move the backgrounds element into the slide container to
- // that the same scaling is applied
- this.Reveal.getSlidesElement().appendChild( this.Reveal.getBackgroundsElement() );
-
- // Clicking on an overview slide navigates to it
- queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ).forEach( slide => {
- if( !slide.classList.contains( 'stack' ) ) {
- slide.addEventListener( 'click', this.onSlideClicked, true );
- }
- } );
-
- // Calculate slide sizes
- const margin = 70;
- const slideSize = this.Reveal.getComputedSlideSize();
- this.overviewSlideWidth = slideSize.width + margin;
- this.overviewSlideHeight = slideSize.height + margin;
-
- // Reverse in RTL mode
- if( this.Reveal.getConfig().rtl ) {
- this.overviewSlideWidth = -this.overviewSlideWidth;
- }
-
- this.Reveal.updateSlidesVisibility();
-
- this.layout();
- this.update();
-
- this.Reveal.layout();
-
- const indices = this.Reveal.getIndices();
-
- // Notify observers of the overview showing
- this.Reveal.dispatchEvent({
- type: 'overviewshown',
- data: {
- 'indexh': indices.h,
- 'indexv': indices.v,
- 'currentSlide': this.Reveal.getCurrentSlide()
- }
- });
-
- }
-
- }
-
- /**
- * Uses CSS transforms to position all slides in a grid for
- * display inside of the overview mode.
- */
- layout() {
-
- // Layout slides
- this.Reveal.getHorizontalSlides().forEach( ( hslide, h ) => {
- hslide.setAttribute( 'data-index-h', h );
- transformElement( hslide, 'translate3d(' + ( h * this.overviewSlideWidth ) + 'px, 0, 0)' );
-
- if( hslide.classList.contains( 'stack' ) ) {
-
- queryAll( hslide, 'section' ).forEach( ( vslide, v ) => {
- vslide.setAttribute( 'data-index-h', h );
- vslide.setAttribute( 'data-index-v', v );
-
- transformElement( vslide, 'translate3d(0, ' + ( v * this.overviewSlideHeight ) + 'px, 0)' );
- } );
-
- }
- } );
-
- // Layout slide backgrounds
- Array.from( this.Reveal.getBackgroundsElement().childNodes ).forEach( ( hbackground, h ) => {
- transformElement( hbackground, 'translate3d(' + ( h * this.overviewSlideWidth ) + 'px, 0, 0)' );
-
- queryAll( hbackground, '.slide-background' ).forEach( ( vbackground, v ) => {
- transformElement( vbackground, 'translate3d(0, ' + ( v * this.overviewSlideHeight ) + 'px, 0)' );
- } );
- } );
-
- }
-
- /**
- * Moves the overview viewport to the current slides.
- * Called each time the current slide changes.
- */
- update() {
-
- const vmin = Math.min( window.innerWidth, window.innerHeight );
- const scale = Math.max( vmin / 5, 150 ) / vmin;
- const indices = this.Reveal.getIndices();
-
- this.Reveal.transformSlides( {
- overview: [
- 'scale('+ scale +')',
- 'translateX('+ ( -indices.h * this.overviewSlideWidth ) +'px)',
- 'translateY('+ ( -indices.v * this.overviewSlideHeight ) +'px)'
- ].join( ' ' )
- } );
-
- }
-
- /**
- * Exits the slide overview and enters the currently
- * active slide.
- */
- deactivate() {
-
- // Only proceed if enabled in config
- if( this.Reveal.getConfig().overview ) {
-
- this.active = false;
-
- this.Reveal.getRevealElement().classList.remove( 'overview' );
-
- // Temporarily add a class so that transitions can do different things
- // depending on whether they are exiting/entering overview, or just
- // moving from slide to slide
- this.Reveal.getRevealElement().classList.add( 'overview-deactivating' );
-
- setTimeout( () => {
- this.Reveal.getRevealElement().classList.remove( 'overview-deactivating' );
- }, 1 );
-
- // Move the background element back out
- this.Reveal.getRevealElement().appendChild( this.Reveal.getBackgroundsElement() );
-
- // Clean up changes made to slides
- queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ).forEach( slide => {
- transformElement( slide, '' );
-
- slide.removeEventListener( 'click', this.onSlideClicked, true );
- } );
-
- // Clean up changes made to backgrounds
- queryAll( this.Reveal.getBackgroundsElement(), '.slide-background' ).forEach( background => {
- transformElement( background, '' );
- } );
-
- this.Reveal.transformSlides( { overview: '' } );
-
- const indices = this.Reveal.getIndices();
-
- this.Reveal.slide( indices.h, indices.v );
- this.Reveal.layout();
- this.Reveal.cueAutoSlide();
-
- // Notify observers of the overview hiding
- this.Reveal.dispatchEvent({
- type: 'overviewhidden',
- data: {
- 'indexh': indices.h,
- 'indexv': indices.v,
- 'currentSlide': this.Reveal.getCurrentSlide()
- }
- });
-
- }
- }
-
- /**
- * Toggles the slide overview mode on and off.
- *
- * @param {Boolean} [override] Flag which overrides the
- * toggle logic and forcibly sets the desired state. True means
- * overview is open, false means it's closed.
- */
- toggle( override ) {
-
- if( typeof override === 'boolean' ) {
- override ? this.activate() : this.deactivate();
- }
- else {
- this.isActive() ? this.deactivate() : this.activate();
- }
-
- }
-
- /**
- * Checks if the overview is currently active.
- *
- * @return {Boolean} true if the overview is active,
- * false otherwise
- */
- isActive() {
-
- return this.active;
-
- }
-
- /**
- * Invoked when a slide is and we're in the overview.
- *
- * @param {object} event
- */
- onSlideClicked( event ) {
-
- if( this.isActive() ) {
- event.preventDefault();
-
- let element = event.target;
-
- while( element && !element.nodeName.match( /section/gi ) ) {
- element = element.parentNode;
- }
-
- if( element && !element.classList.contains( 'disabled' ) ) {
-
- this.deactivate();
-
- if( element.nodeName.match( /section/gi ) ) {
- let h = parseInt( element.getAttribute( 'data-index-h' ), 10 ),
- v = parseInt( element.getAttribute( 'data-index-v' ), 10 );
-
- this.Reveal.slide( h, v );
- }
-
- }
- }
-
- }
-
- }
|