I'm using the following code to detect multiple keys on a keypress event:
var down = [];
$(document).keydown(function (e) {
down[e.keyCode] = true;
}).keyup(function (e) {
if (down[17] && down[32]) {
// Do something
}
down[e.keyCode] = false;
});
However, this hotkey (CTRL + SPACE) is meant to be used while an input field has focus. So whenever I press the key combination, it also adds a space to the input field.
How can I prevent this from happening? I've looked at ways to disable spaces in input (like this), but I can't figure out how to make it work inside my keypress event only.
You may try this. I hope it helps.
var down = [];
$(document).keydown(function (e) {
down[e.keyCode] = true;
}).keypress(function (e) {
if (down[17] && down[32]) {
var $sampleTextBox = $("input#sampleTextBox");
$sampleTextBox.val($sampleTextBox.val().replace(/\s/g, ''));
alert($sampleTextBox.val().length)
alert("Ctrl + Space Pressed!");
}
down[e.keyCode] = false;
}).keyup(function (e) {
if (down[17] && down[32]) {
var $sampleTextBox = $("input#sampleTextBox");
$sampleTextBox.val($sampleTextBox.val().replace(/\s/g, ''));
alert($sampleTextBox.val().length)
alert("Ctrl + Space Pressed!");
}
down[e.keyCode] = false;
});
--
Thanks,
SuperCoder
I ended up using a different approach, as MelanciaUK suggested.
On the keyup event, it removes the last character in the input field.
var down = [];
$(document).keydown(function (e) {
down[e.keyCode] = true;
}).keyup(function (e) {
if (down[17] && down[32]) {
// Do something
input = $(':focus');
input.val(function (index, value) {
return value.substr(0, value.length - 1);
});
}
down[e.keyCode] = false;
});
While it doesn't prevent the space from being added, it removes it immediately.
Related
I tried to set eventListener for two input fields. I can press Enter on every input field and it runs ProductInsertPhp() function which save data to MySQL base. When I click on Submit button everything works perfectly. If I press Enter on any input field it works OK only on the first time. But if I run script again it make two inserts. Again - three inserts to base. Every time it is raised by 1.
I tried code with getElementById but it works only with one field.
<script>
//Works ok but only for one field.
//var polaText = document.getElementById("txtInput");
//polaText.addEventListener('keyup', function (e) {
var inputText = document.querySelectorAll(".inpt");
inputText = addEventListener('keyup', function (e) {
e = e || window.event;
var isEsc = false;
var isEnter = false;
if ("key" in e) {
isEsc = (e.key === 'Escape' || e.key === 'Esc');
isEnter = (e.key === 'Enter');
}
if (isEsc) {
funct()
}
if (isEnter) {
//document.getElementById("submitButton").click();
ProductInsertPHP();
console.log("insert");
}
});
</script>
There is no error messages on console. What can I do to set it to only one insert?
There are two things off in your code.
You are not adding the eventListener to every inputText element, you are overriding the variable
your if() has one } too much
Check the comments in this corrected solution:
<script>
var inputText = document.querySelectorAll(".inpt");
// add for loop to query all inputs and add eventlistener to every one of them
inputText.forEach(inp => {
inp.addEventListener('keyup', (e) => {
e = e || window.event;
var isEsc = false;
var isEnter = false;
if ("key" in e) {
isEsc = (e.key === 'Escape' || e.key === 'Esc');
isEnter = (e.key === 'Enter');
}
if (isEsc) {
funct()
}
if (isEnter) {
//} <-- remove this
document.getElementById("submitButton").click();
ProductInsertPHP();
console.log("insert");
}
})
});
</script>
I have a simple script that uses left and right arrows to move to next and previous blogpost.
var nextEl = document.getElementById("pagination__next__link");
var prevEl = document.getElementById("pagination__prev__link");
document.onkeyup = function(e) {
if (nextEl !== null) {
if (e.keyCode === 37) {
window.location.href = nextEl.getAttribute('href');
}
}
if (prevEl !== null) {
if (e.keyCode === 39) {
window.location.href = prevEl.getAttribute('href');
}
}
return false;
};
But it also works when I have text input or textarea focused. What would be the best way to disable the keyboard shortcuts when focused?
Thanks!
Disable event propagation of the input to the document
nextEl.onkeyup = prevEl.onkeyup = function(e){ e.stopPropagation(); };
I am making a TD element of table editable on double click:
$(document).on("dblclick", "#table>tbody>tr>td.cell", function(e) {
if (e.which != 1 || e.shiftKey || e.altKey || e.ctrlKey)
// need left button without keyboard modifiers
return;
reset_selection();
var editor = document.createElement("div");
editor.setAttribute("contenteditable", "true");
editor.innerHTML = this.innerHTML;
this.innerHTML = '';
// this.style.padding = 0;
this.appendChild(editor);
$(document).on("*", stub);
editor.onblur = function() {
// this.parentNode.setAttribute("style", "");
this.parentNode.innerHTML = this.innerHTML;
sys.editor = null;
$(document).off("*", stub);;
};
editor.focus();
});
function stub(e) {
e.stopImmediatePropagation();
return false;
}
But when i double click on the text inside the editable div, the double click event propagates to the parent td causing undesired consequences. There are also other events (select, mousedown, etc) i want to prevent, so writing a stub for each of them doesn't look nice to me.
Is there a way to disable all currently active jQuery event handlers and enable them afterwards? Or somewhow stop propagating all events from the editable div to its parents?
Or somewhow stop propagating all events from the editable div to its parents?
It may not be very palatable, but it's not that bad to specifically disable the events:
$(this).on("select mousedown mouseup dblclick etc", false);
(Assuming this refers to the cell you're editing.)
There is a limited number of events, after all, and on allows you to list them in a space-delimited string and disable them by passing false.
You can then re-enable them by passing the same list and false again into off.
Use on / off JQuery methods :
var myFunction = function(e) {
if (e.which != 1 || e.shiftKey || e.altKey || e.ctrlKey)
// need left button without keyboard modifiers
return;
reset_selection();
var editor = document.createElement("div");
editor.setAttribute("contenteditable", "true");
editor.innerHTML = this.innerHTML;
this.innerHTML = '';
// this.style.padding = 0;
this.appendChild(editor);
$(document).on("*", stub);
editor.onblur = function() {
// this.parentNode.setAttribute("style", "");
this.parentNode.innerHTML = this.innerHTML;
sys.editor = null;
$(document).off("*", stub);;
};
editor.focus();
};
function stub(e) {
e.stopImmediatePropagation();
return false;
}
//Active the events
$(document).on("dblclick", "#table>tbody>tr>td.cell", myFunction);
//Disable the events
$(document).off("dblclick", "#table>tbody>tr>td.cell",myFunction);
//Reactive the events
$(document).on("dblclick", "#table>tbody>tr>td.cell", myFunction);
Update
You can also manage a variable set to true if the event must not be taking into account :
var skipEvent = true;
$(document).on("dblclick", "#table>tbody>tr>td.cell", function (e) {
//Check variable and skip if true
if (skipEvent)
return false;
if (e.which != 1 || e.shiftKey || e.altKey || e.ctrlKey)
// need left button without keyboard modifiers
return;
reset_selection();
var editor = document.createElement("div");
editor.setAttribute("contenteditable", "true");
editor.innerHTML = this.innerHTML;
this.innerHTML = '';
// this.style.padding = 0;
this.appendChild(editor);
$(document).on("*", stub);
editor.onblur = function () {
// this.parentNode.setAttribute("style", "");
this.parentNode.innerHTML = this.innerHTML;
sys.editor = null;
$(document).off("*", stub);;
};
editor.focus();
});
I have to use javascript to make links instead of for several unimportant reasons, and I want for it to behave like even though im not using it. Not the affects thats easy, but I want to be able to hold down shift while clicking to open a new window and to open it in a new tab if they are holding down ctrl. How would I do this? Also, it has to be compatible with IE9.
[edit] Also, this is going to be in an iframe
I guess you want something like this:
JSFiddle
http://jsfiddle.net/MXuVY/3/
JavaScript
var ctrlPressed = false;
$('#link').click(function () {
var link = 'http://stackoverflow.com/';
if (ctrlPressed) {
window.open(link,'_blank');
} else {
window.location = link;
}
return false;
});
$(document).keydown(function (e) {
if (e.keyCode === 17) {
ctrlPressed = true;
}
});
$(document).keyup(function (e) {
if (e.keyCode === 17) {
ctrlPressed = false;
}
});
HTML
<span id="link">Link to stackoverflow</span>
Version without jQuery
JSFiddle
http://jsfiddle.net/MXuVY/6/
JavaScript
function addEvent(el, eType, fn, uC) {
if (el.addEventListener) {
el.addEventListener(eType, fn, uC);
return true;
} else if (el.attachEvent) {
return el.attachEvent('on' + eType, fn);
} else {
el['on' + eType] = fn;
}
}
var ctrlPressed = false,
a = document.getElementById('link'),
link = 'http://stackoverflow.com/';
addEvent(a, 'click', function () {
if (ctrlPressed) {
window.open(link,'_blank');
} else {
window.location = link;
}
return false;
});
addEvent(document, 'keydown', function (e) {
if (e.keyCode === 17) {
ctrlPressed = true;
}
});
addEvent(document, 'keyup', function (e) {
if (e.keyCode === 17) {
ctrlPressed = false;
}
});
Bind a keystroke event listener to window or document and use it's callback function to do whatever you need.
If you use jquery, its a bit easier to make a more reliable keystroke listener, imho. http://blog.cnizz.com/2008/10/27/javascript-key-listener/
So, this is what you want: http://jsfiddle.net/DerekL/V8yzF/show
$("a").click(function(ev) {
if (ev.ctrlKey) { //If ctrl
window.open(this.attr("href"));
retrun false;
} else if (ev.shiftKey) { //If shift
window.open(this.attr("href"),"_blank", "width=400,height=300");
retrun false;
} else { //If nothing
//do nothing
}
});
I have created a form with malsup's Form Plugin wherein it submits on change of the inputs. I have set up my jQuery script to index drop down menus and visible inputs, and uses that index to determine whether keydown of tab should move focus to the next element or the first element, and likewise with shift+tab keydown. However, instead of moving focus to the first element from the last element on tab keydown like I would like it to, it moves focus to the second element. How can I change it to cycle focus to the actual first and last elements? Here is a live link to my form: http://www.presspound.org/calculator/ajax/sample.php. Thanks to anyone that tries to help. Here is my script:
$(document).ready(function() {
var options = {
target: '#c_main',
success: setFocus
};
$('#calculator').live('submit', function() {
$(this).ajaxSubmit(options);
return false;
});
$(this).focusin(function(event) {
var shiftDown = false;
$('input, select').each(function (i) {
$(this).data('initial', $(this).val());
});
$('input, select').keyup(function(event) {
if (event.keyCode==16) {
shiftDown = false;
$('#shiftCatch').val(shiftDown);
}
});
$('input, select').keydown(function(event) {
if (event.keyCode==16) {
shiftDown = true;
$('#shiftCatch').val(shiftDown);
}
if (event.keyCode==13) {
$('#captured').val(event.target.id);
} else if (event.keyCode==9 && shiftDown==false) {
return $(event.target).each(function() {
var fields = $(this).parents('form:eq(0),calculator').find('select, input:visible');
var index = fields.index(this);
var nextEl = fields.eq(index+1).attr('id');
var firstEl = fields.eq(0).attr('id');
var focusEl = '#'+firstEl;
if (index>-1 && (index+1)<fields.length) {
$('#captured').val(nextEl);
} else if(index+1>=fields.length) {
if ($(this).val() != $(this).data('initial')) {
$('#captured').val(firstEl);
} else {
event.preventDefault();
$(focusEl).focus();
}
}
return false;
});
} else if (event.keyCode==9 && shiftDown==true) {
return $(event.target).each(function() {
var fields = $(this).parents('form:eq(0),calculator').find('select, input:visible');
var index = fields.index(this);
var prevEl = fields.eq(index-1).attr('id');
var lastEl = fields.eq(fields.length-1).attr('id');
var focusEl = '#'+lastEl;
if (index<fields.length && (index-1)>-1) {
$('#captured').val(prevEl);
} else if (index==0) {
if ($(this).val() != $(this).data('initial')) {
$('#captured').val(lastEl);
} else {
event.preventDefault();
$(focusEl).select();
}
}
return false;
});
}
});
});
});
function setFocus() {
with (document.calculator)
var recap = document.getElementById(recaptured.value);
if (recap!=null) {
setTimeout(function() {
if (recap.getAttribute('type')=='text') {
recap.select();
} else {
recap.focus();
}
}, 100 );
}
}
Edit #1: I made a few minor changes to the code, which has brought me a little closer to my intended functionality of the script. However, I only made one change to the code pertaining to the focus: I tried to to disable the tab keydown when pressed on the last element (and also the shift+tab keydown on the first element) in an attempt to force the focus on the element I want without skipping over it like it has been doing. This is the code I added:
$(this).one('keydown', function (event) {
return !(event.keyCode==9 && shiftDown==true);
});
This kind of works. After the page loads, If the user presses tab on the last element without making a change to its value, the focus will be set to the second element. However, the second time the user presses tab on the last element without making a change to its value, and every subsequent time thereafter, the focus will be set to the first element, just as I would like it to.
Edit #2: I replaced the code in Edit #1, with code utilizing event.preventDefault(), which works better. While if a user does a shift+tab keydown when in the first element, the focus moves to the last element as it should. However, if the user continues to hold down the shift key and presses tab again, focus will be set back to the first element. And if the user continues to hold the shift key down still yet and hits tab, the focus will move back to the last element. The focus will shift back and forth between the first and last element until the user lifts the shift key. This problem does not occur when only pressing tab. Here is the new code snippet:
event.preventDefault();
$(focusEl).focus();
You have a lot of code I didn't get full overview over, so I don't know if I missed some functionality you wanted integrated, but for the tabbing/shift-tabbing through form elements, this should do the work:
var elements = $("#container :input:visible");
var n = elements.length;
elements
.keydown(function(event){
if (event.keyCode == 9) { //if tab
var currentIndex = elements.index(this);
var newIndex = event.shiftKey ? (currentIndex - 1) % n : (currentIndex + 1) % n;
var el = elements.eq(newIndex);
if (el.attr("type") == "text")
elements.eq(newIndex).select();
else
elements.eq(newIndex).focus();
event.preventDefault();
}
});
elements will be the jQuery object containing all the input fields, in my example it's all the input fields inside the div #container
Here's a demo: http://jsfiddle.net/rA3L9/
Here is the solution, which I couldn't have reached it without Simen's help. Thanks again, Simen.
$(document).ready(function() {
var options = {
target: '#c_main',
success: setFocus
};
$('#calculator').live('submit', function() {
$(this).ajaxSubmit(options);
return false;
});
$(this).focusin(function(event) {
$('#calculator :input:visible').each(function (i) {
$(this).data('initial', $(this).val());
});
return $(event.target).each(function() {
$('#c_main :input:visible').live(($.browser.opera ? 'keypress' : 'keydown'), function(event){
var elements = $("#calculator :input:visible");
var n = elements.length;
var currentIndex = elements.index(this);
if (event.keyCode == 13) { //if enter
var focusElement = elements.eq(currentIndex).attr('id');
$('#captured').val(focusElement);
} else if (event.keyCode == 9) { //if tab
var newIndex = event.shiftKey ? (currentIndex - 1) % n : (currentIndex + 1) % n;
var el = elements.eq(newIndex);
var focusElement = el.attr('id');
if ($(this).val() != $(this).data('initial')) {
$('#captured').val(focusElement);
} else if ((currentIndex==0 && event.shiftKey) || (currentIndex==n-1 && !event.shiftKey)) {
event.preventDefault();
if (el.attr('type')=='text') {
$.browser.msie ? "" : $(window).scrollTop(5000);
el.select().delay(800);
} else {
$.browser.msie ? "" : $(window).scrollTop(-5000);
el.focus().delay(800);
}
} else if (el.is('select')) {
event.preventDefault();
if (el.attr('type')=='text') {
el.select();
} else {
el.focus();
}
}
}
});
});
});
});
function setFocus() {
with (document.calculator)
var recap = document.getElementById(recaptured.value);
if (recap!=null) {
setTimeout(function() {
if (recap.getAttribute('type')=='text') {
recap.select();
} else {
recap.focus();
}
}, 1 );
}
}
I put my files available to download in my live link: http://www.presspound.org/calculator/ajax/sample.php