如何有效地记录用户打字使用javascript

How to efficiently record user typing using javascript?

本文关键字:javascript 用户 有效地 记录      更新时间:2023-09-26

我希望能够记录然后播放在文本区发生的任何事情。

我遇到过一些解决方案,但他们不可靠,像通过AJAX发送每个击键。在这种情况下,我最终会有数百万行在我的数据库。

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

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

这个变量应该是什么样子的思维导图:

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

我相信google docs正在做类似的事情来回放用户输入的内容。

任何想法?

幸运的是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的可爱的家伙在设计DOM事件规范时已经为你做了所有的艰苦工作。

存储每个操作的时间和该操作的结果,并在完成时序列化日志并存储。
单独重放每个动作太复杂了。假设用户向后移动了几个字符,并在那里添加了新的字符。您需要跟踪光标的位置。
只需记住每次击键时文本区域的整个值。没有必要记住是怎么发生的,对吧?

这是一个实现。小提琴

<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

数据库是用来处理数百万条记录的,所以这不是真正的问题。

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