Monthly Archives: February 2016

JQuery infinite loops on change event – how to prevent

Let’s say you have three date fields on a page, and all three need to be kept in sync.  Additionally, each time a field changes, you need to trigger a ‘change’ event.  This change event then triggers the the same action on another field, and you’re into an infinite loop until you run out of stack space and crash.

Updating all three fields itself doesn’t cause a problem.  It’s the triggering the ‘change’ event that gets you into an endless loop.

This can be solved by saving a flag in localStorage.  sessionStorage would work fine too, or any others like localdb, etc.

What we want to do is test whether we’re on the initial change, or one of the changes triggered by our code.  So we store the millisecond we start, and test against it when the additional ‘change’ events get triggered.  The later ones will be at a slightly different time.

$('#date1, #date2, #date3').on('change', function(){
	var date = $(this).val();
	var d = new Date();
	var now = d.getTime();
	var upd = localStorage.getItem('updating_date');
	if(!upd) {
		localStorage.setItem('updating_date', now);
	} 
	
	// Update the fields
	$('#date1').val(date);
	$('#date2').val(date);
	$('#date3').val(date);
	
	// Only trigger the change if we're on the initial call - one millisecond later we won't be, preventing the loop
	if(localStorage.getItem('updating_date') == d.getTime()) {
		$('#date1').trigger('change');
		$('#date2').trigger('change');
		$('#date3').trigger('change');
	}
	setTimeout(function() {
		localStorage.removeItem('updating_date');
	}, 1);
});

Yes, I know. I’m re-setting the value and re-triggering the change event on the initial element again. For this use case I didn’t feel compelled to weed out the duplicate.