(cm)
| 3417 | |
| 3418 | // Attach the necessary event handlers when initializing the editor |
| 3419 | function registerEventHandlers(cm) { |
| 3420 | var d = cm.display; |
| 3421 | on(d.scroller, "mousedown", operation(cm, onMouseDown)); |
| 3422 | // Older IE's will not fire a second mousedown for a double click |
| 3423 | if (ie && ie_version < 11) |
| 3424 | on(d.scroller, "dblclick", operation(cm, function(e) { |
| 3425 | if (signalDOMEvent(cm, e)) return; |
| 3426 | var pos = posFromMouse(cm, e); |
| 3427 | if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return; |
| 3428 | e_preventDefault(e); |
| 3429 | var word = cm.findWordAt(pos); |
| 3430 | extendSelection(cm.doc, word.anchor, word.head); |
| 3431 | })); |
| 3432 | else |
| 3433 | on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); }); |
| 3434 | // Some browsers fire contextmenu *after* opening the menu, at |
| 3435 | // which point we can't mess with it anymore. Context menu is |
| 3436 | // handled in onMouseDown for these browsers. |
| 3437 | if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);}); |
| 3438 | |
| 3439 | // Used to suppress mouse event handling when a touch happens |
| 3440 | var touchFinished, prevTouch = {end: 0}; |
| 3441 | function finishTouch() { |
| 3442 | if (d.activeTouch) { |
| 3443 | touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000); |
| 3444 | prevTouch = d.activeTouch; |
| 3445 | prevTouch.end = +new Date; |
| 3446 | } |
| 3447 | }; |
| 3448 | function isMouseLikeTouchEvent(e) { |
| 3449 | if (e.touches.length != 1) return false; |
| 3450 | var touch = e.touches[0]; |
| 3451 | return touch.radiusX <= 1 && touch.radiusY <= 1; |
| 3452 | } |
| 3453 | function farAway(touch, other) { |
| 3454 | if (other.left == null) return true; |
| 3455 | var dx = other.left - touch.left, dy = other.top - touch.top; |
| 3456 | return dx * dx + dy * dy > 20 * 20; |
| 3457 | } |
| 3458 | on(d.scroller, "touchstart", function(e) { |
| 3459 | if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) { |
| 3460 | clearTimeout(touchFinished); |
| 3461 | var now = +new Date; |
| 3462 | d.activeTouch = {start: now, moved: false, |
| 3463 | prev: now - prevTouch.end <= 300 ? prevTouch : null}; |
| 3464 | if (e.touches.length == 1) { |
| 3465 | d.activeTouch.left = e.touches[0].pageX; |
| 3466 | d.activeTouch.top = e.touches[0].pageY; |
| 3467 | } |
| 3468 | } |
| 3469 | }); |
| 3470 | on(d.scroller, "touchmove", function() { |
| 3471 | if (d.activeTouch) d.activeTouch.moved = true; |
| 3472 | }); |
| 3473 | on(d.scroller, "touchend", function(e) { |
| 3474 | var touch = d.activeTouch; |
| 3475 | if (touch && !eventInWidget(d, e) && touch.left != null && |
| 3476 | !touch.moved && new Date - touch.start < 300) { |
no test coverage detected