CodeMirror: Catching Enter Key prevents line breaks - javascript

I used the extraKeys-option of CodeMirror 3.12 to detect when the user starts a new line:
extraKeys: {
"Enter": onNewLine
}
onNewLine() does nothing but a console.log(). Now CodeMirror ignores that key. You can't start a new line anymore. Is there a way to hook up additional functionality on a new-line-event without interfering CodeMirror internals? I just want to analyze the text of the recently closed line.

Add a line break at the end of onNewLine function.
This should work
function onNewLine(e){
console.log(e);
editor.replaceSelection("\n" ,"end");
}

I found that returning CodeMirror.Pass also works:
function onNewLine(e) {
console.log("Enter key was pressed!");
return CodeMirror.Pass;
}
From the documentation:
A key handler function may return CodeMirror.Pass to indicate that it has decided not to handle the key, and other handlers (or the default behavior) should be given a turn.
This seems to work even if the handler does perform an action. In my case I was using the editor.indentLine function to indent the current line when the user pressed the enter key.

Related

Remove window event handler after triggered one time

I am dealing with an odd problem where I need an event handler to bind upon instantiation of a module, but when the module is terminated via a click or a keypress, I no longer want this global event bound. I've gotten the click event to register termination of the module handled elsewhere in code and that works, but the problem is the escape press that I want to globally terminate the module regardless of where my user currently is in the app.
My problem is that the .off() doesn't appear to work given the circumstances.
let tools = {};
//how can i eliminate this next line of code after escape has been triggered?
$(window).on('keydown', (e)=>escape(e, tools));
function escape(e, tools){
if (e.which==27){
//do some stuff with tools, etc
$(window).off('keydown', $(window), escape); //this line doesn't seem to work
alert('alert triggered, but next time escape is pressed it wont.');
}
}
Am I going about this approach wrong? I tried binding it to the div element itself, but this has a whole lot more baggage associated with focussing the div to recieve the keypresses, and if the user navigates to another module, the escape will no longer be triggered because this module will no longer have focus, and well, etc etc etc.
Thank you!
Here is fiddle:
https://jsfiddle.net/rbfebL5y/1/
Use only handler function as argument according to documentation:
let tools = {};
//how can i eliminate this next line of code after escape has been triggered?
$(window).on('keydown', escape);
function escape(e){
if (e.which==27){
//do some stuff with tools, etc
$(window).off('keydown', escape);
alert('alert triggered, but next time escape is pressed it wont.');
}
}
You could use localStorage:
// check key pressed and whether we've done this before
if (e.which==27 && !localStorage.getItem('hasLoggedEscape')){
// set the local storage value saying we've done this before
localStorage.setItem('hasLoggedEscape', 1);
//do some stuff with tools, etc
}
later if you want to reset this, do
localStorage.removeItem('hasLoggedEscape');

Javascript onkeypress interferes with rest of page

On a site where some calculated answers must be given, I have implemented an invisible-until-button-clicked <div> with a simple calculator. I want to be able to operate this calculator using the physical keyboard.
I can use document.onkeypress= function(key){ reactKey(key); }, and I can catch the keys pressed. However, the div-buttons I use in my form no longer work, which also means I cannot even summon the hidden div with the calculator.
I have tried to associate the onkeypress with the calculator div, but then the key presses go undetected.
Ideally, I want the key press to be detected and used in a conditional function:
document.onkeyup= function(key){ reactKey(key); }
function reactKey(evt) {
isVisible = document.getElementById("calcRow").style.display;
if (isVisible=="table-row") {
// use key for calculator function
}
} else {
//go about business as usual
}
}
Neither return true; not return false seem to do this.
Anybody any ideas?
Please note I am trying to avoid using JQuery, as it seems silly to link in an entire library for only this functionality.

eventListener can't read keyCode

