JSFiddle - React, Tailwind, and code Playground

by Jon-Carlos Rivera

HTML

<script src="http://jon-carlos.com/scripts/masala.js"></script>

JavaScript

function bouncer (options) {
	var maybeTrigger;

	if (options.triggerAtEnd) {
		maybeTrigger = maybeTriggerEnd;
	} else {
		maybeTrigger = maybeTriggerStart;
	}

	return bounce(maybeTriggerEnd(options.calculateDelay, options.onTrigger));
}

var invokeWith = Function.call.bind(Function.apply);

function bounce (next) {
	var bounces = 0;

	function resetBounce () {
		bounces = 0;
	}

	return function () {
		next(++bounces, resetBounce, [this, arguments]);
	};
}

function handle (delayFn, maybeTriggerFn) {
	return function (numBounces, resetBounce, triggerInvokeArgs) {
		//var delay = delayFn(numBounces);
		maybeTriggerFn(delayFn, resetBounce, triggerInvokeArgs);
	};
}

function maybeTriggerStart (delayFn, triggerFn) {
	var timer;

	function doReset (resetBounceFn) {
		resetBounceFn();
		timer = null;
	}

	return function (numBounces, resetBounceFn, triggerInvokeArgs) {
		var delay = delayFn(numBounces);
		if (timer) {
			clearTimeout(timer);
		} else {
			invokeWith(triggerFn, triggerInvokeArgs);
		}
		timer = setTimeout(doReset, delay, resetBounceFn);
	};
}

function maybeTriggerEnd (delayFn, triggerFn) {
	var timer;

	function doTrigger (resetBounceFn, triggerInvokeArgs) {
		resetBounceFn();
		invokeWith(triggerFn, triggerInvokeArgs);
	}

	return function (numBounces, resetBounceFn, triggerInvokeArgs) {
		var delay = delayFn(numBounces);
		if (timer) {
			clearTimeout(timer);
		}
		timer = setTimeout(doTrigger, delay, resetBounceFn, triggerInvokeArgs);
	};
}

var debounce = masala(bouncer, {
	onTrigger: null,
	calculateDelay: function (numBounces) {
		return 200;
	},
	triggerAtEnd: true
});

// Delay is `---`
// End Triggered:   e-e--e-e---<trigger><reset>
// Start Triggered: e<trigger>-e--e-e---<reset>

var atEnd = debounce({onTrigger: console.log.bind(console)});
var atStart = debounce({onTrigger: console.log.bind(console), triggerAtEnd: false});

atEnd('foo');atEnd('bar');atEnd('baz');

atStart('foo');atStart('bar');atStart('baz');