summaryrefslogtreecommitdiff
path: root/2024-06-18-guix-social/reveal.js/js/controllers/slidenumber.js
blob: e213e29e5181c5f501102e825b188bb2e758cfeb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import {
	SLIDE_NUMBER_FORMAT_CURRENT,
	SLIDE_NUMBER_FORMAT_CURRENT_SLASH_TOTAL,
	SLIDE_NUMBER_FORMAT_HORIZONTAL_DOT_VERTICAL,
	SLIDE_NUMBER_FORMAT_HORIZONTAL_SLASH_VERTICAL
} from "../utils/constants";

/**
 * Handles the display of reveal.js' optional slide number.
 */
export default class SlideNumber {

	constructor( Reveal ) {

		this.Reveal = Reveal;

	}

	render() {

		this.element = document.createElement( 'div' );
		this.element.className = 'slide-number';
		this.Reveal.getRevealElement().appendChild( this.element );

	}

	/**
	 * Called when the reveal.js config is updated.
	 */
	configure( config, oldConfig ) {

		let slideNumberDisplay = 'none';
		if( config.slideNumber && !this.Reveal.isPrintView() ) {
			if( config.showSlideNumber === 'all' ) {
				slideNumberDisplay = 'block';
			}
			else if( config.showSlideNumber === 'speaker' && this.Reveal.isSpeakerNotes() ) {
				slideNumberDisplay = 'block';
			}
		}

		this.element.style.display = slideNumberDisplay;

	}

	/**
	 * Updates the slide number to match the current slide.
	 */
	update() {

		// Update slide number if enabled
		if( this.Reveal.getConfig().slideNumber && this.element ) {
			this.element.innerHTML = this.getSlideNumber();
		}

	}

	/**
	 * Returns the HTML string corresponding to the current slide
	 * number, including formatting.
	 */
	getSlideNumber( slide = this.Reveal.getCurrentSlide() ) {

		let config = this.Reveal.getConfig();
		let value;
		let format = SLIDE_NUMBER_FORMAT_HORIZONTAL_DOT_VERTICAL;

		if ( typeof config.slideNumber === 'function' ) {
			value = config.slideNumber( slide );
		} else {
			// Check if a custom number format is available
			if( typeof config.slideNumber === 'string' ) {
				format = config.slideNumber;
			}

			// If there are ONLY vertical slides in this deck, always use
			// a flattened slide number
			if( !/c/.test( format ) && this.Reveal.getHorizontalSlides().length === 1 ) {
				format = SLIDE_NUMBER_FORMAT_CURRENT;
			}

			// Offset the current slide number by 1 to make it 1-indexed
			let horizontalOffset = slide && slide.dataset.visibility === 'uncounted' ? 0 : 1;

			value = [];
			switch( format ) {
				case SLIDE_NUMBER_FORMAT_CURRENT:
					value.push( this.Reveal.getSlidePastCount( slide ) + horizontalOffset );
					break;
				case SLIDE_NUMBER_FORMAT_CURRENT_SLASH_TOTAL:
					value.push( this.Reveal.getSlidePastCount( slide ) + horizontalOffset, '/', this.Reveal.getTotalSlides() );
					break;
				default:
					let indices = this.Reveal.getIndices( slide );
					value.push( indices.h + horizontalOffset );
					let sep = format === SLIDE_NUMBER_FORMAT_HORIZONTAL_SLASH_VERTICAL ? '/' : '.';
					if( this.Reveal.isVerticalSlide( slide ) ) value.push( sep, indices.v + 1 );
			}
		}

		let url = '#' + this.Reveal.location.getHash( slide );
		return this.formatNumber( value[0], value[1], value[2], url );

	}

	/**
	 * Applies HTML formatting to a slide number before it's
	 * written to the DOM.
	 *
	 * @param {number} a Current slide
	 * @param {string} delimiter Character to separate slide numbers
	 * @param {(number|*)} b Total slides
	 * @param {HTMLElement} [url='#'+locationHash()] The url to link to
	 * @return {string} HTML string fragment
	 */
	formatNumber( a, delimiter, b, url = '#' + this.Reveal.location.getHash() ) {

		if( typeof b === 'number' && !isNaN( b ) ) {
			return  `<a href="${url}">
					<span class="slide-number-a">${a}</span>
					<span class="slide-number-delimiter">${delimiter}</span>
					<span class="slide-number-b">${b}</span>
					</a>`;
		}
		else {
			return `<a href="${url}">
					<span class="slide-number-a">${a}</span>
					</a>`;
		}

	}

	destroy() {

		this.element.remove();

	}

}