~didrocks/+junk/face-detection-15.04

« back to all changes in this revision

Viewing changes to facedetection/www/bower_components/iron-test-helpers/mock-interactions.js

  • Committer: Didier Roche
  • Date: 2016-05-10 23:09:11 UTC
  • Revision ID: didier.roche@canonical.com-20160510230911-c7xr490zrj3yrzxd
New version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @license
 
3
 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
 
4
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 
5
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 
6
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 
7
 * Code distributed by Google as part of the polymer project is also
 
8
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 
9
 */
 
10
 
 
11
(function(global) {
 
12
  'use strict';
 
13
 
 
14
  var HAS_NEW_MOUSE = (function() {
 
15
    var has = false;
 
16
    try {
 
17
      has = Boolean(new MouseEvent('x'));
 
18
    } catch (_) {}
 
19
    return has;
 
20
  })();
 
21
 
 
22
  /**
 
23
   * Returns the (x,y) coordinates representing the middle of a node.
 
24
   *
 
25
   * @param {!HTMLElement} node An element.
 
26
   */
 
27
  function middleOfNode(node) {
 
28
    var bcr = node.getBoundingClientRect();
 
29
    return {
 
30
      y: bcr.top + (bcr.height / 2),
 
31
      x: bcr.left + (bcr.width / 2)
 
32
    };
 
33
  }
 
34
 
 
35
  /**
 
36
   * Returns the (x,y) coordinates representing the top left corner of a node.
 
37
   *
 
38
   * @param {!HTMLElement} node An element.
 
39
   */
 
40
  function topLeftOfNode(node) {
 
41
    var bcr = node.getBoundingClientRect();
 
42
    return {
 
43
      y: bcr.top,
 
44
      x: bcr.left
 
45
    };
 
46
  }
 
47
 
 
48
  /**
 
49
   * Returns a list of Touch objects that correspond to an array of positions
 
50
   * and a target node. The Touch instances will each have a unique Touch
 
51
   * identifier.
 
52
   *
 
53
   * @param {!Array<{ x: number, y: number }>} xyList A list of (x,y) coordinate objects.
 
54
   * @param {!HTMLElement} node A target element node.
 
55
   */
 
56
  function makeTouches(xyList, node) {
 
57
    var id = 0;
 
58
 
 
59
    return xyList.map(function(xy) {
 
60
      var touchInit = {
 
61
        identifier: id++,
 
62
        target: node,
 
63
        clientX: xy.x,
 
64
        clientY: xy.y
 
65
      };
 
66
 
 
67
      return window.Touch ? new window.Touch(touchInit) : touchInit;
 
68
    });
 
69
  }
 
70
 
 
71
  /**
 
72
   * Generates and dispatches a TouchEvent of a given type, at a specified
 
73
   * position of a target node.
 
74
   *
 
75
   * @param {string} type The type of TouchEvent to generate.
 
76
   * @param {{ x: number, y: number }} xy An (x,y) coordinate for the generated
 
77
   * TouchEvent.
 
78
   * @param {!HTMLElement} node The target element node for the generated
 
79
   * TouchEvent to be dispatched on.
 
80
   */
 
81
  function makeSoloTouchEvent(type, xy, node) {
 
82
    xy = xy || middleOfNode(node);
 
83
    var touches = makeTouches([xy], node);
 
84
    var touchEventInit = {
 
85
      touches: touches,
 
86
      targetTouches: touches,
 
87
      changedTouches: touches
 
88
    };
 
89
    var event;
 
90
 
 
91
    if (window.TouchEvent) {
 
92
      event = new TouchEvent(type, touchEventInit);
 
93
    } else {
 
94
      event = new CustomEvent(type, { bubbles: true, cancelable: true });
 
95
      for (var property in touchEventInit) {
 
96
        event[property] = touchEventInit[property];
 
97
      }
 
98
    }
 
99
 
 
100
    node.dispatchEvent(event);
 
101
  }
 
102
 
 
103
  /**
 
104
   * Fires a mouse event on a specific node, at a given set of coordinates.
 
105
   * This event bubbles and is cancellable.
 
106
   *
 
107
   * @param {string} type The type of mouse event (such as 'tap' or 'down').
 
108
   * @param {{ x: number, y: number }} xy The (x,y) coordinates the mouse event should be fired from.
 
109
   * @param {!HTMLElement} node The node to fire the event on.
 
110
   */
 
111
  function makeMouseEvent(type, xy, node) {
 
112
    var props = {
 
113
      bubbles: true,
 
114
      cancelable: true,
 
115
      clientX: xy.x,
 
116
      clientY: xy.y,
 
117
      // Make this a primary input.
 
118
      buttons: 1 // http://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
 
119
    };
 
120
    var e;
 
121
    if (HAS_NEW_MOUSE) {
 
122
      e = new MouseEvent(type, props);
 
123
    } else {
 
124
      e = document.createEvent('MouseEvent');
 
125
      e.initMouseEvent(
 
126
        type, props.bubbles, props.cancelable,
 
127
        null, /* view */
 
128
        null, /* detail */
 
129
        0,    /* screenX */
 
130
        0,    /* screenY */
 
131
        props.clientX, props.clientY,
 
132
        false, /*ctrlKey */
 
133
        false, /*altKey */
 
134
        false, /*shiftKey */
 
135
        false, /*metaKey */
 
136
        0,     /*button */
 
137
        null   /*relatedTarget*/);
 
138
    }
 
139
    node.dispatchEvent(e);
 
140
  }
 
141
 
 
142
  /**
 
143
   * Simulates a mouse move action by firing a `move` mouse event on a
 
144
   * specific node, between a set of coordinates.
 
145
   *
 
146
   * @param {!HTMLElement} node The node to fire the event on.
 
147
   * @param {Object} fromXY The (x,y) coordinates the dragging should start from.
 
148
   * @param {Object} toXY The (x,y) coordinates the dragging should end at.
 
149
   * @param {?number} steps Optional. The numbers of steps in the move motion.
 
150
   *    If not specified, the default is 5.
 
151
   */
 
152
  function move(node, fromXY, toXY, steps) {
 
153
    steps = steps || 5;
 
154
    var dx = Math.round((fromXY.x - toXY.x) / steps);
 
155
    var dy = Math.round((fromXY.y - toXY.y) / steps);
 
156
    var xy = {
 
157
      x: fromXY.x,
 
158
      y: fromXY.y
 
159
    };
 
160
    for (var i = steps; i > 0; i--) {
 
161
      makeMouseEvent('mousemove', xy, node);
 
162
      xy.x += dx;
 
163
      xy.y += dy;
 
164
    }
 
165
    makeMouseEvent('mousemove', {
 
166
      x: toXY.x,
 
167
      y: toXY.y
 
168
    }, node);
 
169
  }
 
170
 
 
171
  /**
 
172
   * Simulates a mouse dragging action originating in the middle of a specific node.
 
173
   *
 
174
   * @param {!HTMLElement} target The node to fire the event on.
 
175
   * @param {?number} dx The horizontal displacement.
 
176
   * @param {?number} dy The vertical displacement
 
177
   * @param {?number} steps Optional. The numbers of steps in the dragging motion.
 
178
   *    If not specified, the default is 5.
 
179
   */
 
180
  function track(target, dx, dy, steps) {
 
181
    dx = dx | 0;
 
182
    dy = dy | 0;
 
183
    steps = steps || 5;
 
184
    down(target);
 
185
    var xy = middleOfNode(target);
 
186
    var xy2 = {
 
187
      x: xy.x + dx,
 
188
      y: xy.y + dy
 
189
    };
 
190
    move(target, xy, xy2, steps);
 
191
    up(target, xy2);
 
192
  }
 
193
 
 
194
  /**
 
195
   * Fires a `down` mouse event on a specific node, at a given set of coordinates.
 
196
   * This event bubbles and is cancellable. If the (x,y) coordinates are
 
197
   * not specified, the middle of the node will be used instead.
 
198
   *
 
199
   * @param {!HTMLElement} node The node to fire the event on.
 
200
   * @param {{ x: number, y: number }=} xy Optional. The (x,y) coordinates the mouse event should be fired from.
 
201
   */
 
202
  function down(node, xy) {
 
203
    xy = xy || middleOfNode(node);
 
204
    makeMouseEvent('mousedown', xy, node);
 
205
  }
 
206
 
 
207
  /**
 
208
   * Fires an `up` mouse event on a specific node, at a given set of coordinates.
 
209
   * This event bubbles and is cancellable. If the (x,y) coordinates are
 
210
   * not specified, the middle of the node will be used instead.
 
211
   *
 
212
   * @param {!HTMLElement} node The node to fire the event on.
 
213
   * @param {{ x: number, y: number }=} xy Optional. The (x,y) coordinates the mouse event should be fired from.
 
214
   */
 
215
  function up(node, xy) {
 
216
    xy = xy || middleOfNode(node);
 
217
    makeMouseEvent('mouseup', xy, node);
 
218
  }
 
219
 
 
220
  /**
 
221
   * Generate a click event on a given node, optionally at a given coordinate.
 
222
   * @param {!HTMLElement} node The node to fire the click event on.
 
223
   * @param {{ x: number, y: number }=} xy Optional. The (x,y) coordinates the mouse event should
 
224
   * be fired from.
 
225
   */
 
226
  function click(node, xy) {
 
227
    xy = xy || middleOfNode(node);
 
228
    makeMouseEvent('click', xy, node);
 
229
  }
 
230
 
 
231
  /**
 
232
   * Generate a touchstart event on a given node, optionally at a given coordinate.
 
233
   * @param {!HTMLElement} node The node to fire the click event on.
 
234
   * @param {{ x: number, y: number }=} xy Optional. The (x,y) coordinates the touch event should
 
235
   * be fired from.
 
236
   */
 
237
  function touchstart(node, xy) {
 
238
    xy = xy || middleOfNode(node);
 
239
    makeSoloTouchEvent('touchstart', xy, node);
 
240
  }
 
241
 
 
242
 
 
243
  /**
 
244
   * Generate a touchend event on a given node, optionally at a given coordinate.
 
245
   * @param {!HTMLElement} node The node to fire the click event on.
 
246
   * @param {{ x: number, y: number }=} xy Optional. The (x,y) coordinates the touch event should
 
247
   * be fired from.
 
248
   */
 
249
  function touchend(node, xy) {
 
250
    xy = xy || middleOfNode(node);
 
251
    makeSoloTouchEvent('touchend', xy, node);
 
252
  }
 
253
 
 
254
  /**
 
255
   * Simulates a complete mouse click by firing a `down` mouse event, followed
 
256
   * by an asynchronous `up` and `tap` events on a specific node. Calls the
 
257
   *`callback` after the `tap` event is fired.
 
258
   *
 
259
   * @param {!HTMLElement} target The node to fire the event on.
 
260
   * @param {?Function} callback Optional. The function to be called after the action ends.
 
261
   * @param {?{
 
262
   *   emulateTouch: boolean
 
263
   * }} options Optional. Configure the emulation fidelity of the mouse events.
 
264
   */
 
265
  function downAndUp(target, callback, options) {
 
266
    if (options && options.emulateTouch) {
 
267
      touchstart(target);
 
268
      touchend(target);
 
269
    }
 
270
 
 
271
    down(target);
 
272
    Polymer.Base.async(function() {
 
273
      up(target);
 
274
      click(target);
 
275
      callback && callback();
 
276
    });
 
277
  }
 
278
 
 
279
  /**
 
280
   * Fires a 'tap' mouse event on a specific node. This respects the pointer-events
 
281
   * set on the node, and will not fire on disabled nodes.
 
282
   *
 
283
   * @param {!HTMLElement} node The node to fire the event on.
 
284
   * @param {?{
 
285
   *   emulateTouch: boolean
 
286
   * }} options Optional. Configure the emulation fidelity of the mouse event.
 
287
   */
 
288
  function tap(node, options) {
 
289
    // Respect nodes that are disabled in the UI.
 
290
    if (window.getComputedStyle(node)['pointer-events'] === 'none')
 
291
      return;
 
292
 
 
293
    var xy = middleOfNode(node);
 
294
 
 
295
    if (options && options.emulateTouch) {
 
296
      touchstart(node, xy);
 
297
      touchend(node, xy);
 
298
    }
 
299
 
 
300
    down(node, xy);
 
301
    up(node, xy);
 
302
    click(node, xy);
 
303
  }
 
304
 
 
305
  /**
 
306
   * Focuses a node by firing a `focus` event. This event does not bubble.
 
307
   *
 
308
   * @param {!HTMLElement} target The node to fire the event on.
 
309
   */
 
310
  function focus(target) {
 
311
    Polymer.Base.fire('focus', {}, {
 
312
      bubbles: false,
 
313
      node: target
 
314
    });
 
315
  }
 
316
 
 
317
  /**
 
318
   * Blurs a node by firing a `blur` event. This event does not bubble.
 
319
   *
 
320
   * @param {!HTMLElement} target The node to fire the event on.
 
321
   */
 
322
  function blur(target) {
 
323
    Polymer.Base.fire('blur', {}, {
 
324
      bubbles: false,
 
325
      node: target
 
326
    });
 
327
  }
 
328
 
 
329
  /**
 
330
   * Returns a keyboard event. This event bubbles and is cancellable.
 
331
   *
 
332
   * @param {string} type The type of keyboard event (such as 'keyup' or 'keydown').
 
333
   * @param {number} keyCode The keyCode for the event.
 
334
   * @param {(string|Array<string>)=} modifiers The key modifiers for the event.
 
335
   *     Accepted values are shift, ctrl, alt, meta.
 
336
   * @param {string=} key The KeyboardEvent.key value for the event.
 
337
   */
 
338
  function keyboardEventFor(type, keyCode, modifiers, key) {
 
339
    var event = new CustomEvent(type, {
 
340
      bubbles: true,
 
341
      cancelable: true
 
342
    });
 
343
 
 
344
    event.keyCode = keyCode;
 
345
    event.code = keyCode;
 
346
 
 
347
    modifiers = modifiers || [];
 
348
    if (typeof modifiers === 'string') {
 
349
      modifiers = [modifiers];
 
350
    }
 
351
    event.shiftKey = modifiers.indexOf('shift') !== -1;
 
352
    event.altKey = modifiers.indexOf('alt') !== -1;
 
353
    event.ctrlKey = modifiers.indexOf('ctrl') !== -1;
 
354
    event.metaKey = modifiers.indexOf('meta') !== -1;
 
355
 
 
356
    event.key = key;
 
357
 
 
358
    return event;
 
359
  }
 
360
 
 
361
  /**
 
362
   * Fires a keyboard event on a specific node. This event bubbles and is cancellable.
 
363
   *
 
364
   * @param {!HTMLElement} target The node to fire the event on.
 
365
   * @param {string} type The type of keyboard event (such as 'keyup' or 'keydown').
 
366
   * @param {number} keyCode The keyCode for the event.
 
367
   * @param {(string|Array<string>)=} modifiers The key modifiers for the event.
 
368
   *     Accepted values are shift, ctrl, alt, meta.
 
369
   * @param {string=} key The KeyboardEvent.key value for the event.
 
370
   */
 
371
  function keyEventOn(target, type, keyCode, modifiers, key) {
 
372
    target.dispatchEvent(keyboardEventFor(type, keyCode, modifiers, key));
 
373
  }
 
374
 
 
375
  /**
 
376
   * Fires a 'keydown' event on a specific node. This event bubbles and is cancellable.
 
377
   *
 
378
   * @param {!HTMLElement} target The node to fire the event on.
 
379
   * @param {number} keyCode The keyCode for the event.
 
380
   * @param {(string|Array<string>)=} modifiers The key modifiers for the event.
 
381
   *     Accepted values are shift, ctrl, alt, meta.
 
382
   * @param {string=} key The KeyboardEvent.key value for the event.
 
383
   */
 
384
  function keyDownOn(target, keyCode, modifiers, key) {
 
385
    keyEventOn(target, 'keydown', keyCode, modifiers, key);
 
386
  }
 
387
 
 
388
  /**
 
389
   * Fires a 'keyup' event on a specific node. This event bubbles and is cancellable.
 
390
   *
 
391
   * @param {!HTMLElement} target The node to fire the event on.
 
392
   * @param {number} keyCode The keyCode for the event.
 
393
   * @param {(string|Array<string>)=} modifiers The key modifiers for the event.
 
394
   *     Accepted values are shift, ctrl, alt, meta.
 
395
   * @param {string=} key The KeyboardEvent.key value for the event.
 
396
   */
 
397
  function keyUpOn(target, keyCode, modifiers, key) {
 
398
    keyEventOn(target, 'keyup', keyCode, modifiers, key);
 
399
  }
 
400
 
 
401
  /**
 
402
   * Simulates a complete key press by firing a `keydown` keyboard event, followed
 
403
   * by an asynchronous `keyup` event on a specific node.
 
404
   *
 
405
   * @param {!HTMLElement} target The node to fire the event on.
 
406
   * @param {number} keyCode The keyCode for the event.
 
407
   * @param {(string|Array<string>)=} modifiers The key modifiers for the event.
 
408
   *     Accepted values are shift, ctrl, alt, meta.
 
409
   * @param {string=} key The KeyboardEvent.key value for the event.
 
410
   */
 
411
  function pressAndReleaseKeyOn(target, keyCode, modifiers, key) {
 
412
    keyDownOn(target, keyCode, modifiers, key);
 
413
    Polymer.Base.async(function() {
 
414
      keyUpOn(target, keyCode, modifiers, key);
 
415
    }, 1);
 
416
  }
 
417
 
 
418
  /**
 
419
   * Simulates a complete 'enter' key press by firing a `keydown` keyboard event,
 
420
   * followed by an asynchronous `keyup` event on a specific node.
 
421
   *
 
422
   * @param {!HTMLElement} target The node to fire the event on.
 
423
   */
 
424
  function pressEnter(target) {
 
425
    pressAndReleaseKeyOn(target, 13);
 
426
  }
 
427
 
 
428
  /**
 
429
   * Simulates a complete 'space' key press by firing a `keydown` keyboard event,
 
430
   * followed by an asynchronous `keyup` event on a specific node.
 
431
   *
 
432
   * @param {!HTMLElement} target The node to fire the event on.
 
433
   */
 
434
  function pressSpace(target) {
 
435
    pressAndReleaseKeyOn(target, 32);
 
436
  }
 
437
 
 
438
  global.MockInteractions = {
 
439
    focus: focus,
 
440
    blur: blur,
 
441
    down: down,
 
442
    up: up,
 
443
    downAndUp: downAndUp,
 
444
    tap: tap,
 
445
    track: track,
 
446
    pressAndReleaseKeyOn: pressAndReleaseKeyOn,
 
447
    pressEnter: pressEnter,
 
448
    pressSpace: pressSpace,
 
449
    keyDownOn: keyDownOn,
 
450
    keyUpOn: keyUpOn,
 
451
    keyboardEventFor: keyboardEventFor,
 
452
    keyEventOn: keyEventOn,
 
453
    middleOfNode: middleOfNode,
 
454
    topLeftOfNode: topLeftOfNode
 
455
  };
 
456
})(this);