I know there are similar questions, but I could not find the answer, and I am trying to create an uncommon shortcut in order to execute action according to a specific combination of keys. I don't have an example, since I have not implemented it, I am trying to figure out if I can do it or not. I have a combination of Ctrl, shift, alt, meta keys, I can capture in javascript, my problem, is that I want to use a common key like "g" and make it behave like Ctrl, shift, alt, meta, etc, in order to combine with a key F1, F2, F3 to execute a javascript function with an specific visual component on screen. An Example, I intend to create a shortcut "Ctrl+1+F1" to perform an action in a specific table in a web page showing with more than one table on the html. Can Anyone answer me if this can be done? if someone can, How can I do it?
A broad overview of the algorithm would be as follows:
Keep a Set-type variable that will contain all currently pressed keys. Whenever you get a keydown/keyup event, update that set by adding/removing whatever key was pressed/released. Attach the event handlers as high as you can - for example, on the <body> tag, so that you can catch everything that happens in your page.
Then at the end of the keydown event you should check if the variable contains EXACTLY the keys that your keyboard shortcut requires. If they do, launch the action. In practice you'll probably have a long list of possible keyboard shortcuts. Check them all. Maybe you'll also need extra checks, like some shortcuts could only be active when a certain control is focused or when something is in the right state or whatever.
As a variation, you might want to launch the action not when the keys are pressed, but when they are released. In that case, don't launch the action immediately, but make some sort of note in another variable, that such-and-such combination was pressed. Then wait until all the keys are released (the set is empty), and THEN launch the action. If some other keys got pressed inbetween, clear that note and check if perhaps another combination should be activated instead. Store that in the note-variable and keep waiting.
Unfortunately, the Control keys and the Function keys seem to be mutually exclusive. You can set up key combos with any number of keys, as in the following example, but combining Control and Function doesn't work (on my system anyway).
const result = document.querySelector('#result')
const keys = {}
window.addEventListener('keydown', (ev) => {
keys[ev.key] = true
})
window.addEventListener('keyup', (ev) => {
if (keys['1'] && keys['Control'] && keys['F1']) {
console.log('This does not work on my system')
} else if (keys['1'] && keys['F1']) {
result.value = "F1 + 1 pressed!"
} else if (keys['Control'] && keys['o'] && keys['p']) {
result.value = "Control + o + p pressed!"
} else {
setTimeout(() => result.value = "", 500)
}
keys[ev.key] = false
})
<p>Click in the result pane and then press F1+1, or Control+o+p. Control+F1+1 does not work.</p>
<input id="result">
Thanks to everyone, compiling the answers given, i was able to solve the problem. i had to give the focus to the table (courtesy of kosh, who gave the straight answer i needed), and on the post(event) of the web page, i was capable to catch the active component. I can not post the solution i built, because the code belongs to the company, but i will try to build an example, and post on monday, in case someone else reaches this post after the same doubt (easter in brazil, and tomorrow i am travelling home, thats why the example i will show only on monday). Thanks to everyone again.
Related
I am working on a WYSIWYG-like editor for equations (in combination with plain text).
Since implementing the functionalities (for equations) that I'd like to have won't work using the existing frameworks (contentEditable or document.designMode), I am now building an editor from scratch. (so far it has worked out good, I've successfully implemented most functionalities of a normal editor)
I've been using the keydown event to detect user input while in "edit-mode" (that is, when the user has clicked on the editor-area, also displaying the cursor), but the problem with that is, that when clicking "alt" or "strg" or other keys that aren't actual characters, they'll also get displayed in my editor.
Now, what I've tried is to ignore those keys by using if-statements, but there are 2 issues I see with that:
1. It may influence performance, when too many keys have to be ignored
2. I can never be sure, if there doesn't exist some exotic key, perhaps on a Mac or so, which I didn't ignore
I have also tried to use the keypress event instead, which worked mostly fine, but still displayed "Enter" and "Delete", so who knows what others keys it may display too. Also, it is labelled as "deprecated".
Are there any better ways of doing that, or will I just have to make a big list of keys to ignore?
A simple (but limited) approach would be to check if the keydown event's keyCode is between 65 (code for key 'a') and 90 (code for 'z').
If you need more than just letters though, another solution would be to check the event's key and its length. For actual characters, the key simply holds that character (so length 1). For Ctrl, Shift, etc., key will hold the full name of the key, e.g. "Control", "Shift", etc.
So, if a key is an actual character, the key property will have a length of 1.
document.onkeydown = function(e) {
var keycode = e.keyCode;
if(e.key.length == 1) {
document.querySelector("#editor").innerHTML += e.key;
}
}
<p id="editor"></p>
You can check this one too
document.addEventListener("keydown", (event) => {
console.log(event);
if (event.code === "Escape") {
console.log("abc");
}
});
I am using the keyboard-controls component in a-frame and I notice that I am unable to hold down multiple keys at the same time.
Please see below a stripped down example using the I and J keys.
Using the following scripts
<script src="https://aframe.io/releases/0.8.2/aframe.min.js"></script>
<script src="https://cdn.rawgit.com/donmccurdy/aframe-keyboard-controls/a9c513fc/dist/aframe-keyboard-controls.js"></script>
The component;
AFRAME.registerComponent('keytest', {
dependencies: ['keyboard-controls'],
init: function () {
//I Keydown
this.el.addEventListener('keydown:KeyI', (e) => {
console.log("I Key down")
});
//K Jeydown
this.el.addEventListener('keydown:KeyJ', (e) => {
console.log("J Key down")
});
},
});
And then attached to the scene
<a-scene keytest>
</a-scene>
And here is a glitch, open the console and try holding down I and J simultaneously.
The issue is that for example, while holding down I if I then also hold down J it stops hearing the I keydown and vice versa. Is this not possible? or am I doing something wrong? I know this would be possible with a normal keydown event..
To give some context if that helps, I am making a vehicle and using the keybaord controls to power it. As it is, pressing forward/backwards accelerates the car and left/right will turn the car, but as it is, as soon as I start turning in either direction, the accelerator is stopped as it no longer hears the forward keypress.
Any advice much appreciated.
This is not a bug, but a slight misunderstanding of the keydown event on your part... The keydown event behavior can best be described as what you would expect to see when typing in a word processor, or notepad. if you hold down the I key you would see an I typed and then after a small delay, rapid repetition of I. Then additionally holding down J during that would stop the Is from being typed altogether, type a J, then after another small delay, rapid repetition of J.
What you should do instead, is once a single keydown event is being fired, set an internal variable to true, maybe call it something like throttle, steeringLeft, etc... then when a keyup event is fired for that key, set it back to false. have the car maneuver based on the true/false states of those variables.
Background:
I am writing a script that does some stuff when a user clears an input type="search" (essentially the same as type=text) using backspace or delete. I want to address the case where user highlights original text and starts typing new text, and also pasting.
Because of this I cannot use keydown (fires before input value is changed). Cannot use keypress (need to fire when backspace/delete is pressed, and it fires too early as well). Using keyup is bad because I can't clear when value === 1 (might already be several characters in the field). I can build in some slop but then it won't clear right away which looks buggy.
Question:
So the DOM input event fires right when the value is updated, which is exactly what I want (tested using jQuery on 'input'). However, I cannot find the captured key (which I need to differentiate between deleting and entering content). I couldn't find great info on the spec. It seems like this is going to be implemented in the data section of the event, which does not yet have any browser support. Does that mean it is currently impossible to get the key from the oninput event? If so, how do most developers handle this? I imagine wanting the key immediately after it is entered is very common, surely there is a decent solution for this?
Current implementation for the curious:
For the time being I am grabbing the value right after keydown by using a setTimeout of 0. This gets me both the key and the updated value, but feels dirty and requires extra handlers for onpaste and such. While writing this it occurs to me I could probably use oninput by keeping track of the last value and comparing to current to differentiate between entering and deleting, but that doesn't seem all that much better, and would still require a separate paste handler since I want my event to fire every time a user pastes, and it doesn't seem to have any flags that would let me know the event was a paste.
I decided the last suggestion of dandavis was the best workaround. I used keydown to grab key info and triggered the action on paste, empty field, or 1 character and last character was not backspace/delete (on input does not fire on enter, modifier keys, etc. so those don't need to be accounted for).
The code looks like this:
var onClear = function(action){
var lastKey;
jQueryObject.keydown(function(e){
lastKey = e.which;
});
jQueryObject.on('input', function(){
if( !this.value.length || (this.value.length === 1 && lastKey !== 46 && lastKey !== 8) ){
action();
}
});
jQueryObject.on('paste', function(){
action();
});
}
I'm trying to intercept the command + keystroke in Safari. I've added an event handler as follows:
document.onkeypress = handleKeyPress;
function handleKeyPress(event) {
if ("+" === String.fromCharCode(event.charCode) && event.metaKey) {
// my code here
return false;
}
return true;
}
When I hit command shift = (shift = is + on my US keyboard), the if statement does not return true.
If I remove the event.metaKey portion of the if statement and hit shift =, the if statement does return true.
Also, if I change the matching string from "+" to "=" and hit command = (with or without the shift key), the if statement does return true.
Is there a way to actually detect the command + keypress (without assuming that the + key is shift = and checking for the event.shiftKey, since this will not be true for some non-US keyboards)?
First of all, I can't necessarily recommend using ⌘+ as a shortcut, since it already means something in Safari (namely, zoom the page). Someone might want that to still work normally. Depending on what you're building, it might make sense, but don't override the default shortcuts unless you're sure.
Anyway: Key events are tricky, often because the keyCode/charCode/which properties don't always match up with the right letter, so String.fromCharCode won't always get you a proper string. keyIdentifier is sometimes a better thing to look at, but not always (for instance, its codes for letter keys are always uppercase letters).
What I've done in the past (and I'm not sure that this is the best way to do it, but it works ok), is to instead listen for keydown and keyup events, and "stack" modifier keys. I.e. whenever a key is depressed, check whether it's a modifier key (i.e. if it's cmd, ctrl, alt, or shift). If it is, add it to the "stack" of modifiers. Do the opposite on keyup; if the released key was a modifier, remove it from the stack.
Now, back in the keydown-handler, if the key wasn't a modifier key, you can send the keydown event (which, unlike a keypress event, will have a pretty reliable keyIdentifier property to check), and the stack of modifiers along to some other callback, that'll take it from there.
In your case, such a callback would check that the cmd-key is in the stack, and that the keyIdentifier for the keydown event is "U+002B" (which is the unicode code for +).
I've put together a jsfiddle example of what I'm talking about. If you click in the "Result" pane (to make sure it's got focus), and press ⌘+, it should show the key combo you used, and write "Success!" below. Otherwise, it'll just show the key combo. On my keyboard, the plus sign is directly accessible, so the key combo I see is just "⌘+". But if you need shift to type a plus sign, you should see "⇧⌘+".
It's a generalized piece of code that's good for handling keyboard shortcuts in Safari/Mac, so you can build on it, if you want. You'll want to add a few event listeners to reset the modifier stack on blur events and such. Ideally, the modifier stack would reset automatically, as you release the keys, but since something might cause the browser, or the observed element/window/document, to lose focus, the keyup events won't be handled, and the released keys won't be removed from the stack. So check for blur events.
Register the event object in a window object level one, event = window.EE for example, then browse it with Firebug or Safari’s Web Developer Tools and see the values that are triggered when you want. So you will know what to compare against.
Sadly, I don't think there is an answer. The problem is, for CMD+SHIFT+= the charCode being pressed is 61 (=), not 43 (+). This appears to be a system-wide design, in that Mac OS X itself interprets CMD+SHIFT+= as = plus two modifiers, not + and COMMAND.
I put together a simple jsFiddle to show this: http://jsfiddle.net/ScuDj/1/
Basically, you are going to have to deal with keyboard layouts if you want to detect COMMAND +.
Alternatively, you could only support the numeric keypad + - that works consistently! (just kidding ;-)
(Also: I tried to attach to the textInput event, but couldn't get it to register globally. I think it only works on domNodes. I've not really used that event much.)
I am creating a smart textarea that needs to recognise a term typed after the '#' symbol.This needs to be able to work for the term CURRENTLY being typed and be able to work for multiple instances of the '#' symbol in a single textarea.
It is designed to work the same way as Facebook when you type the '#' symbol to tag a person in a post. A drop down list will appear and list items will get filtered depending on the term after the '#' symbol.
This also needs to work if the user were to type a term then amend it later. I understand this complicates things a little.
What is the best way to achieve this functionality?
I don't know if it helps but here's i small script to find the hashes.
http://jsfiddle.net/aNgVV/
I suggest you look at the jQuery UI demo for the Autocomplete widget, specifically the demo for using a remote datasource with cache. Specifically for the following reasons:
It automatically takes care of the drop-down widget you mentioned.
It demonstrates how you can populate that drop-down with items based on an AJAX call (which I presume you need).
The demo for Autocomplete caching parses the text in the INPUT element, as it tries to determine whether or not the value the user is currently typing has already been cached, and reacts accordingly. I assume you can do something similar to check for the # types, and to check if a previous # tag is being modified as well.
Initially you need to catch the '#' key being pressed and then capture the subsequent key presses and pass them to a function to handle your auto completion requirements. A rough outline to of the code is below. You may need to catch whitespace key presses as well to stop the auto-completion.
var hashKeyPressed = false;
$('#TextArea').keyup(function(event) {
if(event.keyCode == '222') {
// this will catch the '#' key
hashKeyPressed = true;
}
if(hashKeyPressed) {
// Here you can start build up subsequent key presses into a string
// and pass them to a function to handle the auto-completion
}
});
You can capture the keyup event and check what has been entered last like so:
$('#myTextArea').keyup(function () {
var len = $(this).val().length;
if ($(this).val().substring(length - 1, 1) == '#') {
// Do whatever you want to do here
}
});
EDIT:
You are right - you could do it this way instead:
$('#myTextArea').keypress(function (e) {
if (e.which == 222) {
// do something here
}
});