Detect difference between key combination and single key - javascript

How can I detect the difference between a single CTRL key and a CTRL + 1 key combination?
Currently I have the following:
window.addEventListener('keydown', function(e) {
if(e.keycode === 17){
alert('crtl only')
}
else if (e.ctrlKey && e.keyCode == 49) {
alert('crtl + 1');
}
}

When the key(s) are hit, make a note of the time. Then compare it with the time you noted the last time they key(s) were hit.
If the difference is within your threshold, consider it a double. Otherwise, don't.
If the difference is within your threshold, consider it a double. Otherwise, don't.
Rough example:
var delta = 500;
var lastKeypressTime = 0;
function KeyHandler(event)
{
if ( event.ctrlKey
&& String.fromCharCode(event.charCode).toUpperCase()) == 'T' )
{
var thisKeypressTime = new Date();
if ( thisKeypressTime - lastKeypressTime <= delta )
{
doDoubleKeypress();
// optional - if we'd rather not detect a triple-press
// as a second double-press, reset the timestamp
thisKeypressTime = 0;
}
lastKeypressTime = thisKeypressTime;
}
}

This should work:
window.addEventListener('keydown', function (e) {
if (e.ctrlKey && e.keyCode === 49){
alert('combo hit!');
}
}

Use debounce with keydown
function KeyPress(e) {
var evtobj = window.event ? event : e;
debouce(function(evtobj) {
if (evtobj.keyCode == 65 && evtobj.ctrlKey) {
console.log("Ctrl+a");
evtobj.preventDefault();
} else if (evtobj.ctrlKey) {
console.log("Only ctrl");
}
}, evtobj, 200);
}
Demo
function KeyPress(e) {
var evtobj = window.event ? event : e;
debouce(function(evtobj) {
if (evtobj.keyCode == 65 && evtobj.ctrlKey) {
console.log("Ctrl+a");
evtobj.preventDefault();
} else if (evtobj.ctrlKey) {
console.log("Only ctrl");
}
}, evtobj, 200);
}
function debouce(method, eventObj, debounceTime) {
if (this.timeoutId)
clearTimeout(this.timeoutId);
this.timeoutId = setTimeout(function() {
method(eventObj);
}, debounceTime);
}
document.onkeydown = KeyPress;

Related

Javascript keydown event doesn´t give me the char # in EDGE

I'm working in a mentioning directive, basically when the user is typing in the input field ( a div with contentEditable=true in this case ), is gonna display a list of user for then insert the name of the user in a specific format, now the list is gonna displayed after the user press #, for chrome and firefox work just great but for EDGE and IE ( unfortunately i need to support ) doesn't work because in this case the # apparently doesn't exist.
now for the key press I'm using the #HostListener('keydown', ['$event'])
HostListener
#HostListener('keydown', ['$event']) keyHandler(event: any, nativeElement: HTMLInputElement = this._element.nativeElement) {
let val: string = getValue(nativeElement);
let pos = getCaretPosition(nativeElement, this.iframe);
let charPressed = this.keyCodeSpecified ? event.keyCode : event.key;
if (!charPressed) {
let charCode = event.which || event.keyCode;
if (!event.shiftKey && (charCode >= 65 && charCode <= 90)) {
charPressed = String.fromCharCode(charCode + 32);
} else if (event.shiftKey && charCode === KEY_2) {
charPressed = this.triggerChar;
} else {
charPressed = String.fromCharCode(event.which || event.keyCode);
}
}
if (event.keyCode == KEY_ENTER && event.wasClick && pos < this.startPos) {
// put caret back in position prior to contenteditable menu click
pos = this.startNode.length;
setCaretPosition(this.startNode, pos, this.iframe);
}
// console.log('=== keyHandler', this.startPos, pos, val, charPressed, event);
this.triggerList(event, charPressed, nativeElement, val, pos);
}
Now as you can see I'm using event.keycode and event.key to get the key from the event keydown, I pass does values to the method this.triggerList()
that basically is gonna display the list of mentions options if and only if the user press # that is the trigger char ( this.triggerChar ).
TriggerList Method
private triggerList(event, charPressed, nativeElement, val, pos): any {
if (charPressed == this.triggerChar) {
this.startPos = pos;
this.startNode = (this.iframe ? this.iframe.contentWindow.getSelection() : window.getSelection()).anchorNode;
// console.log('=== HERE CHAR', this.startNode, this.startPos);
// check if mentioning is allowed based on the text before the mention start char
if (!this.configService.appConfig.platform.EDGE) {
let position = this.getHtmlCaretPosition(nativeElement);
const charBefore = val[position - 1];
if (charBefore == undefined || charBefore.trim() == '' || charBefore == ':') {
this.log.trace('Start mentioning');
this.stopSearch = false;
this.searchString = null;
this.showSearchList(nativeElement);
this.updateSearchList();
}
} else {
this.stopSearch = false;
this.searchString = null;
this.showSearchList(nativeElement);
this.updateSearchList();
}
} else if (this.startPos >= 0 && !this.stopSearch) {
if (pos <= this.startPos) {
this.searchList.hidden = true;
}
// ignore shift when pressed alone, but not when used with another key
else if (event.keyCode !== KEY_SHIFT && !event.metaKey && !event.altKey && !event.ctrlKey && pos > this.startPos) {
if (event.keyCode === KEY_SPACE) {
this.startPos = -1;
} else if (event.keyCode === KEY_BACKSPACE && pos > 0) {
pos--;
if (pos == 0) {
this.stopSearch = true;
}
this.searchList.hidden = this.stopSearch;
} else if (!this.searchList.hidden) {
if (event.keyCode === KEY_TAB || event.keyCode === KEY_ENTER) {
this.stopEvent(event);
this.searchList.hidden = true;
// value is inserted without a trailing space for consistency
// between element types (div and iframe do not preserve the space)
let textValue = this.mentionSelect(this.searchList.activeItem);
insertValue(nativeElement, this.startPos, pos, textValue, this.iframe);
this.emitSelection(nativeElement);
if (this.htmlStyling) {
let quillElement = document.querySelector('.ql-editor');
let innerHtml = quillElement.innerHTML;
let strings = innerHtml.split(textValue);
if (strings.length === 2) {
innerHtml = `${strings[0]}<span id="mention${textValue.substring(1)}${strings.length - 1}" style="color: #0065FF; background: rgba(0,101,255,.2)">${textValue}</span> ${strings[1]}`;
} else {
let openSpan = false;
innerHtml = strings.reduce((total, current, currentIndex) => {
if (current.indexOf(`mention${textValue.substring(1)}`) > 0) {
return `${total}${openSpan ? '</span> ' : ''}${current}${textValue}`;
} else if (openSpan) {
return `${total}</span> ${currentIndex < strings.length - 1 ? current + textValue : current}`;
} else {
openSpan = true;
return `${total}${current}<span id="mention${textValue.substring(1)}${strings.length - 1}" style="color: #0065FF; background: rgba(0,101,255,.2)">${textValue}`;
}
}, '');
}
quillElement.innerHTML = innerHtml;
// tslint:disable-next-line:no-angle-bracket-type-assertion
let mentionElement: HTMLInputElement = document.getElementById(`mention${textValue.substring(1)}${strings.length - 1}`) as HTMLInputElement;
// tslint:disable-next-line:no-angle-bracket-type-assertion
setCaretPosition(mentionElement.nextSibling as HTMLInputElement, 1);
}
// fire input event so angular bindings are updated
if ('createEvent' in document) {
let evt = document.createEvent('HTMLEvents');
evt.initEvent('input', false, true);
nativeElement.dispatchEvent(evt);
}
this.startPos = -1;
return false;
} else if (event.keyCode === KEY_ESCAPE) {
this.stopEvent(event);
this.searchList.hidden = true;
this.stopSearch = true;
return false;
} else if (event.keyCode === KEY_DOWN) {
this.stopEvent(event);
this.searchList.activateNextItem();
return false;
} else if (event.keyCode === KEY_UP) {
this.stopEvent(event);
this.searchList.activatePreviousItem();
return false;
}
}
if (event.keyCode === KEY_LEFT || event.keyCode === KEY_RIGHT) {
this.stopEvent(event);
return false;
} else {
let mention = val.substring(this.startPos + 1, pos);
if (event.keyCode !== KEY_BACKSPACE) {
mention += charPressed;
}
this.searchString = mention;
this.searchTerm.emit(this.searchString);
this.updateSearchList();
}
}
}
}
now the issue here is that if the user to insert the char # need to use the combination of ALT + Q EDGE only detect ALT and then Q, compare to firefox and chrome that with the combination ALT + Q detect # for this reason the list is not display because the char never match.
First i replace the event keydown for keypress, then where i save the char in the variable charPress i create a condition to check if the browser is EDGE or IE, and get char code using event.charCode and convert it in to string using String.fromCharCode(event.charCode) at the end looks like this.
#HostListener('keypress', ['$event']) keyHandler(event: any, nativeElement: HTMLInputElement = this._element.nativeElement) {
let val: string = getValue(nativeElement);
let pos = getCaretPosition(nativeElement, this.iframe);
let charPressed = this.keyCodeSpecified ? event.keyCode : event.key;
if (this.configService.appConfig.platform.EDGE) {
charPressed = String.fromCharCode(event.charCode);
}
......

