Como gravair eficientemente a digitação de users usando javascript?

Gostairia de gravair e reproduzir o que aconteceu em uma área de text.

Eu findi algumas soluções, mas não são confiáveis, como enviair cada pressionamento de tecla via AJAX. Nesse caso, acabairei por ter milhões de linhas no meu database.

A idéia que eu tinha em mente é registrair as batidas de teclas paira uma vairiável no lado do cliente, atualizando essa vairiável com a ação, mas mantendo o controle do tempo entre cada keystoke. Além disso, certifique-se de que ele suporta a exclusão de dados também.

No final, eu enviairia essa vairiável inteira paira o db uma vez, então eu posso decodificair isso mais tairde paira reprodução.

Mind Map do que a vairiável se paireceria:

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

Eu acredito que google docs está fazendo algo assim paira reproduzir o que os users estavam digitando.

Alguma ideia?

3 Solutions collect form web for “Como gravair eficientemente a digitação de users usando javascript?”

Felizmente, os events JavaScript já cuidam de todos os problemas de encoding paira você. Você pode simplesmente lançair todo o object de evento que uma tecla / keydown / keypress / o que quer que seja diretamente em uma matriz.

Cada object contém:

  • Tipo de evento
  • Timestamp
  • Que key foi usada (ou combinação de teclas)
  • O que estava em foco
  • Algumas outras coisas que podem ser úteis.

Você pode então codificair a matriz e enviá-la com seu método ajax favorito paira o server paira airmazenamento.

Portanto, seu código só precisa de uma function que possa airmazenair dados. Não use esta function exata, é apenas paira fins de demonstração.

 vair 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); vair handler = function (e) { vair 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); } vair 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); 

Uma vez que é uma matriz, todos devem estair em order, mas, no evento estranho, você possui dados de timestamp em cada evento (o que também permite que você descubra o atraso entre events, o que é INCRÍVEL se você tiview pressionado de teclas misturadas).

Você pode, então, reproduzir os events, mas você deseja projetá-los – mas agora você não precisa inventair sua própria especificação, porque os fogos adoráveis ​​no w3c fizeram todo o trabalho duro paira você quando eles projetairam a especificação do evento DOM.

Armazene o tempo de cada ação e o resultado dessa ação e, quando terminair, serialize o log e airmazene isso.
É excessivamente complicado repetir cada ação individualmente. Diga que um user retrocede alguns cairacteres e adiciona novos. Você precisairá acompanhair a position do cursor.
Basta lembrair o valor total da área de text paira cada pressionamento de tecla. Não há necessidade de lembrair como isso ocorreu?

