Changeset 944 for trunk/autoquest-htmlmonitor
- Timestamp:
- 10/26/12 09:17:48 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/autoquest-htmlmonitor/src/main/js/autoquest-htmlmonitor.js
r937 r944 56 56 */ 57 57 var autoquestActionConfig = [ 58 { "tag": "body", "actions": [ "onunload", "onscroll" ] }, 59 { "tag": "a", "actions": [ "onclick", "ondblclick", "onfocus" ] }, 60 { "tag": "input", "actions": [ "onclick", "ondblclick", "onfocus" ] } 58 { "tag": "a", "actions": [ "onclick", 59 "onfocus" ] }, 60 //{ "tag": "abbr", "actions": [ ] }, 61 //{ "tag": "address", "actions": [ ] }, 62 //{ "tag": "applet", "actions": [ ] }, 63 { "tag": "area", "actions": [ "onclick", 64 "onfocus" ] }, 65 //{ "tag": "article", "actions": [ ] }, 66 //{ "tag": "aside", "actions": [ ] }, 67 { "tag": "audio", "actions": [ "onplaying", 68 "onpause", 69 "ontimeupdate" ] }, 70 { "tag": "b", "actions": [ "onclick" ] }, 71 //{ "tag": "bdi", "actions": [ ] }, 72 //{ "tag": "bdo", "actions": [ ] }, 73 //{ "tag": "blockquote", "actions": [ ] }, 74 { "tag": "body", "actions": [ "onbeforeunload", 75 "onunload", 76 //"onerror", 77 "onscroll", 78 "onpagehide", 79 "onpageshow", 80 "onundo" ] }, 81 { "tag": "button", "actions": [ "onclick", 82 "onfocus" ] }, 83 { "tag": "canvas", "actions": [ "onclick" ] }, 84 //{ "tag": "caption", "actions": [ ] }, 85 { "tag": "cite", "actions": [ "onclick" ] }, 86 { "tag": "code", "actions": [ "onclick" ] }, 87 //{ "tag": "col", "actions": [ ] }, 88 //{ "tag": "colgroup", "actions": [ ] }, 89 { "tag": "command", "actions": [ "onclick", 90 "onfocus" ] }, 91 //{ "tag": "datalist", "actions": [ ] }, 92 { "tag": "dd", "actions": [ "onclick" ] }, 93 { "tag": "del", "actions": [ "onclick" ] }, 94 //{ "tag": "details", "actions": [ ] }, 95 { "tag": "dfn", "actions": [ "onclick" ] }, 96 { "tag": "div", "actions": [ "onclick" ] }, 97 //{ "tag": "dl", "actions": [ ] }, 98 { "tag": "dt", "actions": [ "onclick" ] }, 99 { "tag": "em", "actions": [ "onclick" ] }, 100 { "tag": "embed", "actions": [ "onclick" ] }, 101 //{ "tag": "fieldset", "actions": [ ] }, 102 //{ "tag": "figcaption", "actions": [ ] }, 103 //{ "tag": "figure", "actions": [ ] }, 104 //{ "tag": "footer", "actions": [ ] }, 105 //{ "tag": "form", "actions": [ ] }, 106 //{ "tag": "header", "actions": [ ] }, 107 //{ "tag": "hgroup", "actions": [ ] }, 108 { "tag": "h1", "actions": [ "onclick" ] }, 109 { "tag": "h2", "actions": [ "onclick" ] }, 110 { "tag": "h3", "actions": [ "onclick" ] }, 111 { "tag": "h4", "actions": [ "onclick" ] }, 112 { "tag": "h5", "actions": [ "onclick" ] }, 113 { "tag": "h6", "actions": [ "onclick" ] }, 114 //{ "tag": "hr", "actions": [ ] }, 115 { "tag": "i", "actions": [ "onclick" ] }, 116 //{ "tag": "iframe", "actions": [ ] }, 117 { "tag": "img", "actions": [ "onclick" ] }, 118 { "tag": "input_text", "actions": [ "onchange", 119 "onfocus" ] }, 120 { "tag": "input", "actions": [ "onchange", 121 "onfocus" ] }, 122 { "tag": "ins", "actions": [ "onclick" ] }, 123 { "tag": "kbd", "actions": [ "onclick" ] }, 124 { "tag": "keygen", "actions": [ "onchange", 125 "onfocus" ] }, 126 //{ "tag": "label", "actions": [ ] }, 127 //{ "tag": "legend", "actions": [ ] }, 128 { "tag": "li", "actions": [ "onclick" ] }, 129 //{ "tag": "map", "actions": [ ] }, 130 { "tag": "mark", "actions": [ "onclick" ] }, 131 { "tag": "menu", "actions": [ "onclick" ] }, 132 { "tag": "meter", "actions": [ "onclick" ] }, 133 //{ "tag": "nav", "actions": [ ] }, 134 //{ "tag": "noscript", "actions": [ ] }, 135 { "tag": "object", "actions": [ "onclick" ] }, 136 //{ "tag": "ol", "actions": [ ] }, 137 //{ "tag": "optgroup", "actions": [ ] }, 138 //{ "tag": "option", "actions": [ ] }, 139 { "tag": "output", "actions": [ "onclick" ] }, 140 { "tag": "p", "actions": [ "onclick" ] }, 141 //{ "tag": "param", "actions": [ ] }, 142 //{ "tag": "pre", "actions": [ ] }, 143 { "tag": "progress", "actions": [ "onclick" ] }, 144 { "tag": "q", "actions": [ "onclick" ] }, 145 //{ "tag": "rp", "actions": [ ] }, 146 //{ "tag": "rt", "actions": [ ] }, 147 //{ "tag": "ruby", "actions": [ ] }, 148 { "tag": "s", "actions": [ "onclick" ] }, 149 { "tag": "samp", "actions": [ "onclick" ] }, 150 //{ "tag": "section", "actions": [ ] }, 151 { "tag": "select", "actions": [ "onchange", 152 "onfocus" ] }, 153 { "tag": "small", "actions": [ "onclick" ] }, 154 //{ "tag": "source", "actions": [ ] }, 155 { "tag": "span", "actions": [ "onclick" ] }, 156 { "tag": "strong", "actions": [ "onclick" ] }, 157 //{ "tag": "sub", "actions": [ ] }, 158 //{ "tag": "summary", "actions": [ ] }, 159 //{ "tag": "sup", "actions": [ ] }, 160 //{ "tag": "table", "actions": [ ] }, 161 //{ "tag": "tbody", "actions": [ ] }, 162 { "tag": "td", "actions": [ "onclick" ] }, 163 { "tag": "textarea", "actions": [ "onchange", 164 "onfocus" ] }, 165 //{ "tag": "tfoot", "actions": [ ] }, 166 { "tag": "th", "actions": [ "onclick" ] }, 167 //{ "tag": "thead", "actions": [ ] }, 168 { "tag": "time", "actions": [ "onclick" ] }, 169 //{ "tag": "tr", "actions": [ ] }, 170 //{ "tag": "track", "actions": [ ] }, 171 { "tag": "u", "actions": [ "onclick" ] }, 172 //{ "tag": "ul", "actions": [ ] }, 173 { "tag": "var", "actions": [ "onclick" ] }, 174 { "tag": "video", "actions": [ "onplaying", 175 "onpause", 176 "ontimeupdate" ] }, 177 //{ "tag": "wbr", "actions": [ ] }, 61 178 ]; 62 179 … … 139 256 */ 140 257 function addEventHandlingAttributes(node, parentPath) { 141 var nodePath = getNodePath(node, parentPath);258 var nodePath; 142 259 var i; 143 260 var k; … … 145 262 146 263 if (node.nodeType === Node.ELEMENT_NODE) { 264 nodePath = getNodePath(node, parentPath); 265 147 266 for (i = 0; i < autoquestActionConfig.length; i++) { 148 if ( node.tagName.toLowerCase() === autoquestActionConfig[i].tag.toLowerCase()) {267 if (getTagName(node) === autoquestActionConfig[i].tag.toLowerCase()) { 149 268 for (k = 0; k < autoquestActionConfig[i].actions.length; k++) { 150 value = "handleEvent('" + autoquestActionConfig[i].actions[k] + "', '" + 151 nodePath + "', event);"; 269 value = "handleEvent(this, '" + 270 autoquestActionConfig[i].actions[k] + "', '" + 271 nodePath + "', event);"; 152 272 153 273 if (!node.getAttribute(autoquestActionConfig[i].actions[k])) { … … 164 284 } 165 285 } 166 }167 168 for (i = 0; i < node.childNodes.length; i++) {169 addEventHandlingAttributes(node.childNodes[i], nodePath);286 287 for (i = 0; i < node.childNodes.length; i++) { 288 addEventHandlingAttributes(node.childNodes[i], nodePath); 289 } 170 290 } 171 291 } … … 174 294 * generates a path through the DOM-structure of the HTML-site depending on a node and the path 175 295 * to its parent node. The result is the parent path plus a path element for the provided node. 176 * If the node has a tag name, this is the first part of the path element generated for the node.177 * If the node has an id, it becomes the second part of the path element. If the node does not have178 * an id, the method calculates the index of the node within all children of the same type within179 * the parent node. This index becomes then the second part of the path element generated for the180 * node.296 * The first part of the path element generated for the node is the tag name returned by 297 * {@link #getTagName(node)}. If the node has an id, it becomes the second part of the path 298 * element. If the node does not have an id, the method calculates the index of the node within 299 * all children of the same type within the parent node. This index becomes then the second part 300 * of the path element generated for the node. 181 301 * 182 302 * @param node the node of the DOM structure for which the path shall be created … … 191 311 var i = 0; 192 312 193 if (node.nodeType === Node.ELEMENT_NODE) { 194 nodePath += node.tagName.toLowerCase(); 195 196 if ("input" === node.tagName.toLowerCase()) { 197 if (node.type && (node.type !== "")) { 198 nodePath += "_" + node.type; 199 } 200 else { 201 nodePath += "_text"; 202 } 203 } 204 } 205 else { 206 nodePath += "undefined"; 207 } 313 nodePath += getTagName(node); 208 314 209 315 if ((node.id) && (node.id !== "")) { … … 211 317 } 212 318 else { 213 214 319 if (node.parentNode) { 215 320 for (i = 0; i < node.parentNode.childNodes.length; i++) { … … 239 344 * of the nodes. These attributes are generated by the 240 345 * {@link #addEventHandlingAttributes(node,parentPath)} function. It creates a new Event object and 241 * add it to the list of <code>autoquestRecordedEvents</code>. If this list achieves the maximum346 * adds it to the list of <code>autoquestRecordedEvents</code>. If this list achieves the maximum 242 347 * <code>autoquestPackageSize</code> the events in the list are sent to the server asynchronously 243 348 * through calling {@link #sendRequest()}. 244 349 * 350 * @param node the node that fired the event 245 351 * @param eventName the name of the event, e.g. onscroll 246 352 * @param nodePath the path to the node in the HTML DOM on which the event occurred 247 353 * @param event the HTML event that occured 248 354 */ 249 function handleEvent(eventName, nodePath, event) { 250 log("handling event " + eventName); 251 355 function handleEvent(node, eventName, nodePath, event) { 356 var eventType; 357 var eventObj = null; 358 var tagName; 359 252 360 if (!autoquestDestination) { 253 361 // do nothing if we have no destination to send data to … … 255 363 } 256 364 257 var eventType = eventName.toLowerCase(); 258 259 var eventObj = autoquestRecordedEvents.pop(); 260 261 // reuse previous on scroll events to prevent too many events 262 if ((eventName !== "onscroll") || (!eventObj) || (eventObj.type !== "onscroll")) { 263 if (eventObj) { 264 autoquestRecordedEvents.push(eventObj); 265 } 365 log("handling event " + eventName + " on " + node); 366 367 eventType = eventName.toLowerCase(); 368 369 if (autoquestRecordedEvents.length > 0) { 370 eventObj = autoquestRecordedEvents[autoquestRecordedEvents.length - 1]; 371 372 // check if an event showed up several times either for the same or for a parent GUI element 373 if ((eventObj.type === eventName) && (eventObj.nodePath.indexOf(nodePath) === 0)) { 374 // the event is of the same type. 375 if (eventObj.nodePath.length > nodePath.length) { 376 // the same event showed up for the parent GUI element. This must not be handled. 377 // So ignore it 378 log("discarding event " + eventName + " on " + node + 379 " as it is already handled by a child"); 380 return; 381 } 382 else if (eventName !== "onscroll") { 383 // we have the same event on the same element. If it is an onscroll, we should 384 // reuse it. But it is not an onscroll. So we ignore the existing event. 385 eventObj = null; 386 } 387 } 388 else { 389 // the event is not of an equal type as the previous one. So we will not reuse it 390 eventObj = null; 391 } 392 } 393 394 if (!eventObj) { 395 // create a new event and add it to the list 266 396 eventObj = new Event(eventType, nodePath); 267 } 268 397 log("storing event " + eventName); 398 autoquestRecordedEvents.push(eventObj); 399 } 400 401 // now add further event parameters 269 402 if ((eventType === "onclick") || (eventType === "ondblclick")) { 270 403 eventObj.setClickCoordinates(getEventCoordinates(event)); 271 404 } 272 405 273 if ((eventType === "onkeypress") || (eventType === "onkeydown") || (eventType === "onkeyup")) { 274 eventObj.setKey(event.keyCode); 406 tagName = getTagName(node); 407 408 if ("input_password" !== tagName) { 409 if ((eventType === "onkeypress") || 410 (eventType === "onkeydown") || 411 (eventType === "onkeyup")) 412 { 413 eventObj.setKey(event.keyCode); 414 } 415 else if (eventType == "onchange") { 416 if ((tagName.indexOf("input") === 0) || 417 (tagName === "textarea") || 418 (tagName === "keygen")) 419 { 420 eventObj.setSelectedValue(node.value); 421 } 422 else if (tagName === "select") { 423 eventObj.setSelectedValue(node.options.item(node.options.selectedIndex)); 424 } 425 } 275 426 } 276 427 277 428 if (eventType === "onscroll") { 278 if (window.pageYOffset) { 279 eventObj.setScrollPosition(window.pageYOffset); 280 } 281 } 282 283 log("storing event " + eventName); 284 autoquestRecordedEvents.push(eventObj); 429 eventObj.setScrollPosition(getScrollCoordinates(node)); 430 } 285 431 286 432 if (autoquestRecordedEvents.length >= autoquestPackageSize) { … … 295 441 } 296 442 443 /** 444 * determines a tag name of a node. If the node is an input element, the tag name includes the 445 * type of element. Otherwise the method simply returns the tag name. 446 * 447 * @param node the node for which the name must be determined 448 * 449 * @return the name as described 450 */ 451 function getTagName(node) { 452 var tagName = null; 453 454 if (node.tagName) { 455 tagName = node.tagName.toLowerCase(); 456 if ("input" === tagName) { 457 if (node.type && (node.type !== "")) { 458 tagName += "_" + node.type; 459 } 460 else { 461 tagName += "_text"; 462 } 463 } 464 } 465 466 return tagName; 467 } 468 297 469 /** 298 470 * sends the collected data to the server, named in the destination-variable. For this it generates … … 310 482 log("creating message"); 311 483 eventList = autoquestRecordedEvents; 312 autoquestRecordedEvents = []; 484 485 // put the last event into the new list to allow for checks for reoccurence of the same 486 // event 487 autoquestRecordedEvents = [ eventList.pop() ]; 313 488 314 489 message = "{\"message\":{\"clientInfos\":{"; … … 354 529 request.send(message); 355 530 } 531 } 532 533 /** 534 * determines the scroll coordinates of the scrolled element 535 * 536 * @param node the element that was scrolled 537 * 538 * @returns the coordinates of the scrolling as an array with x and y coordinate 539 */ 540 function getScrollCoordinates(node) { 541 if (node.scrollLeft || node.scrollTop) { 542 return [node.scrollLeft, node.scrollTop]; 543 } 544 else if ((node === window) && window.pageYOffset) { 545 return [window.pageXOffset, window.pageYOffset]; 546 } 547 else if ((node == document) || (node == document.body) || (node == document.documentElement)) { 548 if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 549 return [document.body.scrollLeft, document.body.scrollTop]; 550 } 551 else if (document.documentElement && 552 (document.documentElement.scrollLeft || document.documentElement.scrollTop)) 553 { 554 return [document.documentElement.scrollLeft, document.documentElement.scrollTop]; 555 } 556 } 557 558 return [-1, -1]; 356 559 } 357 560 … … 478 681 }; 479 682 683 this.setSelectedValue = function(value) { 684 this.selectedValue = value; 685 }; 686 480 687 this.setScrollPosition = function(scrollPosition) { 481 688 this.scrollPosition = scrollPosition; 482 689 }; 483 690 … … 495 702 } 496 703 497 if (this.scrollPosition) { 498 eventInJSON += ",\"scrollPosition\":" + this.scrollPosition; 704 if (this.selectedValue) { 705 eventInJSON += ",\"selectedValue\":\"" + this.selectedValue + "\""; 706 } 707 708 if ("onscroll" === this.type) { 709 eventInJSON += ",\"scrollPosition\":[" + this.scrollPosition + "]"; 499 710 } 500 711
Note: See TracChangeset
for help on using the changeset viewer.