如何使用javascript有效地记录用户输入?

时间:2011-11-09 20:45:01

标签: javascript

我希望能够录制然后回放文本区中发生的任何事情。

我遇到了一些解决方案,但它们不可靠,就像通过AJAX发送每次击键一样。在那种情况下,我最终会在我的数据库中拥有数百万行。

我想到的想法是将键击记录到客户端的变量,使用操作更新该变量,但跟踪每个键盘之间的时间。还要确保它也支持删除数据。

最后我将整个变量发送到db一次,然后我可以稍后解码它以进行播放。

思考变量的外观图:

   hellooo[1.2][backspace][0.6][backspace]World![return]
Idle time __^     Removes one char __^

我相信谷歌文档正在做类似的事情来播放用户输入的内容。

任何想法?

3 个答案:

答案 0 :(得分:10)

幸运的是,JavaScript事件已经为您解决了所有编码问题。您只需将keyup / keydown / keypress /中的任何内容直接放入数组中就可以抛出整个事件对象。

每个对象包含:

  • 活动类型
  • 时间戳
  • 使用了什么密钥(或密钥的组合)
  • 焦点是什么
  • 其他一些可能最终有用的东西。

然后,您可以对数组进行编码,并使用您喜欢的ajax方法将其发送到服务器进行存储。

因此,您的代码只需要一个可以存储数据的函数。请勿使用此功能,仅用于演示目的。

var handler = function (e) { 
    handler.data.push(e);
    console.log(handler.data);
}
handler.data = [];

window.addEventListener("keyup",    handler); 
window.addEventListener("keydown",  handler); 
window.addEventListener("keypress", handler);

因为它是一个数组,所以它们都应该是有序的,但是在奇怪的事件中,它会对每个事件都有时间戳数据(这也可以让你找出事件之间的延迟,这是 AWESOME 如果你有混合按键。)。

然后您可以重播事件但是您希望设计它们 - 但是现在您不必创建自己的规范,因为w3c的可爱fokes在设计DOM事件规范时为您完成了所有艰苦的工作。 / p>

答案 1 :(得分:5)

存储每个操作的时间和操作的结果,以及完成序列化日志并存储的时间。
单独重放每个动作过于复杂。假设用户向后移动几个字符并在那里添加新字符。您需要跟踪光标位置 记住每次击键时textarea的全部价值。没有必要记住那是怎么发生的?

这是一个实现。 fiddle

<textarea id="recorder"></textarea>
<textarea id="playback"></textarea>

<script type="text/javascript">

var Playback = {
    //store the time an action occured and the resulting state in an object
    //don't use an array because they are not sparce - interstitial keys
    //will have to be iterated over
    record: {},
    init: function( recorderId, playbackId ) {
        this.recorder = document.getElementById( recorderId );
        this.playback = document.getElementById( playbackId );

        this.recorder.addEventListener( 'focus', function() {
            Playback.record = {};
            this.value = '';
        }, false );

        this.recorder.addEventListener( 'keyup', function( e ) {
            Playback.record[ (new Date()).getTime() ] = this.value;
        }, false );

        this.recorder.addEventListener( 'blur', function( e ) {
            Playback.playback.value = '';
            //store the time the sequence started
            //so that we can subtract it from subsequent actions
            var mark = null;
            for( var t in  Playback.record ) {
                if( mark ) {
                    var timeout = t - mark;
                } else {
                    var timeout = 0;
                    mark = t;
                }
                // We need to create a callback which closes over the value of t
                // because t would have changed by the time this is run
                setTimeout( Playback.changeValueCallback( Playback.record[t] ), timeout );
            }
        }, false );

    },

    changeValueCallback: function( val ) {
        return function() { Playback.playback.value = val }
    }
}

Playback.init( 'recorder', 'playback' );

</script>

警告: 事件处理仅适用于兼容的浏览器,您需要自己使用Internet Explorer

答案 2 :(得分:0)

数据库可以处理数百万条记录,因此这不是一个真正的问题。

如果您仍然不想这样做,您可以将与会话相关的所有数据编码为JSON,并将其存储在数据库的文本字段中或存储在服务器上的文件中。在这种情况下,如果数据非常大,可能需要一段时间才能加载数据并将其发送到浏览器,从而导致用户延迟。