KeyBoard Navigation for menu using jquery - javascript

I am trying to add keyboard navigation to Menu(ul li based
) , i have bound the keydown event to menu (or should i bind keydown to the document ?)
the handler function used is given below
KeyDown: function(e) {
var toFocus = false;
if (e.keyCode == 38) {
toFocus = $((e.target/* li */).next()[0]);
}
if (e.keyCode == 40) {
toFocus = $((e.target).next()[1]);
}
if (toFocus) {
$(e.target).attr('tabIndex', '-1');
$(toFocus).attr('tabIndex', '0');
toFocus.focus();
return false;
}
}
here i get e.target as html instead of li ?
can u suggest any other way to add keyboard navigation ?

Try to use custom attribute to hold the tabid for up and down.
...KeyDown: function(e) {
var Direction;
if (e.keyCode == 38)
Direction = "toUp";
else Direction = "toDown";
var Focus = $("li[tabid=\""$(e.target.id).attr(Direction)"\"]");
Focus.focus();
}
---
<li ... tabid="1" toUp="-1" toDown= "2" />
<li ... tabid="2" toUp= "1" toDown= "3" />
<li ... tabid="3" toUp= "2" toDown= "4" />
<li ... tabid="4" toUp= "3" toDown="-1" />
The above code is just to show the idea, it is late now and I didn't have time to test it. So please don't vote me down for not working.
Hope that helps

I just wonder if, instead of doing this by your self, why not using an already existing plugin?
jQuery Keyboard Navigation
demo page here
my demo: just to add a demo page of an example

HTML
<body>
<input type="text" id="target-box" >
<ul class="list">
<li class="selected">Hello</li>
<li>World</li>
</ul>
</body>
jQuery
$(document).on('focus','#target-box', function() {
var target_box = $(this);
$(document).on('keyup', function(e) {
if(e.which == 38){ // up arrow
var selected_item = $('.selected');
if(typeof selected_item.prev()[0] !== 'undefined') {
selected_item.prev().addClass('selected');
selected_item.removeClass('selected');
}
} else if (e.which == 40) { // down arrow
var selected_item = $('.selected');
if (typeof selected_item.next()[0] !== 'undefined') {
selected_item.next().addClass('selected');
selected_item.removeClass('selected');
}
}
if (e.keyCode == 13) { // enter
target_box.val($('.selected').html());
}
});
});
CSS
.selected {
width : 50px;
background-color: gray;
}

Related

Jquery binding key to body except a class

I'm trying to bind a key to my entire page except to one class of elements.
$('*').not('.textarea-note').keypress(function (event) {
// if key pressed is space
if (event.which == 32) {
alert('space pressed');
event.preventDefault();
}
});
The problem is that I need to do the preventDefault() and when I'm in a textarea then I can't make a space caracter.
Am I doing something wrong or it's not possible to bind to everything except some class or something.
Thanks in advance !
Edit :
After the comment from Roland, I came up with this instead which is working perfectly.
$(document).keypress(function (event) {
// if key pressed is space
if (event.which == 32 && event.target.nodeName != "TEXTAREA") {
if (videoPlaying) {
pauseVideo();
} else {
playVideo();
}
event.preventDefault();
}
});
I think you are looking for this...
$(document).keypress(function(event) {
// if key pressed is space
if (event.which == 32) {
if (event.target.id !== "a1") {// for class $(event.target).attr('class')
alert('space pressed');
event.preventDefault();
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="a1"></textarea>
<textarea id="a2"></textarea>
<textarea id="a3"></textarea>

Javascript event keypress on hover

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());
});

Triggering jQuery("#collapseMenu").hide(); on pressing Esc key

As mentioned in WA-ARIA 1.0 keyboard interaction, I need to implement the following behaviour:
When a submenu is open and focus is on a menu item in that submenu:
Escape or the Left Arrow key closes the submenu and returns focus to the parent menu item.
To achieve this, I added the following rudimentary javascript code to my page:
if (e.keyCode == 27) {
element = document.getElementById("spanID");
menuElement = document.getElementById("bigMenu");
if (element.className == "glyphicon glyphicon-menu-down") {
element.className = "glyphicon glyphicon-menu-right";
jQuery("#collapseMenu").hide();
menuElement.setAttribute('aria-expanded', false);
sessionStorage.setItem("expand", false);
}
}
That did not work, so it's not the correct way to go about things. Could someone point what is it that I am doing incorrectly.
if you're already using jQuery go all the way.
$(document).on('keypress', function(e){
if (e.keyCode == 27 || e.keyCode == 37) { // escape or left key
var element = $("#spanID"),
menuElement = $("#bigMenu");
if (element.hasClass('glyphicon') && element.hasClass('glyphicon-menu-down')) {
element.removeClass('glyphicon-menu-down').addClass('glyphicon-menu-right');
$("#collapseMenu").hide();
menuElement.attr('aria-expanded', 'false');
sessionStorage.setItem("expand", false);
}
}
});
Try this
document.onkeydown = function(evt) {
evt = evt || window.event;
if (evt.keyCode == 27) {
alert("Escape");
// Here is your code for hiding menu.
}
};

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