article/MoreTags.js

/**
 * Shows only first 4 tags on page load
 * If there is more than 5 tags, add +{more tags} button after last displayed tag
 * Shows remaining tags on button click and hide the button
 *
 * @module MoreTags
 * @prop {Integer} tagsToShowInitially - Maximum number of tags to display on page load
 * @prop {String} tagContainerSelector - Tag container class
 * @prop {String} hiddenClass - CSS hiding class
 * @prop {Object} $tagContainer - DOM reference to tag container
 * @prop {Array} tags - Array of tags in $tagContainer
 */
const MoreTags = {
	tagsToShowInitially: 4,
	tagContainerSelector: '.c-tags__body',
	hiddenClass: 'is-hidden',
	$tagContainer: null,
	tags: null,

	/**
	 * Initializes tags logic on article pages
	 *
	 * @method init
	 */
	init() {
		// If there is no tag container, bail
		if ( ! document.querySelector( this.tagContainerSelector ) ) {
			return;
		}

		// Assign elements
		this.$tagContainer = document.querySelector( this.tagContainerSelector );

		this.tags = this.$tagContainer.querySelectorAll( '.c-tags__link' );

		// If number of tags is less or same as maximum allowed number, bail
		if ( this.tagsToShowInitially >= this.tags.length ) {
			return;
		}

		// Hide extra tags
		// Note: IE11 does not support .forEach method on Object, use Object.keys
		Object.keys( this.tags ).forEach( ( key ) => {
			const count = parseInt( key, 10 );
			if ( this.tagsToShowInitially < count + 1 ) {
				this.tags[key].classList.add( 'is-hidden' );
			}
		});

		// Add '+' button after last displayed tag
		const $moreButton = document.createElement( 'a' );
		$moreButton.setAttribute( 'href', '#' );
		$moreButton.classList.add( 'c-tags__link' );
		$moreButton.classList.add( 'c-tags__link--more' );

		// Create screenreader text
		const $srSpan = document.createElement( 'span' );
		$srSpan.classList.add( 'sr-only' );
		const srText = document.createTextNode( 'Click to see more tags' );
		$srSpan.appendChild( srText );
		$moreButton.appendChild( $srSpan );

		const text = document.createTextNode( `+${this.tags.length - this.tagsToShowInitially}` );
		$moreButton.appendChild( text );
		$moreButton.addEventListener( 'click', ( event ) => {
			this.handleClick( event );
		});
		this.$tagContainer.appendChild( $moreButton );
	},

	/**
	 * Handles click on 'More tags' button
	 *
	 * @method handleClick
	 */
	handleClick( event ) {
		event.preventDefault();
		this.tags.forEach( ( $tag ) => {
			if ( $tag.classList.contains( this.hiddenClass ) ) {
				$tag.classList.remove( this.hiddenClass );
			}
		});
		// Hide the button
		event.target.classList.add( this.hiddenClass );
	},
};

export default MoreTags;