/** * Substep Plugin * * Copyright 2017 Henrik Ingo (@henrikingo) * Released under the MIT license. */ /* global document, window */ ( function( document, window ) { "use strict"; // Copied from core impress.js. Good candidate for moving to src/lib/util.js. var triggerEvent = function( el, eventName, detail ) { var event = document.createEvent( "CustomEvent" ); event.initCustomEvent( eventName, true, true, detail ); el.dispatchEvent( event ); }; var activeStep = null; document.addEventListener( "impress:stepenter", function( event ) { activeStep = event.target; }, false ); var substep = function( event ) { if ( ( !event ) || ( !event.target ) ) { return; } var step = event.target; var el; // Needed by jshint if ( event.detail.reason === "next" ) { el = showSubstepIfAny( step ); if ( el ) { // Send a message to others, that we aborted a stepleave event. triggerEvent( step, "impress:substep:stepleaveaborted", { reason: "next", substep: el } ); // Autoplay uses this for reloading itself triggerEvent( step, "impress:substep:enter", { reason: "next", substep: el } ); // Returning false aborts the stepleave event return false; } } if ( event.detail.reason === "prev" ) { el = hideSubstepIfAny( step ); if ( el ) { triggerEvent( step, "impress:substep:stepleaveaborted", { reason: "prev", substep: el } ); triggerEvent( step, "impress:substep:leave", { reason: "prev", substep: el } ); return false; } } }; var showSubstepIfAny = function( step ) { var substeps = step.querySelectorAll( ".substep" ); if ( substeps.length > 0 ) { var sorted = sortSubsteps( substeps ); var visible = step.querySelectorAll( ".substep-visible" ); return showSubstep( sorted, visible ); } }; var sortSubsteps = function( substepNodeList ) { var substeps = Array.from( substepNodeList ); var sorted = substeps .filter( el => el.dataset.substepOrder ) .sort( ( a, b ) => { var orderA = a.dataset.substepOrder; var orderB = b.dataset.substepOrder; return parseInt( orderA ) - parseInt( orderB ); } ) .concat( substeps.filter( el => { return el.dataset.substepOrder === undefined; } ) ); return sorted; }; var showSubstep = function( substeps, visible ) { if ( visible.length < substeps.length ) { for ( var i = 0; i < substeps.length; i++ ) { substeps[ i ].classList.remove( "substep-active" ); } // Loop over all substeps that are not yet visible and set // those of currentSubstepOrder to visible and active var el; var currentSubstepOrder; for ( var j = visible.length; j < substeps.length; j++ ) { if ( currentSubstepOrder && currentSubstepOrder !== substeps[ j ].dataset.substepOrder ) { // Stop if the substepOrder is greater break; } el = substeps[ j ]; currentSubstepOrder = el.dataset.substepOrder; el.classList.add( "substep-visible" ); el.classList.add( "substep-active" ); } return el; } }; var hideSubstepIfAny = function( step ) { var substeps = step.querySelectorAll( ".substep" ); var visible = step.querySelectorAll( ".substep-visible" ); var sorted = sortSubsteps( visible ); if ( substeps.length > 0 ) { return hideSubstep( sorted ); } }; var hideSubstep = function( visible ) { if ( visible.length > 0 ) { var current = -1; for ( var i = 0; i < visible.length; i++ ) { if ( visible[ i ].classList.contains( "substep-active" ) ) { current = i; } visible[ i ].classList.remove( "substep-active" ); } if ( current > 0 ) { visible[ current - 1 ].classList.add( "substep-active" ); } var el = visible[ visible.length - 1 ]; el.classList.remove( "substep-visible" ); // Continue if there is another substep with the same substepOrder if ( current > 0 && visible[ current - 1 ].dataset.substepOrder === visible[ current ].dataset.substepOrder ) { visible.pop(); return hideSubstep( visible ); } return el; } }; // Register the plugin to be called in pre-stepleave phase. // The weight makes this plugin run before other preStepLeave plugins. window.impress.addPreStepLeavePlugin( substep, 1 ); // When entering a step, in particular when re-entering, make sure that all substeps are hidden // at first document.addEventListener( "impress:stepenter", function( event ) { var step = event.target; var visible = step.querySelectorAll( ".substep-visible" ); for ( var i = 0; i < visible.length; i++ ) { visible[ i ].classList.remove( "substep-visible" ); } }, false ); // API for others to reveal/hide next substep //////////////////////////////////////////////// document.addEventListener( "impress:substep:show", function() { showSubstepIfAny( activeStep ); }, false ); document.addEventListener( "impress:substep:hide", function() { hideSubstepIfAny( activeStep ); }, false ); } )( document, window );