article/LiveBlogAccessibility.js

/**
 * Adds aria-lables to semantic elements in liveblog entries
 * Liveblog displays entries using elements <article> and <aside>
 * For accessibility standards, such elements should include a unique aria-label
 *
 * @module LiveBlogAccessibility
 * @prop {Object} selectors - DOM element selectors
 * @prop {Array} paginationButtons - pagination buttons in liveblog (Next, Prev)
 */
const LiveBlogAccessibility = {
	selectors: {
		liveblogContainer: '#wpcom-liveblog-container',
		liveblogEntry: '.liveblog-entry',
		liveblogAside: '.liveblog-entry-aside',
		liveblogTimeContainer: '.liveblog-meta-time',
		liveblogPaginationButton: '.liveblog-btn',
	},

	paginationButtons: [],

	/**
	 * Look if liveblog is enabled in the article, init
	 *
	 * @method init
	 */
	init() {
		// Let liveblog entries load first
		setTimeout( () => {
			// If liveblog is not enabled, bail
			if ( ! document.querySelector( this.selectors.liveblogContainer ) ) {
				return;
			}
			this.addArialabels();
		}, 3000 );

		this.paginationButtons = document.querySelectorAll( this.selectors.liveblogContainer );
		// Add event listener only if liveblog has pagination buttons
		if ( 0 < this.paginationButtons.length ) {
			Object.keys( this.paginationButtons ).forEach( ( key ) => {
				const $button = this.paginationButtons[key];
				$button.addEventListener( 'click', () => {
					// Let the next page of liveblog entries load first
					setTimeout( () => {
						this.addArialabels();
					}, 1000 );
				});
			});
		}
	},

	/**
	 * Adds unique aria-label to liveblog <article> and <aside> elements bases on entry timestamp
	 *
	 * @method addArialabels
	 */
	addArialabels() {
		const $entries = document.querySelectorAll( this.selectors.liveblogEntry );
		// if there are no liveblog entries, bail
		if ( ! $entries ) {
			return;
		}

		// Note: IE11 does not support .forEach method on Object, use Object.keys
		Object.keys( $entries ).forEach( ( key ) => {
			const $entry = $entries[key];
			// get entry date and time
			const $timeContainer = $entry.querySelector( this.selectors.liveblogTimeContainer );
			if ( ! $timeContainer ) {
				return;
			}

			const $timeSpans = $timeContainer.querySelectorAll( 'span' );

			if ( ! $timeSpans || 2 > $timeSpans.length ) {
				return;
			}
			// set as aria-label on article element
			const time = $timeSpans[1].innerHTML;
			$entry.setAttribute( 'aria-label', `Blog entry (${time})` );

			// set as aria-label on aside element
			const $aside = $entry.querySelector( this.selectors.liveblogAside );
			$aside.setAttribute( 'aria-label', `Blog entry (${time}) sidebar links` );
		});
	},
};

export default LiveBlogAccessibility;