录制和重播javascript

Hak*_*kan 9 javascript dom-events

我知道可以记录鼠标移动,滚动和击键.但是对文档的更改呢?如何记录文档的更改?

这是我的尝试.必须有一种更简单的方法来存储所有事件?

我感谢所有我能得到的提示!

<!DOCTYPE html>
<html>
<head>
<title>Record And replay javascript</title>
</head>
<body id="if_no_other_id_exist">

<div style="height:100px;background:#0F0" id="test1">click me</div>
<div style="height:100px;background:#9F9" class="test2">click me</div>
<div style="height:100px;background:#3F9" id="test3">click me</div>
<div style="height:100px;background:#F96" id="test4">click me</div>



<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>

$(document).ready(function() {
var the_time_document_is_redy = new Date().getTime();
var the_replay = '';


$('div').live("click", function (){
var the_length_of_visit = new Date().getTime() - the_time_document_is_redy;


// check if the element that is clicked has an id
if (this.id)
{

the_replay =
the_replay
+
"setTimeout(\"$('#"
+
this.id
+
"').trigger('click')\","
+
the_length_of_visit
+
");"
;


alert (
"The following javascript will be included in the file in the replay version:\n\n"
+ 
the_replay
) // end alert

} // end if



// if it does not have an id, check if the element that is clicked has an class
else if (this.className)
{

// find the closest id to better target the element (needed in my application)
var closest_div_with_id = $(this).closest('[id]').attr('id');

the_replay =
the_replay
+
"setTimeout(\"$('#"
+
closest_div_with_id
+
" ."
+
this.className
+
"').trigger('click')\","
+
the_length_of_visit
+
");"
;


alert (
"The following javascript will be included in the file in the replay version:\n\n"
+ 
the_replay
) // end alert

} // end if

});






// fall back if there are no other id's
$('body').attr('id','if_no_other_id_exist');


// example of how it will work in the replay version
setTimeout("$('#test1').trigger('click')",10000);

});
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

dav*_*ler 20

我对这个问题感到好奇,并在这里实施了一个概念验证

https://jsbin.com/nemake/edit?js,output

使用演示

  • 尝试按录制,单击,再次按录制,然后单击播放.
  • Play创建一个<iframe>,注入原始HTML并重放用户事件.
  • 要更改缩放,请更改REPLAY_SCALE源代码中的变量.
  • 要更改播放速度,请更改SPEED源代码中的变量.
  • NB我只在chrome 56上测试了jsbin.

实施细节:

  • 它支持鼠标移动,单击和键入.我省略了其他(滚动,窗口调整大小,悬停,焦点等),但应该很容易扩展.
  • 事件侦听器event.stopPropagation()在侦听文档上的事件时通过使用捕获来绕过任何事件.
  • 使用zoomCSS3 以不同的分辨率显示回放.
  • 可以覆盖透明画布以绘制鼠标的跟踪线.我只使用一个简单的div,所以没有跟踪线.

注意事项:

  • 想象一下,我们正在真实网站上捕获用户事件.由于所提供的页面可能会在现在和播放之间发生变化,因此在重播iframe中的录制时,我们无法依赖客户端的服务器.相反,我们必须快照html,记录期间发出的所有ajax请求和资源请求.在演示中,我只是为了简单而快照HTML.但实际上,所有额外请求都必须在客户端页面上下载时实时存储在服务器上.此外,在回放期间,重要的是以与用户感知的相同的时间线回放请求.要模拟请求时间线,还必须存储每个请求的偏移量和持续时间.在客户端上下载所有页面请求时,将减慢客户端页面的速度.优化此上载的一种方法可以是在上传请求之前对请求的内容进行md5散列,如果服务器上已经存在md5散列,则不需要重新上载请求数据.此外,一个用户的会话可以利用该散列方法利用另一个用户上传的请求数据.

  • 上传所有活动时需要仔细考虑.由于将生成大量事件,这意味着大量数据.也许可以对事件进行一些压缩,例如丢失一些不那么重要的鼠标移动事件.不应对每个事件发送上载请求以最小化请求数.应该缓冲事件,直到在上载每批事件之前达到缓冲区大小或超时.应该使用超时,因为用户可以在任何时候关闭页面,从而丢失一些事件.

  • 在播放期间,应模拟传出的POST请求以防止在其他地方重复事件.

  • 在回放期间,应该欺骗用户代理,但是在渲染原始显示时这可能是不可靠的.

  • 自定义录制代码可能与客户端代码冲突.例如jquery.命名空间将被要求避免这种情况.

  • 可能存在一些边缘情况,其中键入和单击可能不会再现与原始中相同的结果HTML,例如随机数,日期时间.虽然并非所有浏览器都支持,但可能需要变异观察者观察HTML变化.屏幕截图可能会在这里有用,但可能会证明OTT.