How to limit query function runs with while looping?

For the last days I've been working on a stimulus presentation function. Now it's the details that need adjustment, in particular im stuck with this:
I want my keypress event to be executed only 20 times, after which an alert states that the task is over. I tried for looping and while. I've probably lost the overview to see my fault, but my code doesn't stop after 20 key presses. Where is my mistake?
var i=0;
while (i < 20) {
$(function(){
$(document).keypress(function(e){
if ($(e.target).is('input, textarea')) {
return;
};
if (e.which === 97 || e.which === 108 || e.which === 32) {
if(Math.random() < 0.5) {
var new_word = stim[Math.floor((Math.random()*stim.length)+1)].name;
$("#abc").text(new_word);
} else {
var new_img = stim[Math.floor((Math.random()*stim.length)+1)].path;
$("#abc").empty();
var prox_img = $('<img id="abcimg" height="300px" width="300px">');
prox_img.attr('src', new_img);
prox_img.appendTo('#abc');
}
};
});
});
i++;
alert("abcdefg");
};
You dont need loop, just use global counter, i for example
var i = 0; // saves count of keypress events
$(function() {
$(document).keypress(function(e) {
if ($(e.target).is('input, textarea') || i > 20) { // check for 20 events
return;
};
i++; // increase counter...
if (e.which === 97 || e.which === 108 || e.which === 32) {
if(Math.random() < 0.5) {
var new_word = stim[Math.floor((Math.random()*stim.length)+1)].name;
$("#abc").text(new_word);
} else {
var new_img = stim[Math.floor((Math.random()*stim.length)+1)].path;
$("#abc").empty();
var prox_img = $('<img id="abcimg" height="300px" width="300px">');
prox_img.attr('src', new_img);
prox_img.appendTo('#abc');
}
}
});
});
You need to remove the event when the loop is finished executing, else the event remains attached to the document.
$(document).off("keypress");

