aboutsummaryrefslogtreecommitdiffhomepage
path: root/js/reveal.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/reveal.js')
-rw-r--r--js/reveal.js275
1 files changed, 174 insertions, 101 deletions
diff --git a/js/reveal.js b/js/reveal.js
index d856c3d..f077b78 100644
--- a/js/reveal.js
+++ b/js/reveal.js
@@ -317,7 +317,7 @@ var Reveal = (function(){
setupDOM();
// Decorate the slide DOM elements with state classes (past/future)
- setupSlides();
+ formatSlides();
// Updates the presentation to match the current configuration values
configure();
@@ -346,26 +346,6 @@ var Reveal = (function(){
}
/**
- * Iterates through and decorates slides DOM elements with
- * appropriate classes.
- */
- function setupSlides() {
-
- var horizontalSlides = toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
- horizontalSlides.forEach( function( horizontalSlide ) {
-
- var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
- verticalSlides.forEach( function( verticalSlide, y ) {
-
- if( y > 0 ) verticalSlide.classList.add( 'future' );
-
- } );
-
- } );
-
- }
-
- /**
* Finds and stores references to DOM elements which are
* required by the presentation. If a required element is
* not found, it is created.
@@ -1040,38 +1020,6 @@ var Reveal = (function(){
}
/**
- * Return a sorted fragments list, ordered by an increasing
- * "data-fragment-index" attribute.
- *
- * Fragments will be revealed in the order that they are returned by
- * this function, so you can use the index attributes to control the
- * order of fragment appearance.
- *
- * To maintain a sensible default fragment order, fragments are presumed
- * to be passed in document order. This function adds a "fragment-index"
- * attribute to each node if such an attribute is not already present,
- * and sets that attribute to an integer value which is the position of
- * the fragment within the fragments list.
- */
- function sortFragments( fragments ) {
-
- var a = toArray( fragments );
-
- a.forEach( function( el, idx ) {
- if( !el.hasAttribute( 'data-fragment-index' ) ) {
- el.setAttribute( 'data-fragment-index', idx );
- }
- } );
-
- a.sort( function( l, r ) {
- return l.getAttribute( 'data-fragment-index' ) - r.getAttribute( 'data-fragment-index');
- } );
-
- return a;
-
- }
-
- /**
* Applies JavaScript-controlled layout rules to the
* presentation.
*/
@@ -1572,16 +1520,7 @@ var Reveal = (function(){
// Show fragment, if specified
if( typeof f !== 'undefined' ) {
- var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment' ) );
-
- toArray( fragments ).forEach( function( fragment, indexf ) {
- if( indexf < f ) {
- fragment.classList.add( 'visible' );
- }
- else {
- fragment.classList.remove( 'visible' );
- }
- } );
+ navigateFragment( f );
}
// Dispatch an event if the slide changed
@@ -1664,6 +1603,8 @@ var Reveal = (function(){
// Re-create the slide backgrounds
createBackgrounds();
+ formatSlides();
+
updateControls();
updateProgress();
updateBackground( true );
@@ -1672,6 +1613,30 @@ var Reveal = (function(){
}
/**
+ * Iterates through and decorates slides DOM elements with
+ * appropriate classes.
+ */
+ function formatSlides() {
+
+ var horizontalSlides = toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
+ horizontalSlides.forEach( function( horizontalSlide ) {
+
+ var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
+ verticalSlides.forEach( function( verticalSlide, y ) {
+
+ if( y > 0 ) verticalSlide.classList.add( 'future' );
+
+ sortFragments( verticalSlide.querySelectorAll( '.fragment' ) );
+
+ } );
+
+ if( verticalSlides.length === 0 ) sortFragments( horizontalSlide.querySelectorAll( '.fragment' ) );
+
+ } );
+
+ }
+
+ /**
* Updates one dimension of slides by showing the slide
* with the specified index.
*
@@ -1725,7 +1690,9 @@ var Reveal = (function(){
// Show all fragments on prior slides
while( pastFragments.length ) {
- pastFragments.pop().classList.add( 'visible' );
+ var pastFragment = pastFragments.pop();
+ pastFragment.classList.add( 'visible' );
+ pastFragment.classList.remove( 'current-fragment' );
}
}
else if( i > index ) {
@@ -1736,7 +1703,9 @@ var Reveal = (function(){
// No fragments in future slides should be visible ahead of time
while( futureFragments.length ) {
- futureFragments.pop().classList.remove( 'visible' );
+ var futureFragment = futureFragments.pop();
+ futureFragment.classList.remove( 'visible' );
+ futureFragment.classList.remove( 'current-fragment' );
}
}
@@ -2282,7 +2251,7 @@ var Reveal = (function(){
var hasFragments = currentSlide.querySelectorAll( '.fragment' ).length > 0;
if( hasFragments ) {
var visibleFragments = currentSlide.querySelectorAll( '.fragment.visible' );
- f = visibleFragments.length;
+ f = visibleFragments.length - 1;
}
}
@@ -2291,67 +2260,144 @@ var Reveal = (function(){
}
/**
- * Navigate to the next slide fragment.
+ * Return a sorted fragments list, ordered by an increasing
+ * "data-fragment-index" attribute.
*
- * @return {Boolean} true if there was a next fragment,
- * false otherwise
+ * Fragments will be revealed in the order that they are returned by
+ * this function, so you can use the index attributes to control the
+ * order of fragment appearance.
+ *
+ * To maintain a sensible default fragment order, fragments are presumed
+ * to be passed in document order. This function adds a "fragment-index"
+ * attribute to each node if such an attribute is not already present,
+ * and sets that attribute to an integer value which is the position of
+ * the fragment within the fragments list.
*/
- function nextFragment() {
-
- if( currentSlide && config.fragments ) {
- var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment:not(.visible)' ) );
+ function sortFragments( fragments ) {
- if( fragments.length ) {
- // Find the index of the next fragment
- var index = fragments[0].getAttribute( 'data-fragment-index' );
+ fragments = toArray( fragments );
- // Find all fragments with the same index
- fragments = currentSlide.querySelectorAll( '.fragment[data-fragment-index="'+ index +'"]' );
+ var ordered = [],
+ unordered = [],
+ sorted = [];
- toArray( fragments ).forEach( function( element ) {
- element.classList.add( 'visible' );
- } );
+ // Group ordered and unordered elements
+ fragments.forEach( function( fragment, i ) {
+ if( fragment.hasAttribute( 'data-fragment-index' ) ) {
+ var index = parseInt( fragment.getAttribute( 'data-fragment-index' ), 10 );
- // Notify subscribers of the change
- dispatchEvent( 'fragmentshown', { fragment: fragments[0], fragments: fragments } );
+ if( !ordered[index] ) {
+ ordered[index] = [];
+ }
- updateControls();
- return true;
+ ordered[index].push( fragment );
}
- }
+ else {
+ unordered.push( [ fragment ] );
+ }
+ } );
- return false;
+ // Append fragments without explicit indices in their
+ // DOM order
+ ordered = ordered.concat( unordered );
+
+ // Manually count the index up per group to ensure there
+ // are no gaps
+ var index = 0;
+
+ // Push all fragments in their sorted order to an array,
+ // this flattens the groups
+ ordered.forEach( function( group ) {
+ group.forEach( function( fragment ) {
+ sorted.push( fragment );
+ fragment.setAttribute( 'data-fragment-index', index );
+ } );
+
+ index ++;
+ } );
+
+ return sorted;
}
/**
- * Navigate to the previous slide fragment.
+ * Navigate to the specified slide fragment.
*
- * @return {Boolean} true if there was a previous fragment,
- * false otherwise
+ * @param {Number} index The index of the fragment that
+ * should be shown, -1 means all are invisible
+ * @param {Number} offset Integer offset to apply to the
+ * fragment index
+ *
+ * @return {Boolean} true if a change was made in any
+ * fragments visibility as part of this call
*/
- function previousFragment() {
+ function navigateFragment( index, offset ) {
if( currentSlide && config.fragments ) {
- var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment.visible' ) );
+ var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment' ) );
if( fragments.length ) {
- // Find the index of the previous fragment
- var index = fragments[ fragments.length - 1 ].getAttribute( 'data-fragment-index' );
- // Find all fragments with the same index
- fragments = currentSlide.querySelectorAll( '.fragment[data-fragment-index="'+ index +'"]' );
+ // If no index is specified, find the current
+ if( typeof index !== 'number' ) {
+ var lastVisibleFragment = sortFragments( currentSlide.querySelectorAll( '.fragment.visible' ) ).pop();
+
+ if( lastVisibleFragment ) {
+ index = parseInt( lastVisibleFragment.getAttribute( 'data-fragment-index' ) || 0, 10 );
+ }
+ else {
+ index = -1;
+ }
+ }
+
+ // If an offset is specified, apply it to the index
+ if( typeof offset === 'number' ) {
+ index += offset;
+ }
+
+ var fragmentsShown = [],
+ fragmentsHidden = [];
+
+ toArray( fragments ).forEach( function( element, i ) {
+
+ if( element.hasAttribute( 'data-fragment-index' ) ) {
+ i = parseInt( element.getAttribute( 'data-fragment-index' ), 10 );
+ }
+
+ // Visible fragments
+ if( i <= index ) {
+ if( !element.classList.contains( 'visible' ) ) fragmentsShown.push( element );
+ element.classList.add( 'visible' );
+ element.classList.remove( 'current-fragment' );
+
+ if( i === index ) {
+ element.classList.add( 'current-fragment' );
+ }
+ }
+ // Hidden fragments
+ else {
+ if( element.classList.contains( 'visible' ) ) fragmentsHidden.push( element );
+ element.classList.remove( 'visible' );
+ element.classList.remove( 'current-fragment' );
+ }
+
- toArray( fragments ).forEach( function( f ) {
- f.classList.remove( 'visible' );
} );
- // Notify subscribers of the change
- dispatchEvent( 'fragmenthidden', { fragment: fragments[0], fragments: fragments } );
+ if( fragmentsHidden.length ) {
+ dispatchEvent( 'fragmenthidden', { fragment: fragmentsHidden[0], fragments: fragmentsHidden } );
+ }
+
+ if( fragmentsShown.length ) {
+ dispatchEvent( 'fragmentshown', { fragment: fragmentsShown[0], fragments: fragmentsShown } );
+ }
updateControls();
- return true;
+
+ return !!( fragmentsShown.length || fragmentsHidden.length );
+
}
+
}
return false;
@@ -2359,6 +2405,30 @@ var Reveal = (function(){
}
/**
+ * Navigate to the next slide fragment.
+ *
+ * @return {Boolean} true if there was a next fragment,
+ * false otherwise
+ */
+ function nextFragment() {
+
+ return navigateFragment( null, 1 );
+
+ }
+
+ /**
+ * Navigate to the previous slide fragment.
+ *
+ * @return {Boolean} true if there was a previous fragment,
+ * false otherwise
+ */
+ function previousFragment() {
+
+ return navigateFragment( null, -1 );
+
+ }
+
+ /**
* Cues a new automated slide if enabled in the config.
*/
function cueAutoSlide() {
@@ -3142,6 +3212,9 @@ var Reveal = (function(){
down: navigateDown,
prev: navigatePrev,
next: navigateNext,
+
+ // Fragment methods
+ navigateFragment: navigateFragment,
prevFragment: previousFragment,
nextFragment: nextFragment,