forked from marmelab/gremlins.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
clicker.js
136 lines (122 loc) · 5.25 KB
/
clicker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/**
* The clicker gremlin clicks anywhere on the visible area of the document
*
* The clicker gremlin triggers mouse events (click, dblclick, mousedown,
* mouseup, mouseover, mouseover, mouseover, mousemove, and mouseout) on
* random targets displayed on the viewport.
*
* By default, the clicker gremlin activity is showed by a red circle.
*
* var clickerGremlin = gremlins.species.clicker();
* horde.gremlin(clickerGremlin);
*
* The clicker gremlin can be customized as follows:
*
* clickerGremlin.clickTypes(['click', 'mouseover']); // the mouse event types to trigger
* clickerGremlin.positionSelector(function() { // find a random pair of coordinates to click });
* clickerGremlin.showAction(function(x, y) { // show the gremlin activity on screen });
* clickerGremlin.canClick(function(element) { return true }); // to limit where the gremlin can click
* clickerGremlin.maxNbTries(5); // How many times the gremlin must look for a clickable element before quitting
* clickerGremlin.logger(loggerObject); // inject a logger
* clickerGremlin.randomizer(randomizerObject); // inject a randomizer
*
* Example usage:
*
* horde.gremlin(gremlins.species.clicker()
* .clickTypes(['click'])
* .positionSelector(function() {
* // only click inside the foo element area
* var $el = $('#foo');
* var offset = $el.offset();
* return [
* parseInt(Math.random() * $el.outerWidth() + offset.left),
* parseInt(Math.random() * $el.outerHeight() + offset.top)
* ];
* })
* .canClick(function(element) {
* // only click elements in bar
* return $(element).parents('#bar').length;
* // when canClick returns false, the gremlin will look for another
* // element to click on until maxNbTries is reached
* })
* . showAction(function(x, y) {
* // do nothing (hide the gremlin action on screen)
* })
* );
*/
define(function(require) {
"use strict";
var configurable = require('../utils/configurable');
var Chance = require('../vendor/chance');
return function() {
var document = window.document,
body = document.body;
var defaultClickTypes = ['click', 'click', 'click', 'click', 'click', 'click', 'dblclick', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseover', 'mouseover', 'mousemove', 'mouseout'];
var defaultPositionSelector = function() {
return [
config.randomizer.natural({ max: document.documentElement.clientWidth - 1 }),
config.randomizer.natural({ max: document.documentElement.clientHeight - 1 })
];
};
var defaultShowAction = function(x, y) {
var clickSignal = document.createElement('div');
clickSignal.style.border = "3px solid red";
clickSignal.style['border-radius'] = '50%';
clickSignal.style.width = "40px";
clickSignal.style.height = "40px";
clickSignal.style['box-sizing'] = 'border-box';
clickSignal.style.position = "absolute";
clickSignal.style.webkitTransition = 'opacity 1s ease-out';
clickSignal.style.mozTransition = 'opacity 1s ease-out';
clickSignal.style.transition = 'opacity 1s ease-out';
clickSignal.style.left = (x - 20 ) + 'px';
clickSignal.style.top = (y - 20 )+ 'px';
var element = body.appendChild(clickSignal);
setTimeout(function() {
body.removeChild(element);
}, 1000);
setTimeout(function() {
element.style.opacity = 0;
}, 50);
};
var defaultCanClick = function() { return true; };
/**
* @mixin
*/
var config = {
clickTypes: defaultClickTypes,
positionSelector: defaultPositionSelector,
showAction: defaultShowAction,
canClick: defaultCanClick,
maxNbTries: 10,
logger: {},
randomizer: new Chance()
};
/**
* @mixes config
*/
function clickerGremlin() {
var position, posX, posY, targetElement, nbTries = 0;
do {
position = config.positionSelector();
posX = position[0];
posY = position[1];
targetElement = document.elementFromPoint(posX, posY);
nbTries++;
if (nbTries > config.maxNbTries) return false;
} while (!targetElement || !config.canClick(targetElement));
var evt = document.createEvent("MouseEvents");
var clickType = config.randomizer.pick(config.clickTypes);
evt.initMouseEvent(clickType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
targetElement.dispatchEvent(evt);
if (typeof config.showAction == 'function') {
config.showAction(posX, posY, clickType);
}
if (typeof config.logger.log == 'function') {
config.logger.log('gremlin', 'clicker ', clickType, 'at', posX, posY);
}
}
configurable(clickerGremlin, config);
return clickerGremlin;
};
});