Keydown处理前一个字符而不是当前字符

时间:2012-12-25 14:05:03

标签: jquery keydown delayed-execution

我尝试使用jquery和ajax创建MS-Dos仿真窗口。 它工作得很好但是当我输入一个单词或按回车键时,脚本显示的时间太晚了(第一次按下时没有显示任何字符,对于每个下一个keydown,它显示用户键入的前一个字符而不是当前字符)。

以下是我的脚本的简化版本:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <link rel="stylesheet" type="text/css" href="css/terminal.css">
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
        <script type="text/javascript">
            $(document).ready(function() 
            {       
                //set cursor position
                $('#cursor').css('left','0px');

                //focus on textfield
                $('#field').focus();

                //On key down...
                $('#field').keydown(function(event) 
                {
                    request=$(this).val();
                    count=$(this).val().length;

                    //Display chars as they come
                    $("#instruct").html(request);

                    // If "enter" is pressed
                    if (event.which == 13) 
                    {
                        event.preventDefault();

                        //clean user entry
                        request=request.replace(/\n/g, "");

                        // Process user entry
                        $.ajax({
                              type: "POST",
                              url: "scripts/ajax/terminal.php",
                              data: {command:request},
                              success: function(response) 
                              {
                                // if user typed something before pressing "enter"
                                if(response !='')
                                {
                                    // update list by logging the previous entry, showing system response and clearing the textarea
                                    $('#log').append("<li class='user'>--- &gt;<span>"+request+"</span></li>");
                                    $('#log').append("<li class='sys' >SYS &gt;<span>"+response+"</span></li>");
                                    $('#field').val('');
                                }
                              }
                        }); 
                    }
                });             
            });
        </script>   
    </head>

    <body>
        <ul id="log">
            <li class='sys'>Sys &gt;<span>Identification required</span></li>
        </ul>

        <ul id="realtime">
            <li id="live-space">
                <span class="user-line">--- &gt;</span>
                <textarea type="text" id="field"></textarea>
                <div>
                    <span id="instruct"></span><div id="cursor">_</div>
                </div>
            </li>
        </ul>
    </body>
</html>

我确定“keyDown”应该被触发,因为我改变了这个

$("#instruct").html(request);

进入这个

$("#instruct").html(request+'x');

...“x”将在第一次keydown后直接显示,而“request”内容将被延迟到下一次keydown(例如,如果我键入“a”,我只会看到“x”和当我立即输入“b”后,我看到“斧头”等等......)。

所以这不是关于解雇keydown而是关于在正确的时间选择正确的角色。

我做错了什么?

谢谢。

2 个答案:

答案 0 :(得分:3)

<强> Working demo

在捕获字段之前没有更新字段的值,只需附加按下的键的char,但如果使用String.fromCharCode(event.which),则keydown将返回大写字符,因此请使用keypress < / p>

$('#field').on('keypress',function(event){
    request=$(this).val() + String.fromCharCode(event.which);
    ...

或者您可以使用

$('#field').on('keyup',function(event){
    request=$(this).val(); // value is ready by now
    ...

但反馈显得较慢,因为您正在等待释放密钥

答案 1 :(得分:2)

这是关于时间的。在keydown事件发生时,控件尚未收到该字符 - 事实上,它甚至不确定是否会收到该字符(因为您可以屏蔽keydownkeypress,它只在它之后添加)。因此,当你阅读你的控制内容时,你做得太早了 - 这就像你决定去麦当劳时尝试吃汉堡包,而不是在你去支付它之后。

您可以阅读有关键盘事件here的更多信息,并在spec here中详细了解。

解决方案:这不是keydown的意思。尝试查看change事件是否适合您。编辑:我的意思是,抓住change事件带来的角色。正如您所做的那样,使用keydown抓住Enter键。