capturing Alt+F+P jquery

Here is how I was able to capture CTRL+C in jQuery
$(window).bind('keydown', function (event) {
if (event.ctrlKey || event.metaKey) {
switch (String.fromCharCode(event.which).toLowerCase()) {
case 'p':
event.preventDefault();
printFunc();
break;
}
}
});
How can i do the same for ALT+F+P
$(window).bind('keydown', function (event) {
if (event.altKey || event.metaKey) {
switch (String.fromCharCode(event.which).toLowerCase()) {
case 'f':
event.preventDefault();
//************ Need help for identifying p **************
// alert('Alt-f');
printFunc();
break;
}
}
});
I tried this also but no luck:
if (event.altKey && event.which == 70 && event.which == 80) {
alert('Alt-f-p');
}
This works, but only if you do "p" before "f". In Chrome at least, Alt+F activates a browser function. Live demo (click).
var pressed = {};
$(document).keydown(function(event) {
//event.altKey 70 80
var k = event.keyCode;
if (event.altKey && (k == 70 || k == 80)) {
pressed[k] = true;
console.log(k);
}
if (pressed[70] && pressed[80]) {
console.log('all pressed!');
}
});
$(document).keyup(function() {
pressed = {};
});
Perhaps you would want to adapt it to use something not conflicted?

How to detect keyboard modifier (Ctrl or Shift) through JavaScript

