diff --git a/app/assets/javascripts/discourse/components/debounce.js b/app/assets/javascripts/discourse/components/debounce.js index b9be435c6f2..cbd654001b6 100644 --- a/app/assets/javascripts/discourse/components/debounce.js +++ b/app/assets/javascripts/discourse/components/debounce.js @@ -1,6 +1,7 @@ /** Debounce a Javascript function. This means if it's called many times in a time limit it - should only be executed once. + should only be executed once (at the end of the limit counted from the last call made). + Original function will be called with the context and arguments from the last call made. @method debounce @module Discourse @@ -8,32 +9,16 @@ @param {Number} wait how long to wait **/ Discourse.debounce = function(func, wait) { - var timeout = null; + var self, args; + var later = function() { + func.apply(self, args); + }; return function() { - var context = this; - var args = arguments; + self = this; + args = arguments; - var later = function() { - timeout = null; - return func.apply(context, args); - }; - - if (timeout) return; - - var currentWait; - if (typeof wait === "function") { - currentWait = wait(); - } else { - currentWait = wait; - } - - if (timeout) { - clearTimeout(timeout); - } - - timeout = setTimeout(later, currentWait); - return timeout; + Ember.run.debounce(null, later, wait); }; }; diff --git a/test/javascripts/components/debounce_test.js b/test/javascripts/components/debounce_test.js index 98c7550b95c..d3c88cd4e4d 100644 --- a/test/javascripts/components/debounce_test.js +++ b/test/javascripts/components/debounce_test.js @@ -4,6 +4,10 @@ var firedOnce = function(message) { ok(original.calledOnce, message); }; +var firedTwice = function(message) { + ok(original.calledTwice, message); +}; + var notFired = function(message) { ok(!original.called, message); }; @@ -39,27 +43,20 @@ test("executes delayed function only once, no matter how many times debounced fu firedOnce("second call was supressed"); }); -test("does not prolong the timeout when the debounced function is called for the second time during the timeout", function() { +test("prolongs the timeout when the debounced function is called for the second time during the timeout", function() { debounced(); clock.tick(50); debounced(); clock.tick(50); - firedOnce("function is executed exactly at the end of the original timeout"); -}); - -test("returns a JS timer handle that allows delayed execution to be cancelled before the timeout ends", function() { - var timerId = debounced(); + notFired("at the end of the original timeout nothing happens"); clock.tick(50); - clearTimeout(timerId); - - clock.tick(50); - notFired("timeout has ended but function was not executed"); + firedOnce("function is executed exactly at the end of the prolonged timeout"); }); -test("preserves first call's context and params when executing delayed function", function() { +test("preserves last call's context and params when executing delayed function", function() { var firstObj = {}; var secondObj = {}; @@ -67,11 +64,11 @@ test("preserves first call's context and params when executing delayed function" debounced.call(secondObj, "second"); clock.tick(100); - ok(original.calledOn(firstObj), "the context of the first of two subsequent calls is preserved"); - ok(original.calledWithExactly("first"), "param passed during the first of two subsequent calls is preserved"); + ok(original.calledOn(secondObj), "the context of the last of two subsequent calls is preserved"); + ok(original.calledWithExactly("second"), "param passed during the last of two subsequent calls is preserved"); }); -test("can be called again (with a different context and params) after timeout passes", function() { +test("can be called again after timeout passes", function() { var firstObj = {}; var secondObj = {}; @@ -81,6 +78,5 @@ test("can be called again (with a different context and params) after timeout pa debounced.call(secondObj, "second"); clock.tick(100); - ok(original.calledOn(secondObj), "function is executed with the context of the call made after the timeout has passed"); - ok(original.calledWithExactly("second"), "function is executed with the param passed to the call made after the timeout has passed"); + firedTwice(); });