Javascript event keypress on hover - javascript

Hi I have multiple divs on the page. I want to raise an alert based on a user hovering over one of the divs and pressing control z. I need to in effect alert out what is in the span dependant upon which div the user is hovered over on.
I have tried with getbyId the problem arises with multiple elements. I am unsure if i need to bind every element.
<div class="mydiv">Keypress here!<span>test</span></div>
<div class="mydiv">Keypress here!<span>test1</span></div>
var pressed = false;
onload = function(e) {
var myElement = document.getElementsByTagName('div');
function keyaction(e, element) {
// var originator = e.target || e.srcElement;
if (e.charCode === 122 && e.ctrlKey) {
//myElement.innerHTML += String.fromCharCode(e.charCode);
alert(true);
}
}
for (var i = 0; i < myElement.length; i++) {
myElement[i].addEventListener("mouseover", function (e)
{
document.addEventListener("keypress", function(t){keyaction(t,e);}, false);
});
myElement[i].addEventListener("mouseout", function ()
{
document.removeEventListener("keypress", keyaction, false);
});
}
}

I think you are overdoing for what is needed. A simple keydown event bind on mouseover and unbind on mouseout would do the trick.
Here's an example :
<div id="wrapper">
<div class="mydiv">Keypress here!<span>test</span></div>
<div class="mydiv">Keypress here!<span>test1</span></div>
</div>
<br>
Keys Pressed :
<br>
<div id="key"></div>
$("#wrapper .mydiv").on("mouseover",function()
{
$(document).bind("keydown",function(e) {
var originator = e.keyCode || e.which;
if(e.ctrlKey)
$("#key").append(originator + ",");
});
}).on("mouseout",function()
{
$(document).unbind("keydown");
});
http://jsfiddle.net/s095evxh/2/
P.S : for some reason , Jsfiddle doesn't allow keydown event on mouseover so you might have to click manually on the div to make it work but the solution works flawless on a local system.

I would suggest that you use the normalized e.which if available. You also have code 122 which is F11 keys code not 90 related to the 'z' key.
Turn the event manager on when over and off when not per your stated desire:
$('.mydiv').on('mouseenter', function () {
$(window).on('keydown', function (e) {
var code = e.which ||e.keyCode;
$('#status').append('we:'+ code);
if (code === 90 && e.ctrlKey) {
$('#status').append('howdy');
}
});
});
$('.mydiv').on('mouseleave', function () {
$(window).off('keydown');
});
Note that I changed to post some text to a fictitious "status" div rather than your alert as that will change where the cursor hovers. Change that to some real action. There MAY be issues with the event bubbling but I will leave that determination to you.
Here is a key code list (google for more/another) https://gist.github.com/lbj96347/2567917
EDIT: simple update to push the span text into the status div:
<div class="mydiv">Keypress here!<span>test</span>
</div>
<div class="mydiv">Keypress here!<span>test1</span>
</div>
<div id="status">empty
<div>
$('.mydiv').on('mouseenter', function () {
var me = this;
$(window).on('keydown', function (e) {
var code = e.which || e.keyCode;
$('#status').append('we:' + code);
if (code === 90 && e.ctrlKey) {
$('#status').append($(me).find('span').text());
}
});
});
$('.mydiv').on('mouseleave', function () {
$(window).off('keydown');
$('#status').text('out');
});

