Source:three-image-tiles.component.js

(function () {
	'use strict';
	// Three Image Tiles
	angular
		.module('mohistory')
		.component('threeImageTiles', {
			templateUrl: 'app/components/three-image-tiles/three-image-tiles.component.html',
			controller: threeImageTilesCtrl,
			controllerAs: 'threeImageTiles',
			bindings: {
				data: '<',
				pauseParallax: '<'
			}
		});
	threeImageTilesCtrl.$inject = [];
	/**
	 * This component can render any of these mhs:displayClasses recent-posts,
	 * locations-row, three-up-image-description-link, related-content, press-kit,
	 * exhibits-row, three-up-images-and-titles (aka resource-block) or 
	 * exhibit-sponsors The vm.block object contains configuration information for
	 * each mhs:displayClass.
	 * @memberof mohistory
     * @name threeImageTiles
     * @ngdoc component
	 */
	function threeImageTilesCtrl() {
		var vm = this;
		/* ----- Variables ----- */
		vm.rowSplit = [];
		vm.blocks = {
			'recent-posts': {
				itemsPerRow: 'inf', // 'inf' means the block does not require it's data split into rows
				isInteractive: true,
				usesParallax: false,
				parallaxSpeed: -2,
				limitTo: 100, // This value is used to split data into rows, so is arbitrary for this block
				begin: 0,
			},
			'related-content': {
				itemsPerRow: 'inf',
				isInteractive: false,
				usesParallax: true,
				parallaxSpeed: 2,
				limitTo: 100,
				begin: 0,
			},
			'locations-row': {
				itemsPerRow: 'inf',
				isInteractive: false,
				usesParallax: true,
				parallaxSpeed: 1,
				limitTo: 100,
				begin: 0,
			},
			'three-up-image-description-link': {
				itemsPerRow: 'inf',
				isInteractive: false,
				usesParallax: true,
				parallaxSpeed: 1,
				limitTo: 100,
				begin: 0,
			},
			'press-kit': {
				itemsPerRow: 'inf',
				isInteractive: false,
				usesParallax: true,
				parallaxSpeed: 2,
				limitTo: 100,
				begin: 0,
			},
			'exhibits-row': {
				itemsPerRow: 'inf',
				isInteractive: false,
				usesParallax: false,
				parallaxSpeed: 1,
				limitTo: 100,
				begin: 0,
			},
			'press-row': {
				itemsPerRow: 'inf',
				isInteractive: false,
				usesParallax: false,
				parallaxSpeed: 1,
				limitTo: 100,
				begin: 0,
			},
			'publications-row': {
				itemsPerRow: 'inf',
				isInteractive: false,
				usesParallax: false,
				parallaxSpeed: 1,
				limitTo: 100,
				begin: 0,
			},
			'exhibit-sponsors': {
				itemsPerRow: 'inf',
				isInteractive: false,
				usesParallax: true,
				parallaxSpeed: 1,
				limitTo: 100,
				begin: 0,
			},
			'three-up-images-and-titles': {
				itemsPerRow: 3,
				isInteractive: false,
				usesParallax: false,
				parallaxSpeed: 1,
				limitTo: 3,
				begin: 0,
			},
			'press-photos': {
				itemsPerRow: 3,
				isInteractive: false,
				usesParallax: true,
				parallaxSpeed: 2,
				limitTo: 3,
				begin: 0,
			},
		};
		vm.typeLookup = {
			'mhs_exhibit': 'Exhibit',
			'mhs_event': 'Event',
			'mhs_parentEvent': 'Event',
			'mhs_page': 'Page',
			'mhs_post': 'Post',
			'mhs_presskits': 'Media',
			'mhs_collection_item': 'Collection Item',
			'mhs_legacy_web_page': 'Legacy Web Page',
		};
		vm.curBlockConfig = {};
		vm.dataToDisplay = [];
		vm.currentImageIdx = 0;
		vm.imageLoop = [];
		/* ----- Function Bindings ----- */
		vm.$onInit = onInit;
		vm.isImageVisible = isImageVisible;
		vm.forwardByOne = forwardByOne;
		vm.backByOne = backByOne;
		/* ----- Function Definitions ----- */
		/**
		 * Initiated when component is created. Runs code necessary for block
		 * configuration.
		 * @function onInit
		 * @memberof threeImageTiles
		 */
		function onInit() {
			// Edge case: 'three-up-images-and-titles' appears as 'resource-block' in the CMS.
			if (vm.data['mhs:displayClass'] === 'resource-block') {
				vm.data['mhs:displayClass'] = 'three-up-images-and-titles';
			}
			// Edge case: 'press-photos' appears as 'mediaPhotoBlock' in the CMS.
			if (vm.data['mhs:displayClass'] === 'mediaPhotoBlock') {
				vm.data['mhs:displayClass'] = 'press-row';
			}
			vm.curBlockConfig = vm.blocks[vm.data['mhs:displayClass']];
			// Due to HTML constraints, some blocks need to be split into rows.
			// If a block's itemsPerRow is set to 'inf' it mean the block will wrap
			// to accommodate data. Block's with itemsPerRow set to a number require
			// HTML separation into rows. These blocks use the rowsSplit array to 
			// determine where to split data for rows.
			if (vm.curBlockConfig.itemsPerRow !== 'inf') {
				var rows = Math.ceil(vm.data['mhs:parts'].length / vm.curBlockConfig.itemsPerRow);
				for (var i = 0; i < rows; i++) {
					vm.rowSplit.push(i * 3);
				}
			} else {
				vm.rowSplit.push(0);
			}
			// Determine the array of data to display.
			// If the block is not interactive, the data is not sliced
			if (vm.curBlockConfig.isInteractive) {
				vm.dataToDisplay = vm.data['mhs:parts'].slice(0, 3);
			} else {
				vm.dataToDisplay = vm.data['mhs:parts'];
			}
		}
		/**
		 * Helper function for interactive blocks. Returns a boolean that is
		 * used to hide/show a tile.
		 * @function isImageVisible
		 * @memberof threeImageTiles
		 * @param {number} idx The index of the image to check 
		 * @return {boolean} True if input is the same as the currentImageIdx, false otherwise
		 */
		function isImageVisible(idx) {
			return idx === vm.currentImageIdx;
		}
		/**
		 * Advance the visible tiles by one. This only applies to interactive blocks and will allow for rotation.
		 * @function forwardByOne
		 * @memberof threeImageTiles
		 */
		function forwardByOne() {
			vm.currentImageIdx = vm.currentImageIdx + 1 < vm.data['mhs:parts'].length ? vm.currentImageIdx + 1 : 0;
		}
		/**
		 * Retreat the visible tiles by one. This only applies to interactive blocks and will allow for rotation.
		 * @function backByOne
		 * @memberof twoImageTiles
		 */
		function backByOne() {
			vm.currentImageIdx = vm.currentImageIdx - 1 >= 0 ? vm.currentImageIdx - 1 : vm.data['mhs:parts'].length - 1;
		}
	};
})();