main/StickyOrganizer.js

import customEvent from '../utils/customEvent';
import StickyVideo from './classes/StickyVideo';

/**
 * StickyOrganizer
 *
 * Define functions to adjust bottom leaderboard position to work with other stickky elements
 *
 * @module StickyOrganizer
 */

const StickyOrganizer = {
	selectors: {
		bottomAd: '[id^="districtm-touch-container-"]',
		backToTop: '.c-backToTop',
		sticky: '.c-stickToTop',
		sectionAnchor: '.l-article__sectionAnchor',
		radioBanner: '.c-radioBanner--sticky',
		container: '.l-container',
	},

	states: {
		backToTopShift: 'c-backToTop--shift',
		backToTopBigShift: 'c-backToTop--bigShift',
		stickyShift: 'c-stickToTop--shift',
		stickyBigShift: 'c-stickToTop--bigShift',
		anchorShift: 'l-article__sectionAnchor--shift',
		anchorBigShift: 'l-article__sectionAnchor--bigShift',
		radioBannerShift: 'c-radioBanner--shift',
		radioBannerBodyFlag: 'radio-footer',
		headerStickyAttached: 'l-container--headerStickyAttached',
	},

	$container: false,

	init() {
		window.addEventListener( customEvent.STICKY_ON, evt => this.stickyOn( evt ) );
		window.addEventListener( customEvent.STICKY_OFF, evt => this.stickyOff( evt ) );

		this.$container = document.querySelector( this.selectors.container );

		// if radio banner exists then adjust ad position
		const $radioBanner = document.querySelector( this.selectors.radioBanner );
		if ( $radioBanner ) {
			customEvent.fire( window, customEvent.STICKY_ON, {
				target: $radioBanner,
				selector: this.selectors.radioBanner,
			});
		}
	},

	/**
	 * Adjust element positioning when there's sticky video is stuck.
	 *
	 * @method stickyOn
	 */
	stickyOn( event ) {
		const $target = event.detail.target;
		const $stickies = document.querySelectorAll( this.selectors.sticky );
		const $anchors = document.querySelectorAll( this.selectors.sectionAnchor );

		if ( $target.dataset.headerSticky ) {
			this.$container.classList.add( this.states.headerStickyAttached );
		}

		switch ( event.detail.selector ) {
		case 'c-stickyVideo':
			if ( $target.classList.contains( StickyVideo.stickySelectors.states.mini ) ) {
				// Adjust bottom leaderboard position.
				const $bottomAd = document.querySelector( this.selectors.bottomAd );
				if ( $bottomAd ) {
					const height = $target.clientHeight;
					$bottomAd.style.bottom = `${height}px`;
				}

				// Adjust back to top button position.
				const $backToTop = document.querySelector( this.selectors.backToTop );
				if ( $backToTop ) {
					if ( $bottomAd ) {
						$backToTop.classList.add( this.states.backToTopBigShift );
					} else {
						$backToTop.classList.add( this.states.backToTopShift );
					}
				}

				// Adjust radio banner
				const $radioBanner = document.querySelector( this.selectors.radioBanner );
				if ( $radioBanner ) {
					$radioBanner.classList.add( this.states.radioBannerShift );

					// remove radio banner body flag
					const $body = document.querySelector( 'body' );
					$body.classList.remove( this.states.radioBannerBodyFlag );
				}
			}
			break;
		case '.l-notification':
		case '.l-headerAd__container':
			[].forEach.call( $stickies, ( $sticky ) => {
				if ( $target.offsetHeight > 90 ) {
					$sticky.classList.add( this.states.stickyBigShift );
				} else {
					$sticky.classList.add( this.states.stickyShift );
				}
			});

			[].forEach.call( $anchors, ( $anchor ) => {
				if ( $target.offsetHeight > 90 ) {
					$anchor.classList.add( this.states.anchorBigShift );
				} else {
					$anchor.classList.add( this.states.anchorShift );
				}
			});

			break;
		case '.c-radioBanner--sticky': {
			// Adjust bottom leaderboard position.
			// We need to add a class to do this since the footer loads before the catfish ad
			const $body = document.querySelector( 'body' );
			$body.classList.add( this.states.radioBannerBodyFlag );
		}
			break;
		default:
			break;
		}
	},

	/**
	 * Adjust element positioning when there's sticky video is unstuck.
	 *
	 * @method stickyOff
	 */
	stickyOff( event ) {
		const $target = event.detail.target;
		const $stickies = document.querySelectorAll( this.selectors.sticky );
		const $anchors = document.querySelectorAll( this.selectors.sectionAnchor );

		if ( $target.dataset.headerSticky ) {
			this.$container.classList.remove( this.states.headerStickyAttached );
		}

		switch ( event.detail.selector ) {
		case 'c-stickyVideo':
			if ( $target.classList.contains( StickyVideo.stickySelectors.states.mini ) ) {
				// Reset bottom leaderboard position.
				const $bottomAd = document.querySelector( this.selectors.bottomAd );
				if ( $bottomAd ) {
					$bottomAd.style.bottom = '0';
				}

				// Reset back to top button position.
				const $backToTop = document.querySelector( this.selectors.backToTop );
				if ( $backToTop ) {
					$backToTop.classList.remove( this.states.backToTopShift );
					$backToTop.classList.remove( this.states.backToTopBigShift );
				}

				// Adjust radio banner
				const $radioBanner = document.querySelector( this.selectors.radioBanner );
				if ( $radioBanner ) {
					$radioBanner.classList.remove( this.states.radioBannerShift );

					// Add radio banner body flag
					const $body = document.querySelector( 'body' );
					$body.classList.add( this.states.radioBannerBodyFlag );
				}
			}
			break;
		case '.l-notification':
		case '.l-headerAd__container':
			[].forEach.call( $stickies, ( $sticky ) => {
				$sticky.classList.remove( this.states.stickyBigShift );
				$sticky.classList.remove( this.states.stickyShift );
			});

			[].forEach.call( $anchors, ( $anchor ) => {
				$anchor.classList.remove( this.states.anchorShift );
				$anchor.classList.remove( this.states.anchorBigShift );
			});

			break;
		default:
			break;
		}
	},
};

export default StickyOrganizer;