Skip to content

Organizing functionality

Daisho Komiyama edited this page Jul 5, 2018 · 2 revisions

They say being able to organize functions is one of necessary skillsets for JS dev who has two to three years of experience. Agreed.

*Task 1, 2 and 4 are omitted; See repo: Module_Pattern_Example

Task 3

Refactor "header.js", "carousel.js", and "details.js" to use the "module pattern". Each file should expose one module name (Header, Carousel, and Details, respectively).

1. header.js

before

var $modal = $("[rel=js-modal]");

$("[rel=js-header]").on("click","> [rel^=js]",function(evt){
	evt.preventDefault();
	evt.stopPropagation();
	evt.stopImmediatePropagation();

	var url = $(evt.target).attr("href");

	$.ajax(url,{ dataType: "text" })
	.then(function(contents){
		$modal.html(contents).show();
	});
});

after

var Header = (function() {

	function clickHeaderLink(event) {
		event.preventDefault();
		event.stopPropagation();
		event.stopImmediatePropagation();

		var url = $(event.target).attr("href");

		$.ajax(url,{ dataType: "text" })
		.then(function(contents){
			$modal.html(contents).show();
		});
	}

	function init() {
		$modal = $("[rel=js-modal]");
		$("[rel=js-header]").on("click","> [rel^=js]", clickHeaderLink);
	}

        var $modal;

	return {
		init: init
	};

})();

2. carousel.js

before

$(document).ready(function(){

	function scrollLeft(evt) {
		evt.preventDefault();
		evt.stopPropagation();
		evt.stopImmediatePropagation();

		if (position > 0) {
			position = Math.max(0,position - 250);
		}

		$items.css({ left: (-position) + "px" });
	}

	function scrollRight(evt){
		evt.preventDefault();
		evt.stopPropagation();
		evt.stopImmediatePropagation();

		if (position < maxPosition) {
			position = Math.min(maxPosition,position + 250);
		}

		$items.css({ left: (-position) + "px" });
	}

	var $content = $("[rel=js-carousel] > [rel=js-content]");
	var $items = $content.children("[rel=js-items]");
	var $left = $("[rel=js-carousel] > [rel=js-controls] > [rel=js-left]");
	var $right = $("[rel=js-carousel] > [rel=js-controls] > [rel=js-right]");


	var contentWidth = $content.width();
	var itemsWidth = $items.width();
	var position = 0;
	var maxPosition = (itemsWidth - contentWidth);

	$left.click(scrollLeft);
	$right.click(scrollRight);

});

after

var Carousel = (function() {

	function scrollLeft(evt) {
		evt.preventDefault();
		evt.stopPropagation();
		evt.stopImmediatePropagation();

		if (position > 0) {
			position = Math.max(0,position - 250);
		}

		$items.css({ left: (-position) + "px" });
	}

	function scrollRight(evt){
		evt.preventDefault();
		evt.stopPropagation();
		evt.stopImmediatePropagation();

		if (position < maxPosition) {
			position = Math.min(maxPosition,position + 250);
		}

		$items.css({ left: (-position) + "px" });
	}

	function personClicked(event) {
		event.preventDefault();
	
		var ID = $(event.target).attr('rel').replace(/^.*(\d+)$/, '$1');
		Details.loadPerson(ID);
	}

	function init() {
		$content = $("[rel=js-carousel] > [rel=js-content]");
		$items = $("[rel=js-carousel] > [rel=js-content] > [rel=js-items]");
		$left = $("[rel=js-carousel] > [rel=js-controls] > [rel=js-left]");
		$right = $("[rel=js-carousel] > [rel=js-controls] > [rel=js-right]");
		$items.on('click', '> [rel^="js-item-"]', personClicked);
		
		contentWidth = $content.width();
		itemsWidth = $items.width();
		position = 0;
		maxPosition = (itemsWidth - contentWidth);

		$left.on('click', scrollLeft);
		$right.on('click', scrollRight);
	}

	var $content, $items, $left, $right,
		contentWidth, itemsWidth, position, maxPosition
	;

        //Publish init,
        //other than that, nothing is accessible so that you can keep global name space clean
	return {
		init: init
	};

})();

3. details.js

before

$(document).ready(function(){

	var $items = $("[rel=js-carousel] > [rel=js-content] > [rel=js-items]");
	var $content = $("[rel=js-details]");

	function loadPerson(ID) {
		$.ajax("details/" + ID + ".html",{ dataType: "text" })
		.then(function(content){
			$content.html(content);
		});
	}

	function personClicked(evt) {
		evt.preventDefault();
		evt.stopPropagation();
		evt.stopImmediatePropagation();

		var ID = $(evt.target).attr("rel").replace(/^.*(\d+)$/,"$1");
		loadPerson(ID);
	}

	$items.on("click","> [rel^=js-item-]",personClicked);

});

after

var Details = (function() {

	function loadPerson(ID) {
		$.ajax('details/' + ID + '.html', {
			dataType: 'text'
		}).then(function(content) {
			$('[rel="js-details"]').html(content);
		});
	}

	function init() {		
		$content = $("[rel=js-details]");
	}

	var $content;
        
        //Publish only two functions below,
        //other than those, nothing is accessible so that you can keep global name space clean
	return {
		init: init,
		loadPerson: loadPerson
	};

})();

app.js

$(document).ready(function() {
    Header.init();
    Carousel.init();
    Details.init();
});

index.html

...
<script src="js/header.js"></script>
<script src="js/carousel.js"></script>
<script src="js/details.js"></script>
<script src="js/app.js"></script>
...
Clone this wiki locally