0

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

这是我的脚本的简化版本:

<!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”紧随其后,我看到“ax”等......)。

所以这不是关于触发按键,而是关于在正确的时间选择正确的角色。

我做错了什么?

谢谢你。

4

2 回答 2

3

工作演示

该字段的值在您捕获它之前不会被更新,只需附加按下的键的字符,但如果您使用String.fromCharCode(event.which)则返回大写字符keydownkeypress

$('#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
    ...

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

于 2012-12-25T14:17:52.190 回答
2

这是关于时机。在keydown事件发生的时候,控件还没有接收到字符——事实上,它甚至不确定它是否会接收到它(因为你可以阻止keydownkeypress,它只是在它之后添加)。因此,当您阅读控件的内容时,您做得太早了 - 这就像您决定去麦当劳时尝试吃汉堡包,而不是在您去付款之后。

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

解决方案:这不是keydown本意。尝试看看change活动是否更适合您。编辑:我的意思是,抓住change事件中的角色。keydown像你做的那样用 抓住 Enter 键。

于 2012-12-25T14:10:31.363 回答