d3.event is null inside of debounced function

d3.js, dom-events, javascript, svg

Solution

This happens because D3 removes the event variable after the event has finished, since debounce uses a timeout when it gets called its to late and the event its gone.

To solve this you could use a modified version of your debounce function to save the current event and replace it before your call.

function debounceD3Event(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this;
    var args = arguments;
    var evt  = d3.event;

    var later = function() {
      timeout = null;
      if (!immediate) {
        var tmpEvent = d3.event;
        d3.event = evt;
        func.apply(context, args);
        d3.event = tmpEvent;
      }
    };

    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) {
      var tmpEvent = d3.event;
      d3.event = evt;
      func.apply(context, args);
      d3.event = tmpEvent;
    }

  };
}

Problem

When attempting to use a debounced version of a mousemove event handler, `d3.event` is `null`. I'd like to use the `d3.mouse` object in this de-bounced handler, but `d3.event` returns null and throws an error. How can I have access to `d3.event` in the following code: ``` // a simple debounce function function debounce(func, wait, immediate) { var timeout; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) { func.apply(context, args); } }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) { func.apply(context, args); } }; } // the function to handle the mouse move function handleMousemove ( context ) { var mouse = d3.mouse( context ); console.log( mouse ); } // create a debounced version var debouncedHandleMousemove = debounce(handleMousemove, 250); // set up the svg elements and call the debounced version on the mousemove event d3.select('body') .append('svg') .append('g') .append('rect') .attr('width', 200) .attr('height', 200) .on('mousemove', function () { debouncedHandleMousemove( this ); }); ``` A jsfiddle if you care to see it in action. Trying mousemoving over the `rect` element.

Original source