使用javascript在Android虚拟键盘上键入捕获键

时间:2015-06-09 21:52:20

标签: javascript android jquery samsung-mobile

我有一个带有textarea的网页,我需要捕获用户键入的键(这样我就可以用键入的键替换不同的unicode字符)。我目前的代码如下:

$("#myTextArea").bind('keypress', function(event) {

    var keyInput = event.which;
   // call other functions

});

以上代码适用于PC和iPhone / Safari。但是,在Android (三星)平板电脑上使用Chrome时,会失败。出于某种原因,当我在 android虚拟(软)键盘上键入时,"按键"事件未被触发。 Android版本是5.0.2。

如果我尝试使用" keyUp"或者" keyDown",它总是为所有字符返回229 (返回键,空格,退格键等除外)。

即使keyCode始终为229,textarea也会显示用户键入的正确字符。这意味着设备知道输入了哪个密钥,但不知怎的,我无法使用javascript来处理此事件(以及密钥代码)。

以下是我迄今为止尝试过的替代方案及其结果:

$("#mainTextArea").on("keydown keyup", function(event) { 
    // event.which and event.keyCode both return 229

$(document).on('keypress', function(event) { 
    // function is not triggered

$('#myTextArea').bind('input keypress', function(event) { 
   // comes inside function, but keyCode and which are undefined

对此问题的任何帮助表示赞赏..

7 个答案:

答案 0 :(得分:10)

不幸的是,你似乎在这里做不了多少。 Keypress事件已弃用,因此不会被触发。 229 on keyup和keydown表示键盘缓冲区正忙。原因 - 当您按下某个键时 - 输入仍不能保证是用户按下的内容,因为自动建议和其他事件可能会立即跟随并使事件无效。 虽然在我看来,首先发送密钥会更好,然后在自动建议中触发另一个事件,这样你就可以单独采取行动......

我目前唯一知道的是连接到keydown和keyup,将值存储在keydown上,获取keyup上的值并找到delta,这是用户按下的。不幸的是,这对于非输入控件(例如 - 身体或类似的东西)不起作用。 也许不是你想听到的答案,但仍然。

答案 1 :(得分:6)

我遇到了同样的问题。有几种解释,但无论如何似乎很奇怪,没有提供解决方案。 目前我通过捕获oninput事件来解决它。

"此事件类似于onchange事件。不同之处在于oninput事件在元素的值发生更改后立即发生,而onchange在元素失去焦点时发生,在内容更改后#34;

此事件也支持插入文本,粘贴文本或更正&建议。

它没有给我完美的解决方案,因为我只能在输入后操作文本,但目前它是我所拥有的最好的文本。

如果有人有更好的解决方案,我会很高兴听到它。

答案 2 :(得分:3)

只检查输入字符keyCode,如果它是0或229那么这里是函数 getKeyCode(),它使用JS的 charCodeAt 来返回输入的KeyCode string一个参数并返回最后一个字符的keycode。

<script>
        var getKeyCode = function (str) {
            return str.charCodeAt(str.length);
        }


        $('#myTextfield').on('keyup',function(e){

            //for android chrome keycode fix
            if (navigator.userAgent.match(/Android/i)) {

                var inputValue = this.value;

                var charKeyCode = e.keyCode || e.which;
                if (charKeyCode == 0 || charKeyCode == 229) { 
                    charKeyCode = getKeyCode(inputValue);
                    alert(charKeyCode+' key Pressed');
                }else{
                   alert(charKeyCode+' key Pressed');
                    }
            }       
        });
    </script>

答案 3 :(得分:3)

在为我正在进行的项目进行研究时,我遇到了这个讨论。我不得不为移动应用程序创建输入掩码,Pavel Donchev's answer让我想到了什么可以在Android中捕获密钥。在我的特定项目中,keydown和keyup是不够的,因为keyup事件只在一个密钥被释放后触发,所以它意味着在后期验证,所以我做了一些更多的研究(和许多试验和错误)与输入事件并使它工作。

var input = document.getElementById('credit-card-mask'),
    oldValue,
    newValue,
    difference = function(value1, value2) {
      var output = [];
      for(i = 0; i < value2.length; i++) {
        if(value1[i] !== value2[i]) {
          output.push(value2[i]);
        }
      }
      return output.join("");
    },
    keyDownHandler = function(e) {
      oldValue = input.value;
      document.getElementById("onkeydown-result").innerHTML = input.value;
    },
    inputHandler = function(e) {
      newValue = input.value;
      document.getElementById("oninput-result").innerHTML = input.value;
      document.getElementById("typedvalue-result").innerHTML = difference(oldValue, newValue);
    }
;

input.addEventListener('keydown', keyDownHandler);
input.addEventListener('input', inputHandler);
<input type="text" id="credit-card-mask" />
<div id="result">
  <h4>on keydown value</h4>
  <div id="onkeydown-result"></div>
  <h4>on input value</h4>
  <div id="oninput-result"></div>
  <h4>typed value</h4>
  <div id="typedvalue-result"></div>
</div>

oninput事件在keydown事件发生后立即触发,这是我验证的最佳时机。

我在一篇文章中编写了整篇文章。如果你很好奇,可以阅读here

答案 4 :(得分:2)

有一个textInput事件可以为您提供输入的字符

const inputField = document.getElementById('wanted-input-field');

inputField.addEventListener('textInput', function(e) {
    // e.data will be the 1:1 input you done
    const char = e.data; // In our example = "a"

    // If you want the keyCode..
    const keyCode = char.charCodeAt(0); // a = 97

    // Stop processing if "a" is pressed
    if (keyCode === 97) {
        e.preventDefault();
        return false;
    }
    return true;
});

答案 5 :(得分:1)

我最近实施了一个&#34;提及&#34;最新版本的Astro AI辅助电子邮件应用程序中的功能。基本上你输入&#34; @&#34;在我们的撰写网页视图中,您将获得自动填充建议列表。我们和大多数其他人一样,在Javascript中试图解决这个问题时遇到了问题。最终起作用的是原生解决方案。如果@Override WebView的onCreateInputConnection()方法,则可以使用自定义类包装super.onCreateInputConnection()结果(它只是一个InputConnection接口)。然后在你的包装器实现中,你可以通过commitText()或setComposingText()或者某些特定于你正在寻找的其他方法来捕获输入...就像删除一样。我不知道你是否会对上下箭头等控制字符进行回调,但也许这可以成为解决你特定问题的地方。

答案 6 :(得分:-3)

我想出来了!

这是一个100%可行的解决方案,可以在任何地方使用各种功能,包括iOS上的表情符号建议和任何粘贴的内容。我正在使用子字符串比较来查找从onInput更改为onInput的实际内容。

指出删除文本的位置以及从中插入文本的点。

评分和选择作为答案表示赞赏。

var x = document.getElementById("area"),
    text = x.value,
    event_count = 0



function find_Entered_And_Removed_Substrings(
    previous_string, current_string, pos
) {
    let
        right_pos = pos,
        right_boundary_of_removed =
            previous_string.length -
            (
                current_string.length -
                pos
            ),
        left_max_pos = Math.min(
            pos,
            right_boundary_of_removed
        ),
        left_pos = left_max_pos

    for (
        let x = 0; x < left_max_pos; x++
    ) {
        if (
            previous_string[x] !==
            current_string[x]
        ) {
            left_pos = x
            break
        }
    }


    return {
        left: left_pos,
        right: pos,
        removed_left: left_pos,
        removed_right: right_boundary_of_removed
    }
}

x.oninput =
    (e) => {
        // debugger;
        let
            cur_text = x.value,
            positions =
                find_Entered_And_Removed_Substrings(
                    text, cur_text, Math.max(
                        x.selectionStart, x.selectionEnd
                    )
                )
        console.log(positions)
        let
            entered =
                cur_text.substring(
                    positions.left, positions.right
                ),
            removed =
                text.substring(
                    positions.removed_left, positions.removed_right
                )


        if (
            entered.length >
            0 ||
            removed.length >
            0
        ) {
            document.getElementById("entered")
                .innerHTML +=
                entered

            document.getElementById("removed")
                .innerHTML +=
                removed

            document.getElementById("events")
                .innerHTML =
                event_count++
        }


        text = cur_text
    }
<textarea id="area"></textarea>
<br/>
<pre id="entered"></pre>
<br/>
<div id="events"></div>
<pre id="removed"></pre>