WTK*_*WTK 12

仅使用Javascript重播用户操作是一个复杂的问题.

首先,您无法移动鼠标光标,也无法模拟鼠标悬停/悬停.因此,用户与页面的交互很大程度上消失了.

其次,一旦记录下来的行为,大部分时间都必须在不同的环境中重播,而不是首先记录的.我的意思是您可以使用较小的分辨率,不同的客户端浏览器,基于重播浏览器cookie等的不同内容重播屏幕上的操作.

如果您花时间研究可用于记录网站访问者操作的可用服务(http : //clicktale.com,http://userfly.com/等等),您会发现他们都没有能力完全重放用户操作,特别是涉及mouseovers,ajax,复杂的JS小部件时.

关于你检测DOM变化的问题 - 正如Chris Biscardi在他的回答中所说,有一些突变事件就是为此而设计的.但是,请记住,它们并未在每个浏览器中实现.也就是说,IE不支持它们(根据msdn http://blogs.msdn.com/b/ie/archive/2010/03/26/dom-上的博客条目,它们将在IE 9中得到支持.level-3-events-support-in-ie9.aspx).

根据用例,依赖这些事件可能适合您.

至于" 更好的更简单的方式存储所有事件 ".还有其他方法(语法方面),监听您选择的事件,但是处理(=存储)它们不能以简单的方式处理,除非您想序列化整个事件对象,这不是一个好主意,如果您要将有关这些事件的信息发送到某个服务器来存储它们.您必须意识到这样一个事实,即在使用网站时会出现大量事件,因此需要存储/发送到服务器的大量潜在数据.

我希望我清楚自己,你会发现其中一些信息很有用.我自己参与了旨在做你想要做的事情的项目,所以我知道一旦你开始深入研究这个问题,它会变得多么复杂.


Chr*_*rdi 5

我相信您正在寻找突变事件。

http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-eventgroupings-mutationevents

这里有一些资源供您参考:

http://tobiasz123.wordpress.com/2009/01/19/utilizing-mutation-events-for-automatic-and-persistent-event-attaching/

http://forum.jquery.com/topic/mutation-events-12-1-2010

https://github.com/jollytoad/jquery.mutation-events

更新:

作为对评论的回应,一个非常非常基本的实现:

//callback function
function onNodeInserted(){alert('inserted')}
//add listener to dom(in this case the body tag)
document.body.addEventListener ('DOMNodeInserted', onNodeInserted, false); 
//Add element to dom 
$('<div>test</div>').appendTo('body')
Run Code Online (Sandbox Code Playgroud)

就像 WTK 所说,你正在让自己进入复杂的领域。


Elh*_*les 5

记录

保存页面的初始 DOM,从中删除脚本,并且您还需要将所有相对 URL 更改为绝对 URL。

然后,记录 DOM 突变和键盘/鼠标事件。

重播

从初始保存的 DOM 开始,使用时间戳顺序应用突变和事件。

事实上,点击不会执行任何操作,因为我们已经删除了任何脚本。但因为我们已经保存了 DOM 更改,所以我们可以在单击后重放效果。


Aft*_*eed 5

我在 github 上找到了这两个解决方案,它们允许您捕获事件,然后在远程服务器上重放该事件。

https://github.com/ElliotNB/js-replay

以及更全面的解决方案

https://github.com/rrweb-io/rrweb

https://www.rrweb.io/#demos

两者都有演示,您可以尝试。