So I'm working on a game that will accept user input (up down left right arrow keys). To do so, I will add an event listener that will check when the user presses said keys. I have it set up in the following way:
function gameStart(){
//Generates four random numbers on board
for(gameStart_i = 0; gameStart_i < 4; gameStart_i++){
generateNumber();
}
document.getElementById("start_button").innerHTML = "Reset Game";
document.getElementById("start_button").setAttribute('onclick', 'reset()');
document.getElementById("start_button").id = 'reset_button';
var board = document.getElementById("game_background");
console.log("1");
board.addEventListener("keydown", inputListen(), false);
console.log("1.1");
}
function inputListen(e){
console.log("2");
var code = e.keyCode;
switch(code){
case 37:
alert("left");
break;
case 38:
alert("up");
break;
case 39:
alert("right");
break;
case 40:
alert("down");
break;
}
}
This seems in line with how tutorials show it. However, some tutorials change the addEventListener line with something that would look like this:
board.addEventListener("keydown", inputListen, false); //removes the () after the function
However that doesn't seem to work for me when I look into my console.
When I run my code my console gives me the following error:
1
2
Uncaught TypeError: Cannot read property 'keyCode' of undefined
at inputListen (script.js:86)
at gameStart (script.js:16)
at HTMLButtonElement.onclick (2048Game.html:114)
I think it's because I don't pass any parameters to my function, but none of the online tutorials pass paraements in their addEventListener statement.
Thank you,
Alex
The proper way to do this is indeed to remove the () after inputListen.
Using the () immediately calls the function, which then gives you aforementioned Cannot read property 'keycode' of undefined since no input parameters were given.
You should have also received the error in the console between the two console.log lines, which proves the error came from the addEventListener line.
You want to pass the function without calling it using the line you posted:
board.addEventListener("keydown", inputListen, false); //removes the () after the function
Take a look at this JSFiddle:
function gameStart(){
console.log("before");
document.getElementById("game_background").addEventListener("keydown", inputListen, false);
console.log("after");
}
This should print out to the console
before
after
And then nothing else until it detects a keydown.
It also matters what kind of element you bind this to. An element such as <input> will have no trouble here, but normal non-focusable elements will need the tabindex attribute in order to be focused and respond to a keydown:
<div id="game_background" tabindex="-1">
</div>
You'll need to click the element once to focus onto it, then your events should be captured. More info at this answer.
Yes drop the (), you are using the function itself to the event listener, not the result of the function call.
The keydown event is likely not sent to an arbitrary <div> in the page. Add the event listener to the window itself instead, if you don't want the user to manually click to focus on it.
window.addEventListener('keydown', inputListen);

Why is my javascript function completely ignored? (Very simple example)

I have two buttons. Save and undo. They execute a javascript, and in the end they call resetButtons() which is meant to disable the buttons until any other change in the users input occurs. This code has worked for over a year now, but while implementing some new features, this one has broken.
Here is a direct snippet of code:
function undo(){
var r = confirm("Are you sure you want to cancel your inputs?");
if (r == true) {
setLoadedValues(); //calls in the cached previous values
updateAllBoxValues(); //updates view
console.log("before resetting buttons");
resetButtons();
console.log("after resetting buttons");
}
}
function resetButtons(){
console.log("resetting buttons");
$(".save").addClass("disabled");
$('.save').attr('disabled', 'disabled');
$(".undo").addClass('disabled');
$('.undo').attr('disabled', 'disabled');
console.log("done resetting buttons");
}
This gives the following output:
before resetting buttons
after resetting buttons
I have suspected some wrong formatting with brackets, but this is a direct snippet of code, and if undo() works, so should resetButtons(), right? Also, I should have been given a undefined function, or an unexpecetd end of input or something similar if that was the case. The call to resetButtons is also ignored when I click the save button. I am lost. Help?
You have a duplicate function definition. Rename one of them.
Your code seems fine, you must have some other error somewhere else (like a function named like those two).
By the way, I suggest using jQuery's "prop" method to change the disabled attribute:
$('foo').prop('disabled', true);
$('foo').prop('disabled', false);
Try triggering the resetButton() function in console, if there's an issue it should return it. Testing it in a random console gives all the logs it should, but I can't vouch for the selectors. The error is probably elsewhere in the code.

How do I throttle in jQuery only on a certain condition, and execute immediately otherwise?

I'm using this jQuery plug-in for throttle support.
I have a text input variable called textbox set as follows, which will execute someFunction at most once every second:
textbox.keypress($.throttle(1000, someFunction(e)));
However, I want someFunction to execute immediately if the key pressed is the enter key. I'm not quite sure how to do this. Any suggestions?
textbox.keypress(function(event) {
if(event.which == 13){
// Enter key has been preseed. Do something.
} else {
$.throttle(1000, function(){
someFunction(event);
})
}
});
Keep in mind what you're passing for callbacks. Both 'someFunction' and '$.throttle' are being invoked directly, with their return values being passed as callbacks. To avoid this, wrap the functions in a function (lambda) as I have done above.
You will need to have in your code a handler for the 'ENTER' keypress and abort the $.throttle if that is the case. Can you paste more of your code maybe to give us a better idea of what to work with?

Categories

Resources