产品原型
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

478 lines
19 KiB

4 years ago
  1. // use this to isolate the scope
  2. (function() {
  3. if(!$axure.document.configuration.showRecordPlay) { return; }
  4. $(window.document).ready(function() {
  5. $axure.player.createPluginHost({
  6. id: 'recordPlayHost',
  7. context: 'interface',
  8. title: 'Recording'
  9. });
  10. _generateRecordPlay();
  11. $('#recordButton').click(_recordClick);
  12. $('#playButton').click(_playClick);
  13. $('#stopButton').click(_stopClick);
  14. $('#deleteButton').click(_deleteClick);
  15. // bind to the page load
  16. $axure.page.bind('load.page_notes', function() {
  17. $.ajax({
  18. type: "POST",
  19. url: '/RecordController/ListRecordings',
  20. success: function(response) {
  21. $('#recordNameHeader').html("");
  22. $('#recordPlayContent').html("");
  23. //populate the notes
  24. axRecordingList = [];
  25. if(!eventList) {
  26. recordingIndex = 0;
  27. eventList = [];
  28. recordingStartTime = 0;
  29. bulkEventElement = "";
  30. lastBulkEvent = {};
  31. }
  32. for(var idx in response.recordingList) {
  33. getOneRecording(response.recordingList[idx]);
  34. }
  35. return false;
  36. },
  37. // dataType: 'json'
  38. });
  39. });
  40. });
  41. var nameMatcher = new RegExp("^axRecording[0-9]{4}$", "i");
  42. var indexMatcher = new RegExp("[0-9]{4}$", "i");
  43. var convertFromJson = function(oneRecording) {
  44. if(nameMatcher.exec(oneRecording.recordingName)) {
  45. var myArray = indexMatcher.exec(oneRecording.recordingName);
  46. var currIdx = parseInt(myArray);
  47. if(recordingIndex < currIdx) {
  48. recordingIndex = currIdx;
  49. }
  50. }
  51. for(var idx in oneRecording.eventList) {
  52. var thisEvent = oneRecording.eventList[idx];
  53. thisEvent.eventInfo = {};
  54. thisEvent.eventInfo.srcElement = thisEvent.elementID;
  55. // TODO: check that this is correct.
  56. if(isBulkMouse(thisEvent.eventType)) {
  57. thisEvent.eventInfo.mousePositions = [];
  58. thisEvent.eventInfo.mousePositions = thisEvent.mousePositions;
  59. thisEvent.timeStamp = thisEvent.mousePositions[0].timeStamp;
  60. }
  61. if(isSingleMouse(thisEvent.eventType)) {
  62. thisEvent.eventInfo.cursor = {};
  63. thisEvent.eventInfo.cursor = thisEvent.cursor;
  64. }
  65. if(thisEvent.eventType === 'OnDrag') {
  66. thisEvent.eventInfo.dragInfo = {};
  67. thisEvent.eventInfo.dragInfo = thisEvent.dragInfo;
  68. thisEvent.timeStamp = thisEvent.dragInfo.startTime;
  69. }
  70. }
  71. return oneRecording;
  72. };
  73. var getOneRecording = function(recordingItem) {
  74. $.ajax({
  75. type: "POST",
  76. url: '/RecordController/GetRecording',
  77. data: { 'recordingId': recordingItem.recordingId },
  78. success: function(response) {
  79. axRecordingList[axRecordingList.length] = convertFromJson(response);
  80. var axRecordingContainer = $('#recordingContainer').find('li').filter('.recordingRootNode');
  81. axRecordingContainer.append(_formAxRecordingBranch(response));
  82. _attachEventTriggers(response);
  83. }, // dataType: 'json'
  84. });
  85. };
  86. var axRecordingList;
  87. var eventList;
  88. var recordingIndex;
  89. var recordingStartTime;
  90. var recordingId;
  91. var recordingName;
  92. var leadingZeros = function(number, digits) { // because this thing doesn't have string.format (or does it?)
  93. var recurseLeadingZeros = function(number, digitsLeft) {
  94. if(digitsLeft > 0) {
  95. return recurseLeadingZeros("0" + number, digitsLeft - 1);
  96. } else {
  97. return number;
  98. }
  99. };
  100. return recurseLeadingZeros(number, digits - String(number).length);
  101. };
  102. var generateRecordingName = function() {
  103. return "axRecording" + leadingZeros(recordingIndex, 4);
  104. };
  105. var isSingleMouse = function(eventType) {
  106. return (eventType === 'OnClick' ||
  107. eventType === 'OnMouseUp' ||
  108. eventType === 'OnMouseDown' ||
  109. eventType === 'OnMouseOver' ||
  110. eventType === 'OnKeyUp' ||
  111. eventType === 'OnSelectedChange' ||
  112. eventType === 'OnSelect' ||
  113. eventType === 'OnUnselect' ||
  114. eventType === 'OnTextChange' ||
  115. eventType === 'OnMouseOut');
  116. };
  117. var isBulkMouse = function(eventType) {
  118. return (eventType === 'OnMouseHover' ||
  119. eventType === 'OnMouseMove');
  120. };
  121. var bulkEventElement;
  122. var lastBulkEvent;
  123. $axure.messageCenter.addMessageListener(function(message, eventData) {
  124. var lastEvent, lastBulkData;
  125. if(message === 'logEvent') {
  126. if(bulkEventElement !== eventData.elementID) {
  127. lastBulkEvent = {};
  128. bulkEventElement = eventData.elementID;
  129. }
  130. if(isBulkMouse(eventData.eventType)) {
  131. lastEvent = lastBulkEvent[eventData.eventType];
  132. if(lastEvent) {
  133. // this is the second or third or whatever onmousemove in a row
  134. lastBulkData = lastEvent.eventInfo.mousePositions;
  135. lastBulkData[lastBulkData.length] = {
  136. cursor: eventData.eventInfo.cursor,
  137. timeStamp: eventData.timeStamp
  138. };
  139. } else {
  140. eventData.eventInfo.mousePositions = [];
  141. eventData.eventInfo.mousePositions[0] = {
  142. cursor: eventData.eventInfo.cursor,
  143. timeStamp: eventData.timeStamp
  144. };
  145. eventList[eventList.length] = eventData;
  146. lastBulkEvent[eventData.eventType] = eventData;
  147. }
  148. } else {
  149. var z = true;
  150. }
  151. if(isSingleMouse(eventData.eventType) ) {
  152. eventList[eventList.length] = eventData;
  153. lastBulkEvent = {};
  154. bulkEventElement = eventData.elementID;
  155. }
  156. if(eventData.eventType === 'OnDrag') {
  157. lastEvent = lastBulkEvent[eventData.eventType];
  158. if (lastEvent) {
  159. // this is the second or third or whatever onmousemove in a row
  160. lastBulkData = lastEvent.eventInfo.mousePositions;
  161. lastBulkData[lastBulkData.length] = {
  162. dragInfo: eventData.eventInfo.dragInfo,
  163. timeStamp: eventData.timeStamp
  164. };
  165. } else {
  166. eventData.eventInfo.mousePositions = [];
  167. eventData.eventInfo.mousePositions[0] = {
  168. dragInfo: eventData.eventInfo.dragInfo,
  169. timeStamp: eventData.timeStamp
  170. };
  171. eventList[eventList.length] = eventData;
  172. lastBulkEvent[eventData.eventType] = eventData;
  173. }
  174. }
  175. // if(eventData.eventType === 'OnKeyUp') {
  176. // transmissionFields.eventInfo = eventData.eventInfo;
  177. // $.ajax({
  178. // type: "POST",
  179. // url: '/RecordController/LogMouseClick',
  180. // data: transmissionFields,
  181. // });
  182. // }
  183. }
  184. });
  185. var _recordClick = function(event) {
  186. $('#recordButton').addClass('recordPlayButtonSelected');
  187. recordingIndex++;
  188. // $axure.recording.startRecord();
  189. recordingStartTime = new Date().getTime();
  190. $.ajax({
  191. type: "POST",
  192. url: '/RecordController/CreateRecording',
  193. data: {
  194. 'recordingName': generateRecordingName(),
  195. timeStamp: recordingStartTime
  196. },
  197. success: function(response) {
  198. recordingId = response.recordingId;
  199. recordingName = response.recordingName;
  200. $axure.messageCenter.postMessage('startRecording', {'recordingId' : recordingId, 'recordingName': recordingName});
  201. },
  202. // dataType: 'json'
  203. });
  204. };
  205. var _playClick = function(event) {
  206. $('#playButton').addClass('recordPlayButtonSelected');
  207. };
  208. var _stopClick = function(event) {
  209. var axRecording, axObjectDictionary, axRecordingContainer, transmissionFields;
  210. $('#sitemapLinksContainer').toggle();
  211. if($('#recordButton').is('.recordPlayButtonSelected')) {
  212. $('#recordButton').removeClass('recordPlayButtonSelected');
  213. // $axure.recording.stopRecord();
  214. axRecording = {
  215. 'recordingId' : recordingId,
  216. 'recordingName': recordingName,
  217. 'eventList': eventList
  218. };
  219. axRecordingList[axRecordingList.length] = axRecording;
  220. axRecordingContainer = $('#recordingContainer').find('li').filter('.recordingRootNode');
  221. axRecordingContainer.append(_formAxRecordingBranch(axRecording));
  222. _attachEventTriggers(axRecording);
  223. lastBulkEvent = {};
  224. var recordingStepList = [];
  225. for(var eventListIdx in eventList) {
  226. var eventListItem = eventList[eventListIdx];
  227. if(eventListItem.eventType === 'OnDrag') {
  228. var lastDrag = eventListItem.eventInfo.mousePositions[eventListItem.eventInfo.mousePositions.length - 1].dragInfo;
  229. eventListItem.eventInfo.dragInfo.currentX = lastDrag.currentX;
  230. eventListItem.eventInfo.dragInfo.currentY = lastDrag.currentY;
  231. eventListItem.eventInfo.dragInfo.currentTime = lastDrag.currentTime;
  232. eventListItem.eventInfo.dragInfo.xDelta = eventListItem.eventInfo.dragInfo.currentX - eventListItem.eventInfo.dragInfo.lastX;
  233. eventListItem.eventInfo.dragInfo.yDelta = eventListItem.eventInfo.dragInfo.currentY - eventListItem.eventInfo.dragInfo.lastY;
  234. transmissionFields = {};
  235. transmissionFields = tackItOn(transmissionFields, eventListItem, ['eventType', 'elementID', 'path']);
  236. transmissionFields = tackItOn(transmissionFields, eventListItem.eventInfo, ['dragInfo']);
  237. transmissionFields.recordingId = recordingId;
  238. }
  239. if(isSingleMouse(eventListItem.eventType)) {
  240. transmissionFields = {};
  241. transmissionFields = tackItOn(transmissionFields, eventListItem, ['timeStamp', 'eventType', 'elementID', 'path']);
  242. transmissionFields = tackItOn(transmissionFields, eventListItem.eventInfo, ['cursor']);
  243. transmissionFields.recordingId = recordingId;
  244. }
  245. if(isBulkMouse(eventListItem.eventType)) {
  246. transmissionFields = {};
  247. transmissionFields = tackItOn(transmissionFields, eventListItem, ['eventType', 'elementID', 'path']);
  248. transmissionFields = tackItOn(transmissionFields, eventListItem.eventInfo, ['mousePositions']);
  249. transmissionFields.recordingId = recordingId;
  250. }
  251. recordingStepList[recordingStepList.length] = transmissionFields;
  252. }
  253. eventList = [];
  254. $axure.messageCenter.postMessage('stopRecording', axObjectDictionary);
  255. var jsonText = {
  256. 'recordingName': recordingName,
  257. 'recordingId': recordingId,
  258. recordingStart: new Date().getTime(),
  259. recordingEnd: recordingStartTime,
  260. 'eventList': recordingStepList
  261. };
  262. $.ajax({
  263. type: "POST",
  264. url: '/RecordController/StopRecording',
  265. data: { 'jsonText': JSON.stringify(jsonText) }
  266. });
  267. }
  268. if($('#playButton').is('.recordPlayButtonSelected')) {
  269. $('#playButton').removeClass('recordPlayButtonSelected');
  270. }
  271. };
  272. var _deleteClick = function(event) {
  273. $.ajax({
  274. type: "POST",
  275. url: '/RecordController/DeleteRecordings',
  276. success: function(response) {
  277. var x = true;
  278. }, // dataType: 'json'
  279. });
  280. };
  281. var tackItOn = function(destination, source, fields) {
  282. for(var idx in fields) {
  283. destination[fields[idx]] = source[fields[idx]];
  284. }
  285. return destination;
  286. };
  287. var makeFirstLetterLower = function(eventName) {
  288. return eventName.substr(0, 1).toLowerCase() + eventName.substr(1);
  289. };
  290. var _attachEventTriggers = function(axRecording) {
  291. for(var eventIdx in axRecording.eventList) {
  292. var eventObject = axRecording.eventList[eventIdx];
  293. var eventID = axRecording['recordingId'] + '_' + eventObject.timeStamp;
  294. currentEvent = eventID;
  295. $('#' + eventID).click(_triggerEvent(axRecording['recordingId'], eventObject.timeStamp));
  296. // $('#' + eventID).click(event.trigger);
  297. }
  298. };
  299. var _formAxRecordingBranch = function(axRecording) {
  300. var eventObject, eventID, RDOID;
  301. var recordPlayUi = '<ul class="recordingTree">';
  302. recordPlayUi += "<li class='recordingNode recordingExpandableNode'>";
  303. recordPlayUi += '<div class="recordingContainer" style="margin-left:15px">';
  304. recordPlayUi += '<a class="recordingPlusMinusLink"><span class="recordingMinus"></span></a>';
  305. recordPlayUi += '<a class="recordingPageLink" nodeurl="home.html">';
  306. recordPlayUi += '<span class="recordingPageIcon"></span>';
  307. recordPlayUi += '<span class="recordingPageName">' + axRecording['recordingName'] + '</span>';
  308. recordPlayUi += '</a>';
  309. recordPlayUi += '<ul>';
  310. for(eventID in axRecording.eventList) {
  311. eventObject = axRecording.eventList[eventID];
  312. recordPlayUi += '<li class="recordingNode recordingLeafNode">';
  313. recordPlayUi += '<div class="recordingEventContainer" style="margin-left:44px">';
  314. var eventID = axRecording['recordingId'] + '_' + eventObject.timeStamp;
  315. recordPlayUi += '<a id="' + eventID + '" class="sitemapPageLink">';
  316. recordPlayUi += 'Event ID: ' + eventID + '<br/>';
  317. recordPlayUi += '<span class="sitemapPageIcon"></span>';
  318. recordPlayUi += '<span class="sitemapPageName">';
  319. recordPlayUi += 'elementID: ' + eventObject.elementID + '<br/>';
  320. recordPlayUi += 'eventType: ' + eventObject.eventType + '<br/>';
  321. // recordPlayUi += 'cursor: ' + eventObject.eventInfo.cursor.x + ',' + eventObject.eventInfo.cursor.y + '<br/>';
  322. for(RDOID in eventObject.path) {
  323. recordPlayUi += '/' + eventObject.path[RDOID];
  324. }
  325. recordPlayUi += '<br/>';
  326. recordPlayUi += '</span>';
  327. recordPlayUi += '</a>';
  328. recordPlayUi += '</div>';
  329. recordPlayUi += '</li>';
  330. }
  331. recordPlayUi += '</ul>';
  332. recordPlayUi += '</div>';
  333. recordPlayUi += "</li>";
  334. recordPlayUi += "</ul>";
  335. return recordPlayUi;
  336. };
  337. var currentEvent = '';
  338. var _triggerEvent = function(axRecording, timeStamp) {
  339. // $axure.messageCenter.postMessage('triggerEvent', false);
  340. for(var axRecordingIdx in axRecordingList) {
  341. if(axRecordingList[axRecordingIdx].recordingId === axRecording) {
  342. for(var eventIdx in axRecordingList[axRecordingIdx].eventList) {
  343. if(axRecordingList[axRecordingIdx].eventList[eventIdx].timeStamp === timeStamp) {
  344. var thisEvent = axRecordingList[axRecordingIdx].eventList[eventIdx];
  345. // thisEvent.trigger();
  346. var thisEventInfo, lowerEventType;
  347. lowerEventType = thisEvent.eventType.toLowerCase();
  348. if(lowerEventType === 'onclick' || lowerEventType === 'onmousein') {
  349. thisEventInfo = {};
  350. thisEventInfo = tackItOn(thisEventInfo, thisEvent.eventInfo, ['cursor', 'timeStamp', 'srcElement']);
  351. if(thisEvent.eventInfo.inputType) {
  352. thisEventInfo = tackItOn(thisEventInfo, thisEvent.eventInfo, ['inputType', 'inputValue']);
  353. }
  354. } else {
  355. thisEventInfo = thisEvent.eventInfo;
  356. }
  357. var thisParameters = {
  358. 'element': thisEvent.elementID,
  359. 'eventInfo': thisEventInfo,
  360. // 'axEventObject': thisEvent.eventObject,
  361. 'eventType': thisEvent.eventType
  362. };
  363. return function() {
  364. $axure.messageCenter.postMessage('playEvent', thisParameters);
  365. };
  366. }
  367. }
  368. }
  369. }
  370. };
  371. var _generateRecordPlay = function() {
  372. var recordPlayUi = "<div id='recordPlayContainer'>";
  373. recordPlayUi += "<div id='recordPlayToolbar'>";
  374. recordPlayUi += "<div style='height:30px;'>";
  375. recordPlayUi += "<a id='recordButton' title='Start a Recording' class='recordPlayButton'></a>";
  376. recordPlayUi += "<a id='playButton' title='Play Back a Recording' class='recordPlayButton'></a>";
  377. recordPlayUi += "<a id='stopButton' title='Stop' class='recordPlayButton'></a>";
  378. recordPlayUi += "<a id='deleteButton' title='Delete All Recordings' class='recordPlayButton'></a>";
  379. recordPlayUi += "</div>";
  380. recordPlayUi += "<div id='recordingContainer'><li class='recordingNode recordingRootNode'></li></div>";
  381. recordPlayUi += "</div>";
  382. $('#recordPlayHost').html(recordPlayUi);
  383. };
  384. })();