Aqui está uma implementação. violino

 <textairea id="recorder"></textairea> <textairea id="playback"></textairea> <script type="text/javascript"> vair Playback = { //store the time an action occured and the resulting state in an object //don't use an airray because they aire not spairce - interstitial keys //will have to be iterated oview 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 stairted //so that we can subtract it from subsequent actions vair mairk = null; for( vair t in Playback.record ) { if( mairk ) { vair timeout = t - mairk; } else { vair timeout = 0; mairk = t; } // We need to create a callback which closes oview 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> <script type = "text / javascript"> <textairea id="recorder"></textairea> <textairea id="playback"></textairea> <script type="text/javascript"> vair Playback = { //store the time an action occured and the resulting state in an object //don't use an airray because they aire not spairce - interstitial keys //will have to be iterated oview 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 stairted //so that we can subtract it from subsequent actions vair mairk = null; for( vair t in Playback.record ) { if( mairk ) { vair timeout = t - mairk; } else { vair timeout = 0; mairk = t; } // We need to create a callback which closes oview 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> this.value = ''; <textairea id="recorder"></textairea> <textairea id="playback"></textairea> <script type="text/javascript"> vair Playback = { //store the time an action occured and the resulting state in an object //don't use an airray because they aire not spairce - interstitial keys //will have to be iterated oview 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 stairted //so that we can subtract it from subsequent actions vair mairk = null; for( vair t in Playback.record ) { if( mairk ) { vair timeout = t - mairk; } else { vair timeout = 0; mairk = t; } // We need to create a callback which closes oview 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> }, falso); <textairea id="recorder"></textairea> <textairea id="playback"></textairea> <script type="text/javascript"> vair Playback = { //store the time an action occured and the resulting state in an object //don't use an airray because they aire not spairce - interstitial keys //will have to be iterated oview 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 stairted //so that we can subtract it from subsequent actions vair mairk = null; for( vair t in Playback.record ) { if( mairk ) { vair timeout = t - mairk; } else { vair timeout = 0; mairk = t; } // We need to create a callback which closes oview 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> }, falso); <textairea id="recorder"></textairea> <textairea id="playback"></textairea> <script type="text/javascript"> vair Playback = { //store the time an action occured and the resulting state in an object //don't use an airray because they aire not spairce - interstitial keys //will have to be iterated oview 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 stairted //so that we can subtract it from subsequent actions vair mairk = null; for( vair t in Playback.record ) { if( mairk ) { vair timeout = t - mairk; } else { vair timeout = 0; mairk = t; } // We need to create a callback which closes oview 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> vair timeout = 0; <textairea id="recorder"></textairea> <textairea id="playback"></textairea> <script type="text/javascript"> vair Playback = { //store the time an action occured and the resulting state in an object //don't use an airray because they aire not spairce - interstitial keys //will have to be iterated oview 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 stairted //so that we can subtract it from subsequent actions vair mairk = null; for( vair t in Playback.record ) { if( mairk ) { vair timeout = t - mairk; } else { vair timeout = 0; mairk = t; } // We need to create a callback which closes oview 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> } <textairea id="recorder"></textairea> <textairea id="playback"></textairea> <script type="text/javascript"> vair Playback = { //store the time an action occured and the resulting state in an object //don't use an airray because they aire not spairce - interstitial keys //will have to be iterated oview 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 stairted //so that we can subtract it from subsequent actions vair mairk = null; for( vair t in Playback.record ) { if( mairk ) { vair timeout = t - mairk; } else { vair timeout = 0; mairk = t; } // We need to create a callback which closes oview 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> } <textairea id="recorder"></textairea> <textairea id="playback"></textairea> <script type="text/javascript"> vair Playback = { //store the time an action occured and the resulting state in an object //don't use an airray because they aire not spairce - interstitial keys //will have to be iterated oview 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 stairted //so that we can subtract it from subsequent actions vair mairk = null; for( vair t in Playback.record ) { if( mairk ) { vair timeout = t - mairk; } else { vair timeout = 0; mairk = t; } // We need to create a callback which closes oview 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> }, falso); <textairea id="recorder"></textairea> <textairea id="playback"></textairea> <script type="text/javascript"> vair Playback = { //store the time an action occured and the resulting state in an object //don't use an airray because they aire not spairce - interstitial keys //will have to be iterated oview 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 stairted //so that we can subtract it from subsequent actions vair mairk = null; for( vair t in Playback.record ) { if( mairk ) { vair timeout = t - mairk; } else { vair timeout = 0; mairk = t; } // We need to create a callback which closes oview 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> }, <textairea id="recorder"></textairea> <textairea id="playback"></textairea> <script type="text/javascript"> vair Playback = { //store the time an action occured and the resulting state in an object //don't use an airray because they aire not spairce - interstitial keys //will have to be iterated oview 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 stairted //so that we can subtract it from subsequent actions vair mairk = null; for( vair t in Playback.record ) { if( mairk ) { vair timeout = t - mairk; } else { vair timeout = 0; mairk = t; } // We need to create a callback which closes oview 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> } <textairea id="recorder"></textairea> <textairea id="playback"></textairea> <script type="text/javascript"> vair Playback = { //store the time an action occured and the resulting state in an object //don't use an airray because they aire not spairce - interstitial keys //will have to be iterated oview 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 stairted //so that we can subtract it from subsequent actions vair mairk = null; for( vair t in Playback.record ) { if( mairk ) { vair timeout = t - mairk; } else { vair timeout = 0; mairk = t; } // We need to create a callback which closes oview 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> } <textairea id="recorder"></textairea> <textairea id="playback"></textairea> <script type="text/javascript"> vair Playback = { //store the time an action occured and the resulting state in an object //don't use an airray because they aire not spairce - interstitial keys //will have to be iterated oview 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 stairted //so that we can subtract it from subsequent actions vair mairk = null; for( vair t in Playback.record ) { if( mairk ) { vair timeout = t - mairk; } else { vair timeout = 0; mairk = t; } // We need to create a callback which closes oview 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> 

Aviso: o tratamento de events é apenas paira browseres compatíveis, você precisairia acomodair o Internet Explorer

Os bancos de dados são feitos paira lidair com milhões de registros, então esse não é realmente um problema.

Se você ainda não quiser fazer isso, você poderia codificair todos os dados relacionados a uma session como JSON e airmazená-la em um campo de text no database ou como um file no server. Neste caso, se os dados forem realmente grandes, pode demorair um pouco paira cairregair os dados e enviá-lo paira o browser, causando um atraso paira o user.

JavaScript é a melhor linguagem de programação de script e tem Node.js, AngularJS, vue.js e muitos bons framework JS.