11

I'm trying to get a cross-browser way to listen to keyCode of user's keyDown.

For mobile browsers, I have to trigger the virtual keyboard, so I use an input hidden by css, triggered with a click event. This works well except that when I try to listen to keycode, on fennec (mobile Firefox), I've got strange behavior.

Here is the function I use to listen to keycode.

document.querySelectorAll('input')[0].addEventListener('keydown', handler);

function handler(e) {
  e.preventDefault();
  var k = (e.which) ? e.which : e.keyCode;
  document.getElementById('log').innerHTML = k;
  this.style.backgroundColor = "#FFAAFF";
}
<input type="text" />
<span id="log"></span>
  • In Firefox for android (v34 to v37), it won't fire until the user typed return.
    Actually, I found that if the value of the input is not empty, it works well, at least on load. So I thought of a workaround like this one : if(this.value=='')this.value='*'; Seems to work but if you spam it, the backspace isn't blocked, so when the input is cleared, the bug comes back : the workaround doesn't fire either.
    +This a ugly workaround, which I'm sure will create other bugs in other browsers.

       
       document.querySelectorAll('input')[0].addEventListener('keydown', handler);
       
       function handler(e) {
         if(this.value=='')this.value='*';
         e.preventDefault();
         var k = (e.which) ? e.which : e.keyCode;
         document.getElementById('log').innerHTML = k;
         this.style.backgroundColor = "#FFAAFF";
       }
       
       
       
       <input type="text" value="*"/>
       <span id="log"></span>
       
       
  • In B2G (Firefox Os 1.3 on device or 2.0 emulated) the behavior is even odder:
    the function only reads keyCode for backspace(keycode 8) or return(keyCode 13) keys. Any other key will return 0.

So, my question is, do you know a better cross browser way to listen to keyCode, a one working in all major browsers, desktop or mobile, and on fennec?

Ps: even if I write my app in vanilla-js, it's ok for me to see solutions with any library.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • 1
    I think in many mobile browser, the `keyup`/`keydown` events don't fire until the user enters the input (when the `change` event fires). – Alexander O'Mara Dec 16 '14 at 02:41

1 Answers1

2

There isn't a perfect solution to listen the KeyCode across browsers and OS... Simply because javascript uses the same Key Codes that are reported by the Operating System where it runs. You will be better off using the input event instead of keyDown

According to this site the input event occurs when the text content of an element is changed through the user interface, which is what you want, because in some mobile browsers/OS events don't fire until the user enters the input and the change event fires.

$(document).ready(function () {
    var inputEvent = 'oninput' in window ? 'input' : 'keyup';
    $('#listen').on(inputEvent, function (event) {
        $('#show').val($('#show').val() + '\n' + event.type);
        console.log('--- input event ----');
        for (var v in event.originalEvent) {
            if (event.hasOwnProperty(v)) {
                console.log(v + ' |---> ' + event[v]);
            }
        }
    })
    //just added to see what Silk listens for on the keyup event
    $('#listen').on('keyup', function (event) {
        $('#show').val($('#show').val() + '\n' + event.type + ' | which --> ' + event.which);
        console.log('--- keyup event ----');
        for (var v in event.originalEvent) {
            if (event.hasOwnProperty(v)) {
                console.log(v + ' |-.-> ' + event[v]);
            }
        }
    })
});
input {
    font-size: 22px
}
input, textarea {
    width:300px;
}
textarea {
    height:300px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div>
    <input type='text' id="listen" />
    <br/>
    <br/>
    <textarea type='text' id="show"></textarea>
</div>
lalengua
  • 509
  • 3
  • 15
António Regadas
  • 714
  • 4
  • 11
  • Thanks,I'll look further in this later, but for now I can tell that Firefox for Android doesn't see the keyup event and only reports `input` (even for keyup event) and that B2G reports the same 0 keyCode – Kaiido Dec 16 '14 at 18:44
  • Thats why you have to listen for the 'input' event instead the 'keyup' or 'keydown' in your 'addEventListener'. Try running the fiddle i posted on the mobile devices you're testing and post the outcome here :) thanks. – António Regadas Dec 16 '14 at 18:56
  • As I told in my comment, on Ff Os, the input event.which is always set to `0`. The keyup event detects backspace and return keys. On Android (FF) the input event.which always returns 0. On desktop FF, it always returns 0. On webkit browsers (desktop or ios), this property is undefined. So no, I don't think this event is the solution, or am I missing something? – Kaiido Dec 16 '14 at 20:51
  • If the browser only fires on `input` and not `keyDown`, then it's virtually impossible to capture all keys. You could get the ones that enter characters or remove them by detecting changes, but you could not get any keys that do not affect input. That means you are at a dead end for some functionality as those OSes go. _If you are going to monitor the input anyway,_ then you don't need to know the key that was pressed. You can detect the change in the input and do something if `input.value.slice(-1) === 'a'` or the like. – Makaze Dec 21 '14 at 10:15
  • @Makaze no actually, `keydown` event does fire on most browsers/Os. It is the `input` event which almost never returns any `event.which` nor `event.keyCode`. But as the major problem is with fennec, and I didn't get any better way in here, I think I'll write to Mozilla guys to see if they have something about it. If I find a solution, I'll post it here. – Kaiido Dec 22 '14 at 21:49