Listen for the keypress on the window and add mouse events to the elements to toggle a variable with what element is active.
var activeElem = null;
$(".mydiv")
.on("mouseenter", function () {
activeElem = $(this);
}).on("mouseleave", function () {
if(activeElem && activeElem.is(this)) {
activeElem = null;
}
});
$(window).on("keydown", function (evt) {
if( activeElem && evt.keyCode===90 && evt.ctrlKey) {
console.log(activeElem.find("span").text());
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="mydiv">Keypress here!<span>test</span></div>
<div class="mydiv">Keypress here!<span>test1</span></div>

To prevent frequent binding/unbinding of the "keydown" handler whenever the user hovers over the <div>, I would simply keep track of the <div> currently being hovered. Something like this:
var hovering = null;
$(document)
.on('keydown', function(e) {
if (e.which === 90 && e.ctrlKey && hovering) {
console.log($('span', hovering).text());
}
})
.on('mouseover', '.mydiv', function(e) {
hovering = this;
})
.on('mouseout', '.mydiv', function() {
hovering = null;
});
.mydiv:hover {
cursor: pointer;
color: gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="mydiv">Test <span>1</span></div>
<div class="mydiv">Test <span>2</span></div>
<div class="mydiv">Test <span>3</span></div>
<div class="mydiv">Test <span>4</span></div>
<div class="mydiv">Test <span>5</span></div>

I would propose the other way around. Listen for the keypress, and select the element which has the hover.
$(document).keypress(function(e) {
if (e.charCode === 26 && e.ctrlKey) {
console.log("Key pressed");
console.log($('.mydiv:hover span').html());
}
});
Codepen Demo

If I am understanding your question correctly, you are looking for the text value of the span within the hovered element. Traversing the DOM from $(this) will get you what you want.
$(".mydiv").mouseover(function (e) {
alert($(this).find('span').text());
});

Related

Switch background if hovering and pressing the shift key?

I'm using this code to switch background when hovering an element and pressing the shift key. It works if I hold the shift key down before I enter the element but not if I'm already on the element and pressing the shift key. Ideas? Thanks!
var shiftPressed = null;
$(document).on({
keydown: function (e) {
if( e.shiftKey )
{
shiftPressed = true;
}
},
keyup: function (e) {
shiftPressed = false;
}
});
$('div').on({
mousemove: function (e) {
if( shiftPressed )
{
$(this).css('backgroundColor', 'red');
}
else
{
$(this).css('backgroundColor', '');
}
},
mouseover: function (e) {
if( shiftPressed )
{
$(this).css('backgroundColor', 'red');
}
else
{
$(this).css('backgroundColor', '');
}
},
mouseleave: function (e) {
$(this).css('backgroundColor', '');
}
}, 'span');
div {
position:absolut;
width:100px;
height:100px;
background:#999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<span>TARGET</span>
</div>
A div cannot be focused (by default); thus, it cannot capture key presses.
However, if you bind the keypress event listener to the document, the event will fire on every key press. Keep the mouseover and mouseleave bound to the div, because they can be fired with a non-focusable element.
Also, a keyboard event is different than a mouse event, so you can't access shiftKey of e in mouseover. Instead, I would use the && operator to test if both conditions are met: the shift key and the mouse in, storing whether the shift key is pressed in a boolean and checking that on mouseover / mouseleave.
var shiftPressed = null; // global data
$(document).on('keyup keydown', function(e) {
shiftPressed = e.shiftKey;
updateDivs();
});
$('div').on({
mouseover: function(e) {
$(this).data('hovered', true); // element-specific data
updateDiv(this);
},
mouseleave: function(e) {
$(this).data('hovered', false); // element-specific data
updateDiv(this);
}
});
function updateDiv(div) {
if (shiftPressed && $(div).data('hovered'))
$(div).css('backgroundColor', 'red');
else
$(div).css('backgroundColor', '');
}
/** updates all divs in document */
function updateDivs() {
$('div').each(function() {
updateDiv(this);
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Hello world</div>
<div>Hi world</div>
You can add a bunch of code to listen to the mouse position and also an event for the keydown and figure out where the cursor is...
There might be a better solution, but this works.
$('div').on("mouseenter", "span", function(e) {
if (e.shiftKey) {
$(this).css('backgroundColor', 'red');
}
}).on("mouseleave", "span", function(e) {
$(this).css('backgroundColor', 'white');
})
let x = 0;
let y = 0;
$(document).on("mousemove", function(e) {
x = e.clientX;
y = e.clientY;
}).on("keydown keyup", function(e) {
$(document.elementFromPoint(x, y)).trigger({
type: e.type==="keydown" ? "mouseenter" : "mouseleave",
shiftKey: true
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<span>Test</span>
<span>Test</span>
<span>Test</span>
<span>Test</span>
<span>Test</span>
<span>Test</span>
<span>Test</span>
<span>Test</span>
<span>Test</span>
</div>
Other way is to set an active element and not worry about the x and y position.
let active;
$('div').on("mouseenter", "span", function(e) {
active = this;
if (e.shiftKey) {
$(this).css('backgroundColor', 'red');
}
}).on("mouseleave", "span", function(e) {
console.log(e)
$(this).css('backgroundColor', 'white');
if (active && !e.custTrigger && $(this).is(active)) active = null
})
$(document).on("keydown keyup", function(e) {
if (active) {
$(active).trigger({
type: e.type==="keydown" ?"mouseenter" : "mouseleave",
shiftKey: true,
custTrigger: true
})
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<span>Test</span>
<span>Test</span>
<span>Test</span>
<span>Test</span>
<span>Test</span>
<span>Test</span>
<span>Test</span>
<span>Test</span>
<span>Test</span>
</div>
This is a bit sloppy but it should work. Just set some vars and then check them whenever an event is fired.
N.B. you have to click once inside the iframe to make it work (so that it can capture keypresses). Presumably on your page you're not using an iframe, so that won't be necessary.
Array.prototype.forEach.call(document.querySelectorAll('.box'), box => {
let hover = false;
let shift = false;
box.addEventListener('mouseenter', ev => {
hover = true;
check();
});
box.addEventListener('mouseleave', ev => {
hover = false;
check();
});
document.addEventListener('keydown', ev => {
shift = ev.shiftKey;
check();
});
document.addEventListener('keyup', ev => {
shift = ev.shiftKey;
check();
});
function check() {
box.style.backgroundColor = shift && hover ? 'red' : '';
}
});
div {
width: 100px;
height: 100px;
background: #999;
margin: 5px;
display: inline-block;
}
<div class="box">
<span>TARGET</span>
</div>
<div class="box">
<span>TARGET</span>
</div>
<div class="box">
<span>TARGET</span>
</div>
A little late to the party, but here's a non jquery example that monitors keystrokes and adds the various shift/ctrl/alt states to the html classList in real time.
css can respond accordingly.
note
to test this code in the stackoverflow snippet, focus is required because the snippet runs in an iframe.
when running as a top level page, the current document is focused by default.
first click "Run Code Snippet" and the select the iframe directly below it - click on the word "shift", and you will be focused in the iframe
you can then tap the shift key.
const html = document.querySelector("html");
["keyup","keydown"].forEach(function(ev){
document.addEventListener(ev,updateHtmlKeyClasses);
});
function updateHtmlKeyClasses(e){
["shiftKey","ctrlKey","altKey"].forEach(function(shiftKey){
html.classList[e[shiftKey]?"add":"remove"](shiftKey);
});
}
div {
margin :10px;
}
html.shiftKey .shiftstate,
html.ctrlKey .ctrlstate,
html.altKey .altstate {
background:lime;
}
.test {
background:cyan;
}
.test:hover {
background:yellow;
}
html.shiftKey .test:hover {
background:red;
}
<div class="shiftstate">
shift
</div>
<div class="ctrlstate">
ctrl
</div>
<div class="altstate">
alt
</div>
<div class="test">
TEST AREA
</div>
keypress doesn't capture the shift-key
This [the keypress event] is similar to the keydown event, except that modifier and non-printing keys such as Shift, Esc, and delete trigger keydown events but not keypress events.

How to manage events on a specific div?

I would like to catch some events for a specific div if the user clicked on the div (focus the div), keyboard events are catch (not if the last click was out of the div (unfocus the div)
I tried some things, but haven't succeeded : JSFiddle
document.getElementById("box").onkeydown = function(event) {
if (event.keyCode == 13) { // ENTER
alert("Key ENTER pressed");
}
}
This code doesn't work even if I click on the div.
Pure JS solution please
The div element isn't interactive content by default. This means that there isn't a case where the return key will ever trigger on it. If you want your div element to be interactive you can give it the contenteditable attribute:
<div id="box" contenteditable></div>
In order to now fire the event you need to first focus the div element (by clicking or tabbing into it). Now any key you press will be handled by your onkeydown event.
JSFiddle demo.
Giving the 'div' a tabindex should do the trick, so the div can have the focus:
<div id="box" tabindex="-1"></div>
If you click on the div it gets the focus and you can catch the event.
JSFIDDEL
If you set 'tabindex' > 0 you can also select the div using TAB.
You could catch all the click events, then check if the event target was inside the div:
var focus_on_div = false;
document.onclick = function(event) {
if(event.target.getAttribute('id') == 'mydiv') {
focus_on_div = true;
} else {
focus_on_div = false;
}
}
document.onkeyup = function(event) {
if (focus_on_div) {
// do stuff
}
}
try this code i hope this work
var mousePosition = {x:0, y:0};
document.addEventListener('mousemove', function(mouseMoveEvent){
mousePosition.x = mouseMoveEvent.pageX;
mousePosition.y = mouseMoveEvent.pageY;
}, false);
window.onkeydown = function(event) {
var x = mousePosition.x;
var y = mousePosition.y;
var elementMouseIsOver = document.elementFromPoint(x, y);
if(elementMouseIsOver.id == "box" && event.keyCode == "13") {
alert("You Hate Enter Dont You?");
}
}
DEMO

How can I use javascript to sequentially show one div at a time?

I'm trying to have a page where one div gets shown and then when the user hits the spacebar, that div gets hidden and the next div gets shown. I'm starting out using CSS to set the visibility of all divs to hidden, but when I press space nothing happens.
$divID = 0;
document.getElementById("div0").style.visibility="visible";
function updateDiv(event){
// If the spacebar was pressed
if (event.type == "keydown" && event.which == 32){
// Hide the current div
$doc.getElementById("div" + $divID).style.visibility="hidden";
++divID;
// Move to next div
$doc.getElementById("div" + $divID).style.visibility="visible";
}
}
// Handle events
document.on("keydown", updateDiv);
You're not very consistent, the variable names change as you go, document is not a jQuery object and has no on() method etc.
var divID = 0;
document.getElementById("div0").style.visibility="visible";
function updateDiv(event){
// If the spacebar was pressed
if (event.type == "keydown" && event.which == 32){
// Hide the current div
document.getElementById("div" + divID).style.visibility="hidden";
++divID;
// Move to next div
document.getElementById("div" + divID).style.visibility="visible";
}
}
// Handle events
$(document).on("keydown", updateDiv);
FIDDLE
How about this fiddle?
var ctr = 1;
var max = 3;
$(document).on('keypress', function (e)
{
if (e.which == 32)
{
$('div').hide();
$('#d' + ctr).show();
ctr++;
if (ctr > max)
ctr = 1;
}
});
I changed up your code a little to use jQuery (since it was listed as a tag, I assumed it was available). This code lets you set up as many divs as you want, doesn't show a new div until the old one is hidden, and keep the last div visible once it's reached:
$('div').hide();
$('div:first').show();
$('body').keypress(function(event) {
$visdiv = $('div:visible');
if(event.which == 32 && !$visdiv.is(':last')) {
$visdiv.hide(400, function() {
$(this).next('div').show();
});
}
});
Fiddle for demonstration.
doc is not defined.
you need var doc = document;
You event handler needs to hook to window.
window.addEventListener("keydown", updateDiv);
You don't need $ in front of regular variables.
You're not really using jQuery, so leave it out.
HTML:
<div class="bloc selected">Bloc 1</div>
<div class="bloc hidden">Bloc 2</div>
<div class="bloc hidden">Bloc 3</div>
<div class="bloc hidden">Bloc 4</div>
JS:
$(document).on('keypress', function (e) {
var code = e.keyCode || e.which;
if(code == 32) {
var next = ($('.selected').next('.bloc').length > 0) ?
$('.selected').next('.bloc') : $('.bloc1');
$('.selected').toggleClass('selected hidden');
next.toggleClass('selected hidden');
}
});
CSS:
.selected {
display:bloc;
}
.hidden {
display:none;
}
FIDDLE: http://jsfiddle.net/Zq8j2/2/

Tinyscrollbar and tab key interaction

How to solve the issue with tab key interaction with tinyscrollbar. When I press tab key to jump to input which is not in view, I get destroyed layout, scroll bars go away, etc. How to solve that?
This is what I have done: Add a tabindex attribute to the element, so that the element can receive focus state from the tab key or mouse click:
<div class="scroll-area" tabindex="1">
<div class="viewport">
<div class="overview">
… CONTENT …
</div>
</div>
<div class="scrollbar">
<span class="track"><span class="thumb"></span></span>
</div>
</div>
Next, I create this function inside the TinyScrollbar plugin to add keyboard support and enable the keyboard navigation on :focus:
$.fn.tinyscrollbar = function(params) {
var options = $.extend({}, $.tiny.scrollbar.options, params),
$this = this;
$this.each(function() {
$(this).data('tsb', new Scrollbar($(this), options));
// Enable keyboard support on focus
$this.on('focus', function () {
$(this).on('keydown', function (e) {
if (e.keyCode == 38 || e.keyCode == 37) {
$(this).tinyscrollbar_keystep(40); // step 40px on single keypress
return false;
} else if (e.keyCode == 40 || e.keyCode == 39) {
$(this).tinyscrollbar_keystep(-40); // step -40px on single keypress
return false;
}
});
});
});
return $this;
};
Then, create .tinyscrollbar_keystep() for updating the scroll step below the .tinyscrollbar_update():
$.fn.tinyscrollbar_update = function(sScroll) {
return $(this).data('tsb').update(sScroll);
};
// Add this functionality for scroll update on keypress (in this case)
$.fn.tinyscrollbar_keystep = function(sScroll) {
return $(this).data('tsb').keystep(sScroll);
};
And .keystep function after initialize()
function initialize() { … }
this.keystep = function(sScroll) {
if (oContent.ratio < 1) {
iScroll -= sScroll;
iScroll = Math.min((oContent[options.axis] - oViewport[options.axis]), Math.max(0, iScroll));
oThumb.obj.css(sDirection, iScroll / oScrollbar.ratio);
oContent.obj.css(sDirection, - iScroll);
}
};
Demo: http://jsbin.com/zaqogidexese/1/edit
I have similar situation here and this is my solution for form input fields:
$(document).on('keydown',function(e) {
switch (e.keyCode ? e.keyCode : e.which) {
case 9: // Tab
if (e.target.localName == 'input') {
content.tinyscrollbar_update($(e.target).position().top);
}
break;
}
});
if you have any wrapper element for each input, update the ".position().top" to ".parent().position().top"

How to show element when a key is pressed, then if it is pressed again, hide the element?

I have this project where I have a side menu which can be toggled using [Ctrl] + [Z]. I want it to hide the very next time the [Ctrl] + [Z] pattern is pressed. My mediocre knowledge of JavaScript hinders me being able to phrase it using google, so I ultimately didn't find anything, so I'm coming here. With the amount of JavaScript I know this technically should work, but logically wouldn't work. Any ideas? Here's my code:
var letter = {
z: 90
...
};
$(document).ready(function() {
$("body").keydown(function(event) {
// toggles element the first time
if(event.ctrlKey && event.which === letter.z) {
$("[data-location='top']").slideDown("fast");
$("[data-location='bottom']").slideDown("fast");
}
// hides element the second time
if(event.ctrlKey && event.which === letter.z) {
$("[data-location='top']").slideUp("fast");
$("[data-location='bottom']").slideUp("fast");
}
});
});
Any help would be very much appreciated! :-)
The .slideToggle() function is what you're looking for.
var letter = {
z: 90
...
};
$(document).ready(function() {
$("body").keydown(function(event) {
if(event.ctrlKey && event.which === letter.z) {
$("[data-location='top']").slideToggle("fast");
$("[data-location='bottom']").slideToggle("fast");
}
});
});
JavaScript:
var letter = {
z: 90
};
$(document).ready(function() {
var visible = false;
$("body").keydown(function(event) {
// toggles element the first time
if(!visible && event.ctrlKey && event.which === letter.z) {
visible = true;
$("[data-location='top']").slideDown("fast");
$("[data-location='bottom']").slideDown("fast");
} else if(visible && event.ctrlKey && event.which === letter.z) {
visible = false;
$("[data-location='top']").slideUp("fast");
$("[data-location='bottom']").slideUp("fast");
}
});
});​
HTML:
<div id="top" class="hidden" data-location="top"></div>
<div id="bottom" class="hidden" data-location="bottom"></div>​
CSS:
#top {height:100px;width:500px;background-color:red;}
#bottom {height:100px;width:500px;background-color:blue;}
.hidden {display:none;}
Fiddle
You only need to bind once to keydown, and then thrw your logic in there. So you code will become:
var letter = {
z: 90
...
};
$(document).ready(function() {
$("body").keydown(function(event) {
// toggles element the first time
if(event.ctrlKey && event.which === letter.z) {
$("[data-location='top']").toggle("fast");
$("[data-location='bottom']").toggle("fast");
}
});
});

Categories

Resources