I want to add a class to a list using keyup event but when the keyup event is called it add the class to the list. After some seconds, the class from the list will be removed then i try to use setinterval on the callback function. It work but if i try to navigate through the list it behave funny.
Here is the code
(function(){
var AutocompleteActivities = {
init: function(config)
{
this.config = config;
$("#keywords").on("keyup", this.confirm);
},
confirm: function(e)
{
var self = AutocompleteActivities;
var con = self.config.div;
key = e.keyCode;
press = e.timeStamp
//check whether there is a key up invent in the search textfield and up or down arrow is press
if(press != "" && e.keyCode == 40 || e.keyCode == 38)
{
if(con.css("display") == "block")
{
setInterval(function(){
self.navigation(key)},500)
}
}
},
navigation: function(key)
{
var con = this.config.div, // #options - the container of the autocomplete
li = con.find("ul").find(">li"),
totalLi = li.length,
firstLi = li.first(),
current = 1; // it should be zero for debug reasons it is one
if(key == 40)
{
if(current != 0) // check whether the autoComplete selection is the first in the
{
firstLi.addClass("selection")
++current
con.find("ul li").filter(function() {
return $(this).hasClass("selection");
}).next().addClass("selection").end().removeClass("selection")
return false;
}
}
}
}
AutocompleteActivities.init({
div: $("#options"),
})
})()
Related
I have a function which gets called on any keypress.
On textarea focus I disable the keypress function.
On textarea blur my keypress function call should be enabled again, but for some reason it is not.
This is the page: http://119.247.250.128/wasyoku/
function Kyprime()
{
document.getElementById('q').onfocus = function() {return false};
if (event.keyCode == 4) turn() // control d
if (event.keyCode == 126) hideframe() // ~
if (event.keyCode == 96) { // `
parent.C.location = (parent.C.location != wasyoku+"home/prime.html")
? "home/prime.html" : "n/FBwasyoku.html" }
if ( parent.C.location != wasyoku + "ascii.html"
&& parent.C.location != wasyoku + "masterpiece/pagelet.html"
&& parent.C.location != wasyoku + "masterpiece/artwork.html"
&& parent.C.location != wasyoku + "masterpiece/webwork.html")
{
if (event.keyCode == 32) // spacebar =
parent.C.location = "../masterpiece/pageletNews.html"
else if (event.keyCode == 3 | event.keyCode == 13) // enter return
parent.C.location = "../ascii.html"
}; document.onkeypress = Kyprime
How can I make my keypress function keep on working after textarea blur?
You could create two event listeners to define whether your keypress event should trigger the Kyprime function or not:
var textarea = document.getElementById('q');
textarea.addEventListener('blur', function() {
document.onkeypress = Kyprime;
});
textarea.addEventListener('focus', function() {
document.onkeypress = null;
});
Then on your Kyprime function you could remove this line:
document.getElementById('q').onfocus = function() {return false};
WORKING EXAMPLE: https://jsfiddle.net/czaj1a0s/1/
I have this code in my JQuery grid:
onSelectRow:function(rowid){
var r=$("#myGrid").getRowData(rowid);
var col1 = r.column1;
$("#myGrid #"+rowid).keyup(function(e) {
if(e.keyCode == 46) {
alert(col1);
}
});
}
my actual purpose is to delete the selected row record in database when [delete] key is pressed on the keyboard.
I am testing the code with alert(), as given code above.
The problem is, whenever I clicked on the same row multiple times, say 4 times, followed by single [delete] key press, the alert popup 4 times. However, it works fine when I clicked 4 different rows, followed by single [delete] key press.
This is the illustration of the situation(clicked rows, followed by [delete]):
clicked row(in sequence) alert popups
row1 ->[delete] row1
row1, row2, row3, row4 ->[delete] row4
row1, row1, row1, row2 ->[delete] row2
row1, row2, row3, row3 ->[delete] row3, row3
row1, row2, row2, row2 ->[delete] row2, row2, row2
row1, row1, row1, row1 ->[delete] row1, row1, row1, row1
Why and how to overcome this problem? Or maybe there is another better way to do this?
Yes, each time You select a row, You're registering a keydown event listener.
Perhaps should You take your keydown event handler out like this:
$("#myGrid tr").keyup(function(e) {
var rowid = parseInt($(this).attr("id"));
var r=$("#myGrid").getRowData(rowid);
var col1 = r.column1;
if(e.keyCode == 46) {
alert(col1);
}
});
EDIT: If your grid is generated dynamically:
$("#myGrid").on("keyup", "tr", function(e) {
var rowid = parseInt($(this).attr("id"));
var r=$("#myGrid").getRowData(rowid);
var col1 = r.column1;
if(e.keyCode == 46) {
alert(col1);
}
});
You may need to somehow check that the row is selected.
What seems to be happening is when you click a row, onSelectRow is called. In this function you bind a keydown event on row. So, when you click the row 4 times, onSelectRow will be called 4 times, this will in-turn bind the event 4 times and so you see an alert 4 times.
Solution is NOT to bind the keydown event inside onSelectRow function. You should rather bind keyup outside onSelectRow function this way :
$("#myGrid someRowSelector").keyup(function(e) {
if(e.keyCode == 46) {
alert(col1);
}
});
Where someRowSelector identifies the rows to bind events on.
Instead of keydown event try keyup event
onSelectRow:function(rowid){
var r=$("#myGrid").getRowData(rowid);
var col1 = r.column1;
$("#myGrid #"+rowid).keyup(function(e) {
if(e.keyCode == 46) {
alert(col1);
}
});
}
if you dont want to modify the plugin you can make extend function for your jqgrid like this.
$.extend($.fn.jqGrid, {
bindKeysCustom: function (settings) {
var o = $.extend({
onEnter: null,
onSpace: null,
onLeftKey: null,
onRightKey: null,
onSupr: null,
scrollingRows: true
}, settings || {});
return this.each(function () {
var $t = this;
if (!$('body').is('[role]')) { $('body').attr('role', 'application'); }
$t.p.scrollrows = o.scrollingRows;
$($t).keydown(function (event) {
var target = $($t).find('tr[tabindex=0]')[0], id, r, mind,
expanded = $t.p.treeReader.expanded_field;
//check for arrow keys
if (target) {
mind = $t.p._index[$.jgrid.stripPref($t.p.idPrefix, target.id)];
if (event.keyCode === 37 || event.keyCode === 38 || event.keyCode === 39 || event.keyCode === 40) {
// up key
if (event.keyCode === 38) {
r = target.previousSibling;
id = "";
if (r) {
if ($(r).is(":hidden")) {
while (r) {
r = r.previousSibling;
if (!$(r).is(":hidden") && $(r).hasClass('jqgrow')) { id = r.id; break; }
}
} else {
id = r.id;
}
}
$($t).jqGrid('setSelection', id, true, event);
event.preventDefault();
}
//if key is down arrow
if (event.keyCode === 40) {
r = target.nextSibling;
id = "";
if (r) {
if ($(r).is(":hidden")) {
while (r) {
r = r.nextSibling;
if (!$(r).is(":hidden") && $(r).hasClass('jqgrow')) { id = r.id; break; }
}
} else {
id = r.id;
}
}
$($t).jqGrid('setSelection', id, true, event);
event.preventDefault();
}
// left
if (event.keyCode === 37) {
if ($t.p.treeGrid && $t.p.data[mind][expanded]) {
$(target).find("div.treeclick").trigger('click');
}
$($t).triggerHandler("jqGridKeyLeft", [$t.p.selrow]);
if ($.isFunction(o.onLeftKey)) {
o.onLeftKey.call($t, $t.p.selrow);
}
}
// right
if (event.keyCode === 39) {
if ($t.p.treeGrid && !$t.p.data[mind][expanded]) {
$(target).find("div.treeclick").trigger('click');
}
$($t).triggerHandler("jqGridKeyRight", [$t.p.selrow]);
if ($.isFunction(o.onRightKey)) {
o.onRightKey.call($t, $t.p.selrow);
}
}
}
//check if enter was pressed on a grid or treegrid node
else if (event.keyCode === 13) {
$($t).triggerHandler("jqGridKeyEnter", [$t.p.selrow]);
if ($.isFunction(o.onEnter)) {
o.onEnter.call($t, $t.p.selrow);
}
} else if (event.keyCode === 32) {
$($t).triggerHandler("jqGridKeySpace", [$t.p.selrow]);
if ($.isFunction(o.onSpace)) {
o.onSpace.call($t, $t.p.selrow);
}
} else if (event.keyCode === 46) {
$($t).triggerHandler("jqGridKeySupr", [$t.p.selrow]);
if ($.isFunction(o.onSupr)) {
o.onSupr.call($t, $t.p.selrow);
}
}
}
});
});
}
});
Then, instead call your jqgrid like this
grid.jqGrid('bindKeys');
You have to call it like this
grid.jqGrid('bindKeysCustom', {
'onSupr': function (rowid) { }
});
Register one keydown-listener and then loop through a list of elements.
This is how I would do this:
var colsToDelete = {};
$(document).keydown(function(e) {
if(e.keyCode == 46) {
for(var id in colsToDelete) {
var data = colsToDelete[id];
alert(data);
}
colsToDelete = {};
e.preventDefault();
}
});
And your code looks like this:
onSelectRow:function(rowid){
var r = $("#myGrid").getRowData(rowid);
colsToDelete[rowid] = r.column1;
}
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);
At the url http://www.candyundies.com/template_non_product.php, I am using an autocomplete script on the search box for suggestions. I have tested and is working in current versions of Chrome, Safari, Opera, Firefox and IE 8. However, I noticed in IE 8, it is throwing an Object expected error after the first letter is typed in the search box but the script continues to work flawlessly. I'm sure it is a syntax error or something small I have overlooked but I cannot seem to find the problem. Any help would be much appreciated.
Contents of autocomplete.js:
// global variables
var acListTotal = 0;
var acListCurrent = -1;
var acDelay = 100;
var acURL = null;
var acSearchId = null;
var acResultsId = null;
var acSearchField = null;
var acResultsDiv = null;
function setAutoComplete(field_id, results_id, get_url) {
// initialize vars
acSearchId = "#" + field_id;
acResultsId = "#" + results_id;
acURL = get_url;
// create the results div
$("#auto").append('<div id="' + results_id + '"></div>');
// register mostly used vars
acSearchField = $(acSearchId);
acResultsDiv = $(acResultsId);
// on blur listener
acSearchField.blur(function(){ setTimeout("clearAutoComplete()", 100) });
// on key up listener
acSearchField.keyup(function (e) {
// get keyCode (window.event is for IE)
var keyCode = e.keyCode || window.event.keyCode;
var lastVal = acSearchField.val();
// check an treat up and down arrows
if(updownArrow(keyCode)){
return;
}
// check for an ENTER or ESC
if(keyCode == 13 || keyCode == 27){
clearAutoComplete();
return;
}
// if is text, call with delay
setTimeout(function () {autoComplete(lastVal)}, acDelay);
});
}
// treat the auto-complete action (delayed function)
function autoComplete(lastValue) {
// get the field value
var part = acSearchField.val();
// if it's empty clear the resuts box and return
if(part == ''){
clearAutoComplete();
return;
}
// if it's equal the value from the time of the call, allow
if(lastValue != part){
return;
}
// get remote data as JSON
$.getJSON(acURL + part, function(json){
// get the total of results
var ansLength = acListTotal = json.length;
// if there are results populate the results div
if(ansLength > 0){
var newData = '';
// create a div for each result
for(i=0; i < ansLength; i++) {
newData += '<div class="unselected">' + json[i] + '</div>';
}
// update the results div
acResultsDiv.html(newData);
acResultsDiv.css("display","block");
// for all divs in results
var divs = $(acResultsId + " > div");
// on mouse over clean previous selected and set a new one
divs.mouseover( function() {
divs.each(function(){ this.className = "unselected"; });
this.className = "selected";
});
// on click copy the result text to the search field and hide
divs.click( function() {
acSearchField.val(this.childNodes[0].nodeValue);
clearAutoComplete();
});
} else {
clearAutoComplete();
}
});
}
// clear auto complete box
function clearAutoComplete() {
acResultsDiv.html('');
acResultsDiv.css("display","none");
}
// treat up and down key strokes defining the next selected element
function updownArrow(keyCode) {
if(keyCode == 40 || keyCode == 38){
if(keyCode == 38){ // keyUp
if(acListCurrent == 0 || acListCurrent == -1){
acListCurrent = acListTotal-1;
}else{
acListCurrent--;
}
} else { // keyDown
if(acListCurrent == acListTotal-1){
acListCurrent = 0;
}else {
acListCurrent++;
}
}
// loop through each result div applying the correct style
acResultsDiv.children().each(function(i){
if(i == acListCurrent){
acSearchField.val(this.childNodes[0].nodeValue);
this.className = "selected";
} else {
this.className = "unselected";
}
});
return true;
} else {
// reset
acListCurrent = -1;
return false;
}
}
Issue resolved. See comment by ocanal.
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;
}
};