0

I'm trying to debounce keystrokes in a form input on IE Mobile 6 (from what I gather, about on par with IE 3-4 in terms of support).

Due to the lack of support, I can't add event listeners after declaration (i.e., document.getElementById('elementId').addEventListener(...) doesn't work), I can only do them inline, like onkeydown="doSomething()".

Here is a jsBin.

So, with this debounce function (taken from David Walsh):

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 recommended way to set up your event function would be like:

var doSomething = debounce(function() { ... }, 250);

However, I can't use this doSomething style function in the inline event listeners on IE Mobile 6.

So, in the markup, I've tried:

<input type="text" onkeydown="doSomething()" />

And

<input type="text" onkeydown="doSomething()()" />

And in javascript:

// return the result of debounce()
function doSomething() {
    return debounce(function() { ... }, 250);
}

// just debounce()
function doSomething() {
    debounce(function() { ... }, 250);
}

// return the result of the returned function of debounce, aka debounce()()
function doSomething() {
    return debounce(function() { ... }, 250)();
}

I've also just tried putting the whole contents of the debounce function inside of this function, like:

function doSomething() {
    var timeout, func, wait, immediate;

    func = function() {
        console.log('test');
    };

    wait = 250;

    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);
    };
}

So, long question short:

How can I write this exact statement:

var doSomething = debounce(...);

Like this:

function doSomething() {

}
Tom
  • 2,180
  • 7
  • 30
  • 48
  • if you're doing `var doSomething = debounce(function() { ... }, 250);` outside a function, there's no reason you can't use it directly in `onkeydown="doSomething()"` so something else must be going on. If you're doing it in a function, you could try `window.doSomething = debounce(function() { ... }, 250);` to make it global – CupawnTae May 28 '15 at 19:01
  • This seems excessive to do. Why not just tie into the oninput event? – Travis J May 28 '15 at 19:02
  • Just a heads up @Tom, a little digging found a doc stating that IE Mobile 6 only supports ECMAScript 3 :[. I'm checking around to see if this might have something to do with your `document.getElementById()` and `addEventLIstener` issue...IE has always been a little flaky with its implementations of JS in the earlier years. http://download.microsoft.com/download/8/c/c/8cc611e7-ec6b-49ee-af4a-415559d53262/Internet%20Explorer%20Mobile%206.pdf – Danny Bullis May 28 '15 at 19:15
  • Just in case you're not opposed to do some light reading, here's the ECMAScript 3 ref. I checked to see if the `.apply` call in the debounce method was an issue...didn't seem like it. http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999.pdf – Danny Bullis May 28 '15 at 19:17
  • also, exactly what version are you using - seems like early 6.x versions didn't support keyboard events http://www.hjgode.de/wp/2009/05/14/internet-explorer-mobile-handles-key-events/ – CupawnTae May 28 '15 at 19:20
  • Try using `.attachEvent` instead of `.addEventListener`. Older implementations of IE browsers (< IE 9) use the attachEvent method. It looks like IE Mobile 6 borrows a lot of its technologies from IE 8, so that's suspect. `document.getElementById("elementId").attachEvent("keydown", doSomething)` http://stackoverflow.com/questions/9769868/addeventlistener-not-working-in-ie8 – Danny Bullis May 28 '15 at 19:25

1 Answers1

0

You seem to have a pretty unique situation. Given that your target browser (IE Mobile 6) implements pretty old technologies (ECMAScript 3 and elements from IE 8), you won't be able to use the standard addEventListener method. Part of your problem is likely due to a mixture of the context limitations of using inline javascript along with the fact that you're programming against an old, old (1999) version of JS. Let's see how this works.

EDIT Also make sure you're wrapping your code in some kind of document ready. I'll use jQuery to do that. That could be why your JS isn't executing.

HTML

<input type='text' id='theInput' />
<script src='yourDebounceScript.js'></script>

JS

// by the time this is executed, 
// DOM elements above this script will be ready
(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);
        };
    }

    var input = document.getElementById('theInput');
    input.attachEvent('keydown' function() {

        // wrap your debounce function in an anonymous function
        // so that you can pass arguments to the debounce as needed
        debounce(function() { /* ... */ }, 250, true);

    });
})();

If you can use jQuery:

// make sure the document is ready before trying to access the DOM
$(function() {

    // your debounce function here...

    // jQuery will handle the version compatibility for you
    $('#theInput').keydown(debounce);

});
Danny Bullis
  • 3,043
  • 2
  • 29
  • 35