2016-10-27 2 views
11

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

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

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

+0

'пользователь перемещает курсор в другое место с помощью click' мыши вы можете объяснить эту часть ? –

+1

@ Иванка Тодорова Если из тегов не ясно: это вопрос о [редакторе CodeMirror] (https://codemirror.net/). Под «другим местоположением» я подразумеваю, что пользователь меняет текущее местоположение курсора, щелкая мышью по тексту в редакторе. – Oak

+0

Можете ли вы опубликовать текущую настройку редактора codemirror? –

ответ

6

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

  • 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>

+0

Функция «cursorActivity» запускается при нажатии клавиши клавиатуры. Ваш 'keyUpHandler' устанавливает' moveByMouse' в true, когда человек вводит что-либо в редактор. –

+0

@ Иванка Тодорова - Очень хорошая точка. – ConnorsFan

+0

Я обновил фрагмент кода для учета движений курсора, вызванных изменениями, внесенными в контент (например, при вводе текста). – ConnorsFan

4

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

  • 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"/>

Примечание: Я попытался объединения cursorActivity и события мыши, но cursorActivity выполняется перед ними? Я на самом деле не уверен, что там происходит = D

+1

Благодарим за решение! На поверхности он работает хорошо, хотя это условие в doAction() не кажется очень надежным. Например, если пользователь переместил мышь немного между событием mousedown и mouseup, но недостаточно, чтобы инициировать выбор - он не будет запускаться. Кроме того, бит 'codeMirror.getSelection(). Length <= 0' означает, что если есть выбранная область, а затем пользователь щелкает за пределами этой области, этот клик не будет считаться. – Oak

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) { 
 
\t editor.cursorDidChange = false; 
 
\t $(editor.getWrapperElement()).on({ 
 
    \t mousedown : function() { 
 
      if (editor.cursorDidChange) CodeMirror.signal(editor, 'cursorClick'); 
 
     }, 
 
     mouseup : function() { 
 
      editor.cursorDidChange = false; 
 
     } 
 
    }); 
 
    editor.on('cursorActivity', function(e) { 
 
    \t 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() { 
 
\t $('<div />', {text : 'Cursor moved when clicked !'}).appendTo('#result') 
 
     .show(1).delay(1000).fadeOut(function() { 
 
      \t $(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="https://codemirror.net/lib/codemirror.css" rel="stylesheet"/> 
 
<!-- EDITOR --> 
 
<div class="code">test.fn = test.prototype = { 
 
    display : function() {} 
 
     console.log("Move cursor by clicking"); 
 
     console.log("Move cursor with keys"); 
 
    }, 
 
\t pushStack: function(elems) { 
 
\t \t // This is just pseudocode to have something to test 
 
\t } 
 
    return false; 
 
}</div> 
 
<!-- EDITOR END --> 
 
<div id="result"></div>

+0

Спасибо за ответ! Отличный и очень аккуратный подход с определением нового события. Кажется, что он не срабатывает, хотя время между мышами и мышью составляет более 300 мс, так как mousedown - это тот, который вызывает изменение курсора, а mouseup запускает onclick.Кроме того, ваше решение рассмотрит двойное или тройное нажатие, чтобы выбрать как 2 или 3 отдельных события cursorClick, даже если все клики выполняются в конце диапазона, чтобы курсор не менял технически местоположение. – Oak

+0

@Oak - Тогда, я думаю, мне придется немного изменить подход, сбросить таймер и вместо этого проверить выборки и т. Д. Посмотрите, что это решает что угодно. – adeneo

+0

Лучше! К сожалению, теперь он также запускается при запуске выбора, хотя, если честно, это технически, изменение местоположения курсора. – Oak

Смежные вопросы