Event Debounce Plugin

Implements a jQuery plugin that provides you with an event when scrolling has been begun then stopped for some time period.

by doug65536

HTML

<h1>Mousemove and scroll are debounced.</h1>


<h2>Log on the right - newest log entry at top</h2>

<div class="log"></div>
<div class="floatleft">
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
</div>
<div class="overflowscroll">
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
    <p>content</p>
</div>

CSS

.floatleft {
    float: left;
    width: 64px;
    background-color: lightgray;
}
.log {
    float: right;
    border: solid black 1px;
    border-radius: 16px;
    padding: 8px;
}
.overflowscroll {
    width: 400px;
    height: 200px;
    overflow: scroll;
    padding
}

JavaScript

// Plugin that adds .debounce() and .debounceSetup()
(function ($) {
    "use strict";

    var defaults = {
        timeout: 500
    };

    $.fn.debounceSetup = function (options) {
        defaults = $.extend(true, {}, defaults, options);
    };

    function makeHandler(element, settings) {
        var item = $(element);

        // Get the data for all debounced events for this element
        var data = $.data(element, 'data.eventDebouncer');

        // Lazy create the data object
        if (data === undefined) {
            data = {};
            $.data(element, 'data.eventDebouncer', data);
        }

        // Lookup or create the event data for this event
        var eventData = data[settings.sourceEvent];
        if (eventData === undefined) {
            eventData = {};
            data[settings.sourceEvent] = eventData;
        } else {
            // We recreate the event handler when it was already debounced
            item.off(eventData.settings.sourceEvent, eventData.handler);
        }

        // Capture a new info object for this handler
        eventData.settings = settings;
        settings = undefined;

        // The handler called when the timeout expires (fires the custom event)
        function timeoutHandler() {
            item.trigger(eventData.settings.createdEvent, eventData.lastEvent);
            eventData.timeoutId = undefined;
        }

        // The handler for the debounced event
        eventData.handler = function (event) {
            // If a timeout is active, cancel it
            if (eventData.timeoutId !== undefined) {
                clearTimeout(eventData.timeoutId);
            }
            eventData.lastEvent = arguments;
            // Setup a timeout to fire if this event stops
            // happening for a full timeout interval
            eventData.timeoutId = setTimeout(timeoutHandler, eventData.settings.timeout);
        };

        // Start capturing events for debounce
       ...