diff options
| author | Juan Marin Noguera <juan@mnpi.eu> | 2023-08-22 17:56:56 +0200 | 
|---|---|---|
| committer | Juan Marin Noguera <juan@mnpi.eu> | 2023-08-22 17:56:56 +0200 | 
| commit | 1fd2213192d22880706440e7f724bdc6db966ee0 (patch) | |
| tree | ff2d6812ef6db399852ad8c4cf2b6f1cd417dfed /present/js/controllers/location.js | |
| parent | 2f9eb7a94819a08937ba08320a142b7f0be407fd (diff) | |
Añadida presentación1.0
Diffstat (limited to 'present/js/controllers/location.js')
| -rw-r--r-- | present/js/controllers/location.js | 245 | 
1 files changed, 245 insertions, 0 deletions
| diff --git a/present/js/controllers/location.js b/present/js/controllers/location.js new file mode 100644 index 0000000..6fa4829 --- /dev/null +++ b/present/js/controllers/location.js @@ -0,0 +1,245 @@ +/** + * Reads and writes the URL based on reveal.js' current state. + */ +export default class Location { + +	// The minimum number of milliseconds that must pass between +	// calls to history.replaceState +	MAX_REPLACE_STATE_FREQUENCY = 1000 + +	constructor( Reveal ) { + +		this.Reveal = Reveal; + +		// Delays updates to the URL due to a Chrome thumbnailer bug +		this.writeURLTimeout = 0; + +		this.replaceStateTimestamp = 0; + +		this.onWindowHashChange = this.onWindowHashChange.bind( this ); + +	} + +	bind() { + +		window.addEventListener( 'hashchange', this.onWindowHashChange, false ); + +	} + +	unbind() { + +		window.removeEventListener( 'hashchange', this.onWindowHashChange, false ); + +	} + +	/** +	 * Returns the slide indices for the given hash link. +	 * +	 * @param {string} [hash] the hash string that we want to +	 * find the indices for +	 * +	 * @returns slide indices or null +	 */ +	getIndicesFromHash( hash=window.location.hash, options={} ) { + +		// Attempt to parse the hash as either an index or name +		let name = hash.replace( /^#\/?/, '' ); +		let bits = name.split( '/' ); + +		// If the first bit is not fully numeric and there is a name we +		// can assume that this is a named link +		if( !/^[0-9]*$/.test( bits[0] ) && name.length ) { +			let element; + +			let f; + +			// Parse named links with fragments (#/named-link/2) +			if( /\/[-\d]+$/g.test( name ) ) { +				f = parseInt( name.split( '/' ).pop(), 10 ); +				f = isNaN(f) ? undefined : f; +				name = name.split( '/' ).shift(); +			} + +			// Ensure the named link is a valid HTML ID attribute +			try { +				element = document.getElementById( decodeURIComponent( name ) ); +			} +			catch ( error ) { } + +			if( element ) { +				return { ...this.Reveal.getIndices( element ), f }; +			} +		} +		else { +			const config = this.Reveal.getConfig(); +			let hashIndexBase = config.hashOneBasedIndex || options.oneBasedIndex ? 1 : 0; + +			// Read the index components of the hash +			let h = ( parseInt( bits[0], 10 ) - hashIndexBase ) || 0, +				v = ( parseInt( bits[1], 10 ) - hashIndexBase ) || 0, +				f; + +			if( config.fragmentInURL ) { +				f = parseInt( bits[2], 10 ); +				if( isNaN( f ) ) { +					f = undefined; +				} +			} + +			return { h, v, f }; +		} + +		// The hash couldn't be parsed or no matching named link was found +		return null + +	} + +	/** +	 * Reads the current URL (hash) and navigates accordingly. +	 */ +	readURL() { + +		const currentIndices = this.Reveal.getIndices(); +		const newIndices = this.getIndicesFromHash(); + +		if( newIndices ) { +			if( ( newIndices.h !== currentIndices.h || newIndices.v !== currentIndices.v || newIndices.f !== undefined ) ) { +					this.Reveal.slide( newIndices.h, newIndices.v, newIndices.f ); +			} +		} +		// If no new indices are available, we're trying to navigate to +		// a slide hash that does not exist +		else { +			this.Reveal.slide( currentIndices.h || 0, currentIndices.v || 0 ); +		} + +	} + +	/** +	 * Updates the page URL (hash) to reflect the current +	 * state. +	 * +	 * @param {number} delay The time in ms to wait before +	 * writing the hash +	 */ +	writeURL( delay ) { + +		let config = this.Reveal.getConfig(); +		let currentSlide = this.Reveal.getCurrentSlide(); + +		// Make sure there's never more than one timeout running +		clearTimeout( this.writeURLTimeout ); + +		// If a delay is specified, timeout this call +		if( typeof delay === 'number' ) { +			this.writeURLTimeout = setTimeout( this.writeURL, delay ); +		} +		else if( currentSlide ) { + +			let hash = this.getHash(); + +			// If we're configured to push to history OR the history +			// API is not available. +			if( config.history ) { +				window.location.hash = hash; +			} +			// If we're configured to reflect the current slide in the +			// URL without pushing to history. +			else if( config.hash ) { +				// If the hash is empty, don't add it to the URL +				if( hash === '/' ) { +					this.debouncedReplaceState( window.location.pathname + window.location.search ); +				} +				else { +					this.debouncedReplaceState( '#' + hash ); +				} +			} +			// UPDATE: The below nuking of all hash changes breaks +			// anchors on pages where reveal.js is running. Removed +			// in 4.0. Why was it here in the first place? ¯\_(ツ)_/¯ +			// +			// If history and hash are both disabled, a hash may still +			// be added to the URL by clicking on a href with a hash +			// target. Counter this by always removing the hash. +			// else { +			// 	window.history.replaceState( null, null, window.location.pathname + window.location.search ); +			// } + +		} + +	} + +	replaceState( url ) { + +		window.history.replaceState( null, null, url ); +		this.replaceStateTimestamp = Date.now(); + +	} + +	debouncedReplaceState( url ) { + +		clearTimeout( this.replaceStateTimeout ); + +		if( Date.now() - this.replaceStateTimestamp > this.MAX_REPLACE_STATE_FREQUENCY ) { +			this.replaceState( url ); +		} +		else { +			this.replaceStateTimeout = setTimeout( () => this.replaceState( url ), this.MAX_REPLACE_STATE_FREQUENCY ); +		} + +	} + +	/** +	 * Return a hash URL that will resolve to the given slide location. +	 * +	 * @param {HTMLElement} [slide=currentSlide] The slide to link to +	 */ +	getHash( slide ) { + +		let url = '/'; + +		// Attempt to create a named link based on the slide's ID +		let s = slide || this.Reveal.getCurrentSlide(); +		let id = s ? s.getAttribute( 'id' ) : null; +		if( id ) { +			id = encodeURIComponent( id ); +		} + +		let index = this.Reveal.getIndices( slide ); +		if( !this.Reveal.getConfig().fragmentInURL ) { +			index.f = undefined; +		} + +		// If the current slide has an ID, use that as a named link, +		// but we don't support named links with a fragment index +		if( typeof id === 'string' && id.length ) { +			url = '/' + id; + +			// If there is also a fragment, append that at the end +			// of the named link, like: #/named-link/2 +			if( index.f >= 0 ) url += '/' + index.f; +		} +		// Otherwise use the /h/v index +		else { +			let hashIndexBase = this.Reveal.getConfig().hashOneBasedIndex ? 1 : 0; +			if( index.h > 0 || index.v > 0 || index.f >= 0 ) url += index.h + hashIndexBase; +			if( index.v > 0 || index.f >= 0 ) url += '/' + (index.v + hashIndexBase ); +			if( index.f >= 0 ) url += '/' + index.f; +		} + +		return url; + +	} + +	/** +	 * Handler for the window level 'hashchange' event. +	 * +	 * @param {object} [event] +	 */ +	onWindowHashChange( event ) { + +		this.readURL(); + +	} + +}
\ No newline at end of file | 