I have a function which detect max length. but the problem is that when the max length reached Ctrl+A combination does't work. How can I detect Ctrl+A combination through javascript.
This is my maxlength code.
if (event.keyCode==8 || event.keyCode==9 || event.keyCode==37 || event.keyCode==39 ){
return true;
} else {
if((t.length)>=50) {
return false;
}
}
Check event.ctrlKey:
function keyHandler(event) {
event = event || window.event;
if(event.keyCode==65 && event.ctrlKey) {
// ctrl+a was typed.
}
}
key codes:
shift 16
ctrl 17
alt 18
your jQuery:
$(document).keydown(function (e) {
if (e.keyCode == 18) {
alert("ALT was pressed");
}
});
JavaScript Madness: Keyboard Events
You can use the following:
document.onkeypress = function(evt) {
evt = evt || window.event;
etv = evt;
switch (etv.keyCode) {
case 16:
// Code to do when Shift presed
console.log('Pressed [SHIFT]');
break;
case 17:
// Code to do when CTRL presed
console.log('Pressed [CTRL]');
break;
case 32:
// Code to do when ALT presed
console.log('Pressed [ALT]');
break;
}
};
I needed a solution for this too, so found some stuff that worked, cleaned it up to be a lot less code, and ES6... JSFiddle link
function isCapsLock(event=window.event) {
const code = event.charCode || event.keyCode;
if (code > 64 && code < 91 && !event.shiftKey) {
return true;
}
return false;
}
document.getElementById("text").addEventListener("keypress", event => {
const status = document.getElementById("status");
if (isCapsLock(event)) {
status.innerHTML = "CapsLocks enabled";
status.style.color = "red";
} else {
status.innerHTML = "CapsLocks disabled";
status.style.color = "blue";
}
}, false);
<input type="text" id="text" /><br>
<span id="status"></span>
This is a very old question. gilly3's answer is valid only if we have at hand an event object of type KeyboardEvent passed as a function argument. How to detect the current control key state if we have not event object available such as in this function?
function testModifierKey() {
// have I some modifier key hold down at this running time?
}
I found the solution after a long search from https://gist.github.com/spikebrehm/3747378 of spikebrehm. his solution is tracing the modifier key state at any time using jQuery with a global variable.
The global variable window.modifierKey can be used in any circonstance without requiring event object.
function testModifierKey() {
// have I have some modifier key hold down at this executing time?
if(window.modifierKey) {
console.log("Some modifier key among shift, ctrl, alt key is currently down.");
// do something at this condition... for example, delete item without confirmation.
} else {
console.log("No modifier key is currently down.");
// do something at other condition... for example, delete this item from shopping cart with confirmation.
}
}
Here is his script to load in your HTML document:
// source: https://gist.github.com/spikebrehm/3747378
// modifierKey used to check if cmd+click, shift+click, etc.
!function($, global){
var $doc = $(document);
var keys;
global.modifierKey = false;
global.keys = keys = {
'UP': 38,
'DOWN': 40,
'LEFT': 37,
'RIGHT': 39,
'RETURN': 13,
'ESCAPE': 27,
'BACKSPACE': 8,
'SPACE': 32
};
// borrowed from Galleria.js
var keyboard = {
map: {},
bound: false,
press: function(e) {
var key = e.keyCode || e.which;
if ( key in keyboard.map && typeof keyboard.map[key] === 'function' ) {
keyboard.map[key].call(self, e);
}
},
attach: function(map){
var key, up;
for(key in map) {
if (map.hasOwnProperty(key)) {
up = key.toUpperCase();
if (up in keyboard.keys) {
keyboard.map[keyboard.keys[up]] = map[key];
} else {
keyboard.map[up] = map[key];
}
}
}
if (!keyboard.bound) {
keyboard.bound = true;
$doc.bind('keydown', keyboard.press);
}
},
detach: function() {
keyboard.bound = false;
keyboard.map = {};
$doc.unbind('keydown', keyboard.press);
}
};
$doc.keydown(function(e) {
var key = e.keyCode || e.which;
if (key === 16 || key === 91 || key === 18 || key === 17) {
modifierKey = true;
} else {
modifierKey = false;
}
});
$doc.keyup(function(e) {
modifierKey = false;
});
}(jQuery, window);

Javascript on second keypress

I've been wondering if there was a simple way to detect if a user presses the same character on the keyboard twice within one second. I've written some code that kind of works but it's unreliable.
var escapeCount = 0;
function reset() {
escapeCount = 0;
setTimeout('reset();', 1000);
}
window.onload = function() {
reset();
};
document.onkeyup = function(e) {
if (!e) var e = window.event;
var code = e.keyCode ? e.keyCode : e.which;
if (code == 27) escapeCount +=1;
if (escapeCount == 2) {
// stuff on second escape
}
};
Is there a better way to do this? Thanks
It would make sense to reset after 1 second has passed since the last character was pressed. Example:
var lastChar = -1;
document.onkeyup = function(e) {
if (!e) var e = window.event;
var code = e.keyCode ? e.keyCode : e.which;
if (lastChar == code) {
// Same key was pressed twice in a row within 1 second.
} else {
lastChar = code;
setTimeout(function() {lastChar = -1;}, 1000);
}
};
Your timer resets every second, so you not only have to press Escape again within a second of the last Escape, but that also has to have no timeout in between the presses.
It's probably easier to forget the timeout and just remember the time of the last keypress instead:
var lastescapetime= null;
document.onkeyup= function(event) {
if (event===undefined) event= window.event;
if (event.keyCode===27) {
var now= new Date().getTime();
if (lastescapetime!==null && now<lastescapetime+1000) {
alert('You double-escaped!');
lastescapetime= null;
} else {
lastescapetime= now;
}
} else {
lastescapetime= null;
}
};

Categories

Resources