2011-11-09 10 views
5

Me gustaría poder grabar y reproducir lo que sucedió en un área de texto.¿Cómo registrar eficientemente la escritura de usuario utilizando javascript?

He encontrado algunas soluciones pero no son confiables, como enviar cada pulsación de tecla a través de AJAX. En ese caso, tendré millones de filas en mi base de datos.

La idea que tenía en mente es registrar las teclas a una variable en el lado del cliente, actualizando esa variable con la acción, pero haciendo un seguimiento del tiempo entre cada keytoke. También asegurándose de que también sea compatible con la eliminación de datos.

Al final enviaría toda esta variable al db una vez, luego puedo decodificarla más tarde para la reproducción.

mapa mental de lo que la variable se vería así:

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

creo que Google Docs está haciendo algo por el estilo para reproducir lo usuarios estaban escribiendo.

alguna idea?

Respuesta

9

Por suerte, los eventos de JavaScript ya se ocupan de todos los problemas de codificación para usted. Puede simplemente tirar el objeto de evento completo que una tecla/tecla/tecla/lo que sea estaba directamente en una matriz.

Cada objeto contiene:

  • Tipo de evento
  • Marca de tiempo
  • qué clave se utiliza (o combinación de teclas)
  • Lo que estaba en el foco
  • Algunas otras cosas que podría terminar siendo útil.

Puede codificar la matriz y enviarla con su método favorito de ajax al servidor para su almacenamiento.

Por lo tanto, su código solo necesita una función que pueda almacenar datos. No use esta función exacta, es sólo para fines de demostración.

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); 

Ya que es una matriz, todos ellos deben estar en orden, pero en el caso extraño que goofs, tiene datos de fecha y hora en cada caso (que también le permite conocer el tiempo transcurrido entre eventos, que es IMPRESIONANTE si tiene teclas pulsadas).

Luego puede reproducir eventos como usted quiera diseñarlos, pero ahora no tiene que inventar sus propias especificaciones porque los encantadores ataques de w3c hicieron todo el trabajo por usted cuando diseñaron las especificaciones de eventos DOM.

+0

me gusta su respuesta, muy claro y en el punto, me había olvidado de la serialización de una matriz de JavaScript de eventos. +1 – Ryan

+0

Gracias @Ryan me alegra que lo haya encontrado útil. – Incognito

+0

Estoy tratando de desencadenar el evento usando: '$ ('# playback'). Trigger (e);' pero no escribe el carácter, supongo que solo activa la función de devolución de llamada, ¿Alguna idea? y ¿cómo te acerca el movimiento del cursor con el mouse? – Ryan

0

Las bases de datos están hechas para manejar millones de registros, por lo que no es realmente un problema.

Si aún no quiere hacer eso, podría codificar todos los datos relacionados con una sesión como JSON y almacenarlos en un campo de texto en la base de datos o como un archivo en el servidor. En este caso, si los datos son realmente grandes, puede llevar un tiempo cargar los datos y enviarlos al navegador, lo que ocasiona un retraso para el usuario.

+0

NO están hechos para manejar millones de consultas ajax, al menos mis servidores. +1 por abusar de internet con solicitudes inútiles. – Ryan

+0

Definitivamente no haría una solicitud para que cada evento se registre. Muchos eventos se pueden enviar juntos en cada solicitud. –

4

Almacene la hora de cada acción y el resultado de esa acción, y cuando termine de serializar el registro y almacenarlo.
Es demasiado complicado reproducir cada acción individualmente. Digamos que un usuario retrocede algunos caracteres y agrega nuevos allí. Tendrá que hacer un seguimiento de la posición del cursor.
Simplemente recuerde el valor completo del área de texto para cada pulsación de tecla. No hay necesidad de recordar cómo ocurrió eso?

Aquí hay una implementación. 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> 

Advertencia: El manejo de eventos es sólo para los navegadores compatibles, que había necesidad de dar cabida a Internet Explorer mismo

+1

Gracias @meouw, parece ser una alternativa rápida y sucia, me gusta también pero requiere mucho más almacenamiento porque cuando el valor de la tabla de texto se hace más grande, se duplica cada vez más hasta que se convierte en un gran archivo de 200 MB después de un tiempo de escribir: D – Ryan

Cuestiones relacionadas