2016-10-27 15 views
11

Chcę coś zrobić, gdy użytkownik przesunie kursor w inne miejsce za pomocą kliknięcia myszą, ale nie zrobi tego, gdy zrobi to za pomocą akcji klawiatury (strzałki, strona/strona, strona główna/koniec).Jak mogę reagować na ruchy kursora na podstawie kliknięć myszy, a nie na klawiaturę?

  • Nie mogę po prostu słuchać cursorActivity, ponieważ uruchamia się zarówno na klawiaturze, jak i na myszach.
  • Nie jestem pewien, czy mogę odsłuchać mousedown, ponieważ może to być początek czegoś, co nie jest zmianą położenia kursora (na przykład wybranie, przeciągnięcie).

Jaki jest najlepszy sposób na wychwycenie ruchów kursora pochodzących od myszy?

+0

'użytkownik przesuwa kursor do innej lokalizacji za pośrednictwem click' myszy można wyjaśnić tę część ? –

+1

@IvankaTodorova Jeśli nie jest to jasne z tagów: jest to pytanie dotyczące edytora CodeMirror (https://codemirror.net/). Przez "inną lokalizację" rozumiem, że użytkownik zmienia bieżącą lokalizację kursora, klikając myszką jakiś tekst w edytorze. – Oak

+0

Czy możesz zamieścić swoją aktualną konfigurację dla edytora codemirror? –

Odpowiedz

6

Można słuchać tych wydarzeń:

  • mousedown
  • cursorActivity
  • keyDown
  • beforeChange

Kursor został przeniesiony przez kliknięcie myszą, jeśli spełnione są te warunki:

  • cursorActivity zdarzenie jest wywoływane po mousedown imprezy
  • klucz
  • No ruch został wciśnięty między tymi dwoma wydarzeniami
  • Bez zmian zostało wprowadzonych do treści między tymi dwoma wydarzeniami
  • nie wybrano tekstu

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' uruchamia się po naciśnięciu klawisza klawiatury. Twój 'keyUpHandler' ustawia' movedByMouse' na true, gdy osoba wpisuje cokolwiek w edytorze. –

+0

@IvankaTodorova - Bardzo dobry punkt. – ConnorsFan

+0

Zaktualizowałem fragment kodu, aby uwzględnić ruchy kursora wywołane zmianami wprowadzonymi w treści (na przykład podczas wpisywania tekstu). – ConnorsFan

4

Wszystko Mouse Wydarzenia (które znam):

  • onclick
  • oncontextmenu
  • ondbclick
  • onmousedown
  • onmouseenter
  • onmouseleave
  • onmousemove
  • onmouseover
  • onmouseout
  • onmouseup

Tak, w zasadzie, nie ma rozwiązania dla problemu, który znajduje się w javascript AFAIK. Możesz jednak skorzystać z drugiej sugestii i śledzić zdarzenia, a w zależności od nich zdecydować, czy wykonać akcję, czy nie.

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

Uwaga: Próbowałem łączenie cursorActivity i myszy wydarzeń, ale cursorActivity jest wykonywany przed nimi? Właściwie nie wiem, co się tam dzieje = D

+1

Dziękujemy za rozwiązanie! Na powierzchni działa dobrze, chociaż ten warunek w doAction() nie wydaje się bardzo solidny. Na przykład, jeśli użytkownik przesunął mysz nieco pomiędzy zdarzeniem mousedown i mouseup - ale nie na tyle, aby zainicjować wybór - nie zadziała. Ponadto bit 'codeMirror.getSelection(). Length <= 0' oznacza, że ​​jeśli istnieje wybrany obszar, a następnie użytkownik kliknie poza tym obszarem, to kliknięcie nie zostanie policzone. – Oak

3

można podłączyć do CodeMirror za pomocą haka i zdefiniować własne zdarzenie, które pożary, gdy zmienia się kursor z jednego kliknięcia myszy na edytorze

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; 
    }) 
}); 

Używa flagi i zegara do przechwytywania obu zdarzeń, jeśli wystąpią one w krótkim czasie względem siebie, ponieważ program obsługi kliknięć jest uruchamiany zaraz po obsłudze kursora kursora.

Oto przykład działa jak używać nowo zdefiniowanej Event z 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

Dziękuję za odpowiedź! Wygląda świetnie i bardzo schludnie, definiując nowe wydarzenie. Wydaje się jednak nie uruchamiać, gdy czas między mousedown i mouseup wynosi ponad 300ms, ponieważ mousedown jest tym, który powoduje zmianę kursora, a mouseup uruchamia onclick.Ponadto twoje rozwiązanie rozważy podwójne lub potrójne kliknięcie, aby wybrać 2 lub 3 oddzielne zdarzenia kursora, nawet jeśli wszystkie kliknięcia są wykonywane na końcu zakresu, więc kursor nie zmienia lokalizacji. – Oak

+0

@Oak - Wtedy myślę, że będę musiał nieco zmienić podejście, upuszczając timer, a zamiast tego sprawdzać wybory itp. Zobacz, czy to rozwiązuje cokolwiek. – adeneo

+0

Lepiej! Niestety, teraz uruchamia się również przy rozpoczynaniu selekcji, choć, szczerze mówiąc, technicznie jest to zmiana położenia kursora. – Oak