Как я могу воздействовать на активность курсора, происходящую от щелчков мыши, а не от действий клавиатуры?

Я хочу что-то сделать, когда пользователь перемещает курсор в другое место с помощью щелчка мыши, но не делает этого, когда это делается с помощью действия клавиатуры (стрелки, pageup/pagedown, home/end).

  • Я не могу просто слушать cursorActivity, так как он запускается как для действий клавиатуры, так и для мыши.
  • Я не уверен, что могу слушать mousedown, потому что это может быть начало чего-то, что не является изменением местоположения курсора (например, выбор, перетаскивание).

Какой лучший способ поймать эти движки курсора мыши?

Ответ 1

Вы можете прослушивать эти события:

  • MouseDown
  • cursorActivity
  • KeyDown
  • beforeChange

Курсор перемещался щелчком мыши, если эти условия выполняются:

  • Событие cursorActivity запускается после события mousedown
  • Между двумя событиями не было нажата клавиша перемещения.
  • Никаких изменений в содержании между этими двумя событиями не было.
  • Текст не выбран

var movedByMouse = false;

var editor = CodeMirror(document.body);

editor.on("mousedown", function () {
    movedByMouse = true;
});

editor.on("cursorActivity", function () {
    if (movedByMouse) {
        movedByMouse = false;
        if (!editor.getSelection()) {
            console.log("Moved by mouse");
        }
    }
});

editor.on("keydown", function () {
    if (isMovementKey(event.which)) {
        movedByMouse = false;
    }
});

editor.on("beforeChange", function () {
    movedByMouse = false;
});

function isMovementKey(keyCode) {
    return 33 <= keyCode && keyCode <= 40;
};
<link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.20.2/codemirror.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.20.2/codemirror.min.js"></script>

Ответ 2

Все события мыши (что я знаю):

  • OnClick
  • oncontextmenu
  • ondbclick
  • OnMouseDown
  • OnMouseEnter
  • OnMouseLeave
  • OnMouseMove
  • OnMouseOver
  • onmouseout
  • OnMouseUp

Итак, в принципе, нет решения для вашей проблемы, что в javascript AFAIK. Тем не менее, вы можете пойти со своим вторым предложением и отслеживать события и в зависимости от них выбрать, выполнять ли это действие или нет.

var editorElement = document.body;
var codeMirror = CodeMirror(editorElement);
var mouseEvents = [
  'click',
  'contextmenu',
  'dbclick',
  'mousedown',
  'mouseenter',
  'mouseleave',
  'mousemove',
  'mouseover',
  'mouseout',
  'mouseup'
];
var mouseEventsLog = [];
var lastCursorPosition = null;
var doAction = function() {
  var previousEvent = mouseEventsLog[mouseEventsLog.length - 2];
  var lastEvent = mouseEventsLog[mouseEventsLog.length - 1];

  if (((previousEvent === 'mousedown' && lastEvent === 'mouseup') || lastEvent === 'click') &&codeMirror.getSelection().length <= 0) {
    if (codeMirror.getCursor() !== lastCursorPosition) {
      console.log('Cursor changed by clicking.');
    }
  }

  lastCursorPosition = codeMirror.getCursor();
};
for (var i = 0; i < mouseEvents.length; i++) {
  editorElement.addEventListener(mouseEvents[i], function(event) {
    mouseEventsLog.push(event.type);
    if (event.type == 'mouseup') {
      doAction();
    }
  }, false);
}
<script src="https://codemirror.net/lib/codemirror.js"></script>
<script src="http://codemirror.net/mode/javascript/javascript.js"></script>
<link href="https://codemirror.net/lib/codemirror.css" rel="stylesheet"/>

Ответ 3

Вы можете подключиться к CodeMirror, используя крючок, и определить свое собственное событие, которое срабатывает, когда курсор меняется с мыши, нажимайте на редактор

CodeMirror.defineInitHook(function (editor) {
    editor.cursorDidChange = false;
    $(editor.getWrapperElement()).on({
        mousedown : function() {
            if (editor.cursorDidChange) CodeMirror.signal(editor, 'cursorClick');
        },
        mouseup : function() {
            editor.cursorDidChange = false;
        }
    });
    editor.on('cursorActivity', function(e) {
        if (e.isSelection) editor.cursorDidChange = true;
    });
    editor.on('beforeSelectionChange', function(e, range) {
        var start = range.ranges[0].anchor, end = range.ranges[0].head;
        e.isSelection = range.origin == '*mouse' && start.line == end.line && start.ch == end.ch;
    })
});

Это использует флаг и таймер, чтобы поймать оба события, если они произойдут в течение короткого времени друг от друга, поскольку обработчик клика срабатывает сразу после обработчика cursorActivity.

Вот рабочий пример того, как использовать вновь определенное событие с CodeMirror:

/* Create Hook */
CodeMirror.defineInitHook(function (editor) {
	editor.cursorDidChange = false;
	$(editor.getWrapperElement()).on({
    	mousedown : function() {
            if (editor.cursorDidChange) CodeMirror.signal(editor, 'cursorClick');
        },
        mouseup : function() {
            editor.cursorDidChange = false;
        }
    });
    editor.on('cursorActivity', function(e) {
    	if (e.isSelection) editor.cursorDidChange = true;
    });
    editor.on('beforeSelectionChange', function(e, range) {
        var start = range.ranges[0].anchor, end = range.ranges[0].head;
        e.isSelection = range.origin == '*mouse' && start.line == end.line && start.ch == end.ch;
    })
});
/* -------------- */
/* Create an editor to test it */

var $this = $('.code').eq(0),
    $code = $this.html(),
    $unescaped = $('<div/>').html($code).text();
        
$this.empty();
    
var editor = CodeMirror($this.get(0), {
    value       : $unescaped,
    mode        : 'javascript',
    lineNumbers : true,
    readOnly    : false
});

/* Lets test out the new event */
editor.on('cursorClick', function() {
	$('<div />', {text : 'Cursor moved when clicked !'}).appendTo('#result')
        .show(1).delay(1000).fadeOut(function() {
         	$(this).remove();
        });
});
body {background: #eee;}
.code {margin: 10px 0;}
#result {color: green;}
.CodeMirror {height: auto!important;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://codemirror.net/lib/codemirror.js"></script>
<script src="https://codemirror.net/mode/javascript/javascript.js"></script>
<link href="#" onclick="location.href='https://codemirror.net/lib/codemirror.css'; return false;" rel="stylesheet"/>
<!-- EDITOR -->
<div class="code">test.fn = test.prototype = {
    display : function() {}
        console.log("Move cursor by clicking");
        console.log("Move cursor with keys");
    },
	pushStack: function( elems ) {
		// This is just pseudocode to have something to test
	}
    return false;
}</div>
<!-- EDITOR END -->
<div id="result"></div>