May 02

Responsive Javascript Part 2

Quick recap. In part 1 of this blog we create two events, a hover event for desktop and a click event for mobile. With these events, we wrapped it around an IF statement so the script can decide which event to render base on window width. In part 2 we are going to make that code better! The main issue addresses testing responsive. Most people seem to believe that, by dragging the browser handles, that's is the best way to test responsive layouts. Just because the window emulate different resolutions doesnt mean its the best way to test. The ONLY REAL WAY of testing responsive is by device testing. Thank GOD there are browsers that render specific resolutions perfectly for this. But for the random people, developers included, that believe by going 'epileptic' on the browser handles to some random, nonsense resolution is testing, YOU ARE WRONG! AND PEOPLE LIKE YOU ^&# #%@%&$@#@% ^&%&&**$#!!! Shame on you and your house. Sorry, my client experience with responsive testing has caused me many nights of crying, half-naked in a fetal position.

Currently, if you test the code from part 1 you'll notice, while shrinking the browsers between 960px and below that the events does not change. The code works fine, because actual site load will use the correct event. So if I was on my phone, the click event will fire. On my desktop, the hover event will fire. But for the people who resize browser handles, a better solution is warranted instead of reloading page for every break-point. This requires three additional steps. A quick summary, we will wrap both events into a function, run an unbind event in the function and fire the function on window resize. The original code from part 1.

Mark up

<img src="http://lorempixel.com/400/200" class="test" />
var imgHeight = $('.test').height();
var imgWidth = $('.test').width();

if( $(window).width() >= 958){
	$('.test').mouseenter(function(){
		$(this).width(imgWidth * 2).height(imgHeight * 2);
	});
	$('.test').mouseleave(function(){
		$(this).width(imgWidth).height(imgHeight);
	});
}else{
	$('.test').click(function(){
		if( $(this).width == imgWidth || $(this).height() == imgHeight){
			$(this).width(imgWidth * 2).height(imgHeight * 2);
		}else{
			$(this).width(imgWidth).height(imgHeight);
		}
	});
}
Wrap it in a function and call the function.
var imgHeight = $('.test').height();
var imgWidth = $('.test').width();

function myInteraction(){
	if( $(window).width() >= 958){
		$('.test').mouseenter(function(){
			$(this).width(imgWidth * 2).height(imgHeight * 2);
		});
		$('.test').mouseleave(function(){
			$(this).width(imgWidth).height(imgHeight);
		});
	}else{
		$('.test').click(function(){
			if( $(this).width == imgWidth || $(this).height() == imgHeight ){
				$(this).width(imgWidth * 2).height(imgHeight * 2);
			}else{
				$(this).width(imgWidth).height(imgHeight);
			}
		});
	}
}

myInteraction();
Now wrapping the IF statement in a function like this does essentially the same thing as part 1. But in this case, turning it into a function makes it easier to fire that function repeatedly. Now we want this to trigger every time the window is resized. Doing it this way will force the script to run the function every time the window is resized, the script determines which event to fire base on the width of the browser.
var imgHeight = $('.test').height();
var imgWidth = $('.test').width();

function myInteraction(){
	if( $(window).width() >= 958){
		$('.test').mouseenter(function(){
			$(this).width(imgWidth * 2).height(imgHeight * 2);
		});
		$('.test').mouseleave(function(){
			$(this).width(imgWidth).height(imgHeight);
		});
	}else{
		$('.test').click(function(){
			if( $(this).width == imgWidth || $(this).height() == imgHeight ){
				$(this).width(imgWidth * 2).height(imgHeight * 2);
			}else{
				$(this).width(imgWidth).height(imgHeight);
			}
		});
	}
}

myInteraction();

$(window).resize(function(){
	myInteraction();
});
But another issue arises. Now we will have two events stacking, none negating the other. Which is really buggy. To fix this we will need to add some kind of unbind event. Since I'm using jQuery, and .off() event is best.
var imgHeight = $('.test').height();
var imgWidth = $('.test').width();

function myInteraction(){
	$('.test').off();

	if( $(window).width() >= 958){
		$('.test').mouseenter(function(){
			$(this).width( imgWidth * 2).height(imgHeight * 2);
		});
		$('.test').mouseleave(function(){
			$(this).width( imgWidth).height(imgHeight);
		});
	}else{
		$('.test').click(function(){
			if( $(this).width == imgWidth || $(this).height() == imgHeight){
				$(this).width(imgWidth * 2).height( imgHeight * 2);
			}else{
				$(this).width(imgWidth).height(imgHeight);
			}
		});
	}
}

myInteraction();

$(window).resize(function(){
	myInteraction();
});
The idea here is to remove any events associated every time the function fires then reset the event through the IF statement. BAH-BOOM!!!