I am trying to apply some simple functionality to a footable. I have a footable were you can tab through the rows. At each row I wish to be able to click enter to expand hidden content/details for the current selected row, but I am having some trouble locating the click function and adding keypress enter.
This is currently some jquery that i have added, but this won't work simply because the HTML is render from javascript, meaning that the hidden content is not render before i click on the row with the mouse:
$("tbody").delegate("*", "focus blur", function () {
var elem = $(this);
setTimeout(function () {
elem.toggleClass("focused", elem.is(":focus"));
}, 0);
});
$('.footable > tbody > tr').keypress(function (e) {
if ($(this).hasClass("focused") && e.which == '13') {
//alert('test');
$('.footable-row-detail').css({ "display": "table-row" });
}
});
As per your first example, use a delegated event handler for the keypress event too:
$('.footable > tbody').on('keypress', '> tr', function (e) {
if ($(this).hasClass("focused") && e.which == '13') {
//alert('test');
$('.footable-row-detail').css({ "display": "table-row" });
}
});
So long as the .footable table element exists always, the events bubble up to the event handler there. Then the '> tr' selector is applied to the element in the bubble-chain. That means the row only has to match at event time.
If the footable table itself is dynamic, move up the ancestors to something more permanent. document is the default if nothing else is closer/convenient (never use body for delegated events as it has a bug caused by styling):
$(document).on('keypress', '.footable > tbody > tr', function (e) {
if ($(this).hasClass("focused") && e.which == '13') {
//alert('test');
$('.footable-row-detail').css({ "display": "table-row" });
}
});
Found out what the problem was.
$table.find(opt.toggleSelector).unbind('keypress').keypress(function (e) {
if ($(this).hasClass('focused') && e.which == 13) {
//alert('You pressed enter!');
$(this).trigger(trg.toggleRow);
}
});
Related
How can I remove a keypress event handler after I have set one for an element?
I have a search box with the id #sb that lists search suggestions upon typing via autocomplete, and then goes to the very first suggestion upon pressing enter if there is one.
It works fine if the user enters a search string which does not exist. Pressing ENTER goes nowhere as it should.
However, if a valid search suggestion is returned, and then the user changes their mind and decides to search for another string for which there is no search suggestion... pressing ENTER still goes to the previously suggested search result.
For example, if the user searches for "hot dogs", deletes that entirely, and then searches for "asgdoksadjgoawhet" then upon pressing enter they will be redirected to http://example.com/hot-dogs, when in fact nothing should happen.
Below is the response section of my autocomplete code:
response: function( event, ui ) {
if(typeof ui.content[0] == 'undefined') {
//no search results exist
//make enter do nothing
$('#sb').keypress(function(e) {
if(e.which == 13) {
e.preventDefault(); //does not work
$('#sb').off('keypress', '#sb'); //does not work, either
}
});
} else {
//search results exist
//make ENTER go to the first suggested result
$('#sb').on('keypress', function(e) {
if(e.which == 13) {
window.location.href = 'http://example.com/'+ui.content[0].id;
}
});
}
}
Should I not be using anonymous functions, perhaps?
If you want to unbind it directly after use you can use .one
This will fire the event only once:
$('#sb').one('keypress', function(e) {
if(e.which == 13) {
//do stuff
}
});
If you however want to unbind the event at any other time you can do this:
var kbEvent = $('#sb').on('keypress', function(e) {
if(e.which == 13) {
//do stuff
}
});
.... some other code ...
$('#sb').off(kbEvent);
$( "#foo" ).bind( "click", handler );
function handler(){
//do the stuff
}
//after some condition
$( "#foo" ).unbind( "click", handler );
Bind the reference of function to event callback, so you can later use it to unbind.
$('#sb').on("keypress", function(e) {
if(e.which == 13) {
$(this).off(e);
}
});
$('#sb').off('keypress', '#sb');
removes the event handler on the child elements '#sb' of the element '#sb'.
$('#sb').off('keypress'); removes the event handler on '#sb'.
Another exemple
$( "#dataTable tbody" ).on( "click", "tr", function() {
//...
}); adds an event handler on each tr elements in "#dataTable tbody"
$( "#dataTable tbody" ).off( "click", "tr"); removes it from each tr elements in "#dataTable tbody"
Try this little example it shows you how to bind and unbind an event.
html
<div>
<input id="bind_me"/>
<div>
</div>
</div>
jQuery code
$('#bind_me').on('keypress', function(e)
{
if(e.which==='q'.charCodeAt(0) || e.which==='q'.charCodeAt(0) )
{
$('#bind_me').off('keypress');
}
var tmp = $(this).next().text();
$(this).next().text(tmp+String.fromCharCode(e.which));
});
I have six sliders on a single page, each in its own section. As you scroll, the section in view gets a CSS class of 'active.' I'm trying to disable keyboard navigation for every slider except the slider in the active section.
My current code looks like this:
$('section').not('.active').on('keydown', function(e){
if(e.keyCode === 37 || e.keyCode === 39) {
e.preventDefault();
return false;
}
});
No avail. They all move. Is my selector wrong? Is there a better way to disable left and right keyboard navigation for a group of elements?
I'm using Unslider.
It looks like the keydown event is assigned to document so first you have to unbind the existing event assigned by the plugin and bind a new keydown event which changes the slide on next and prev.
If you have used $('.banner').unslider(); (ie. a css selector to select all sliders) to initialize the sliders then the following code will do the job
$(function() {
var banners = $('.banner');
banners.unslider();
$(document).unbind('keydown').keydown(function(e){
var index = banners.index($('.active')[0]) + 1;
var data = $('.active').data('unslider'+index);
if(e.keyCode === 37 ) {
e.preventDefault();
data.prev();
return false;
}
if(e.keyCode === 39 ) {
e.preventDefault();
data.next();
return false;
}
});
});
Sample FIDDLE
UPDATE
I have made a small correction in the selector for active banner
FIDDLE
As you can see I have changed $('.active') to $('div.active')
I would recommend you to put a very specific class name than active
you can even replace $('div.active') with $('div.portfolio-slider.active')
Thanks to Cerlin Boss for the help! Here's the solution I ended up using, including arrow navigation that works for individual sliders on a multi-slider page:
$(document).ready(function (){
$('.portfolio-slider').each(function(){
var $this = $(this);
$this.unslider({
delay: false,
dots: false,
fluid: true,
keys: true,
loop: true
}).find('.unslider-arrow').click(function(event){
event.preventDefault();
if ($(this).hasClass('next')) {
$this.data('unslider').next();
} else {
$this.data('unslider').prev();
}
});
$(document).unbind('keydown').keydown(function(e){
var active = $('div.portfolio-slider.active');
if(e.keyCode === 37 ) {
e.preventDefault();
active.data('unslider').prev();
return false;
}
if(e.keyCode === 39 ) {
e.preventDefault();
active.data('unslider').next();
return false;
}
});
});
});
The key, as Cerlin Boss pointed out, is to unbind keydown events, and then rebind them to target only the slider with a specific class, in my case 'active'. Hope this helps someone!
I'm trying to add a class on right-click of an element and then remove it when anything else on the page is clicked.
I'm using jQuery.
My function is this so far:
$(".classElement").live('mousedown', function(e) {
if( (e.which == 3) ) {
$(".classElement").addClass("active");
}
e.preventDefault();
}).live('contextmenu', function(e){
e.preventDefault();
});
However, this adds the "active" class to all ".classElement" in the doc, rather than the individual one being clicked. I want to only add the class to the element being clicked.
Also, how can I remove the class when anything else is clicked?
You can removClass active on click of body element, but for this you have to stop event propagation when you are clicking on current element.
$(document).on('mousedown','.classElement', function(e) {
e.preventDefault();
if( (e.which == 3) ) {
$(this).addClass("active");
}
e.stopPropagation();
}).on('contextmenu','.classElement', function(e){
e.preventDefault();
});
$(document.body).click(function(){
$(".classElement").removeClass("active");
});
You can use $(this) to target current clicked element, so you can do:
$(this).addClass("active");
instead of:
$(".classElement").addClass("active");
Also, since .live() was removed since version 1.9, you should use .on() instead.
to target specific element:
$(this).addClass("active");
and to remove it when anything else is clicked, add this:
$(window).one("click", function(){
$(this).removeClass("active");
});
This adds a one time only click event listener to the window.
Use this code
$(".classElement").live('contextmenu', function(e){
e.preventDefault();
if( (e.which == 3) ) {
$(this).addClass("active");
}
});
and then remove class on document click
$(document).click(function(){
$(".classElement").removeClass("active");
});
I'm trying to create a menu where when a div is clicked it opens another div with the contents. I wanted it close when the user clicked anywhere else. That part seems to work, however it also closes when the div itself is clicked.
The user should be able to click inside the div without it closing,
I was using answers from this question as a guide but they were using ordered lists instead of divs, is there an issue with e.target.class ?
Thanks for any help.
$('.trigger').click(function (e) {
e.stopPropagation();
$('.header-menu-container').hide();
$(this).next('.header-menu-container').slideDown();
});
$(document).click(function (e) {
if (e.target.class == 'header-menu-container' || e.target.class == 'header-menu-contents')
return;
$('.header-menu-container').slideUp();
});
Please see here: http://jsfiddle.net/75JaR/3/
Change class to className...
$(document).click(function (e) {
if (e.target.className == 'header-menu-container' || e.target.className == 'header-menu-contents') return;
$('.header-menu-container').slideUp();
});
updated jsfiddle...
Incidentally, if you add any further classes to the container and contents elements then the above code won't work. The following code would be more suitable as it will work no matter how many extra classes you add...
$(document).click(function (e) {
var $this = $(e.target);
if ($this.hasClass("header-menu-container")) return;
if ($this.hasClass("header-menu-contents")) return;
$('.header-menu-container').slideUp();
});
use this instead:
if ( $(e.target).is('.header-menu-container') || $(e.target).is('.header-menu-contents') )
stop the event bubbling up to the document when the div is clicked, then you don't have to do the class check.
http://jsfiddle.net/75JaR/7/
$('.trigger').click(function (e) {
e.stopPropagation();
$('.header-menu-container').hide();
$(this).next('.header-menu-container').click(function(e){
e.stopPropagation();
}).slideDown();
});
$(document).click(function (e) {
$('.header-menu-container').slideUp();
});
Make a click event on the div to stop hiding it once clicked on it.
$('.trigger').click(function (e) {
e.stopPropagation();
$('.header-menu-container').hide();
$(this).next('.header-menu-container').slideDown();
});
$(document).click(function (e) {
if (e.target.class == 'header-menu-container' || e.target.class == 'header-menu-contents') return;
$('.header-menu-container').slideUp();
$('.header-menu-container').click(function(){
return false;
});
});
I want to show a div on link click and hide if click outside the link or div.
login
<div class="login-panel">
<input type="text" id="LoginForm_username" name="LoginForm[username]" class="field" value="username">
<input type="password" id="LoginForm_password" name="LoginForm[password]" class="field" value="password">
<input type="submit" value="Login" class="loginBtn">
</div>
initially div is hidden. and script is
$(document).ready(function() {
$("#login").click(function () {
$("div.login-panel").toggle();
});
$("body").click(function(e){
if(e.target.className == "login" || e.target.className == "login-panel") {
//alert("do't hide");
}
else {
$(".login-panel").hide();
}
});
});
when I click on link div shows and overlaps some other elements, and when I click outside the body it dies.
But the problem is when I click on input box to enter username login-panel div get hides.
why div hide?
any guidance will be appreciated.
http://jsfiddle.net/thirtydot/F4p2x/15/
$(document).ready(function() {
$("#login").click(function(e) {
$(".login-panel").toggle();
e.stopPropagation();
});
$(document).click(function(e) {
if (!$(e.target).is('.login-panel, .login-panel *')) {
$(".login-panel").hide();
}
});
});
You should do it like this:
http://jsfiddle.net/VWENB/1/
$("#login").click(function(e) {
$("div.login-panel").toggle();
e.stopPropagation();
});
$("body").click(function(e) {
if (e.target.className == "field") {
//alert("do't hide");
} else {
$(".login-panel").hide();
}
});
When you are clicking on a sub-element, your condition (e.target.className) is not applied to your parent element (<div class="login-panel">). But you can use the closest function of jQuery (see here) in order to test if you are in your parent element :
if(e.target.className == "login" || $(e.target).closest(".login-panel").length === 1) {
...
}
PROBLEM is when i click on input box to enter username login-panel div
get hides. why div hide?
Because, you clicked the body too, when clicking in the div. Then both events are triggered. Check out event.stopPropagation() which you may use in the else part of body.onclick.
That because your input lies inside #login div, so if you click inside this div it will hide. So you can use jquery :not selector to specify those excluded elements
$(document).ready(function () {
$("#login,:not('#LoginForm_username'),:not('#LoginForm_password')").click(function () {
$("div.login-panel").toggle();
});
$("body").click(function (e) {
if (e.target.className == "login" || e.target.className == "login-panel") {
//alert("do't hide");
} else {
$(".login-panel").hide();
}
});
});
DEMO
Here you go:
$(document).ready(function () {
$("#login").click(function () {
$("div.login-panel").toggle();
});
$("body").click(function (e) {
if (e.target.nodeName != "INPUT" && e.target.className!= "login" && e.target.className!= "login-panel") {
$(".login-panel").hide();
}
});
});
You were using the wrong selector in your if to check if a click on the body wasn't targeting a input element.
Fiddle
Just find mouse when the click event occur,
<script type="text/javascript">
find_mouse = false;
$(document).ready(function()
{
$('.login-panel').hover(function(){
find_mouse=true; // if mouse on login-panel
}, function(){
find_mouse=false; // not on login panel
});
$("body").click(function(){
if(! find_mouse) // if not on login panel
$('.login-panel').hide();
});
});
</script>
As the other saying clicking input cause event triggering in the body so you should check if the sender is child of the login I think below code do the trick;
$("body").click(function (e) {
var $sender = $(e.target);
if ($sender.closest(".login-panel").length) {
return ;
}
$(".login-panel").hide();
});
Edit : update the condition with closest as it is correct function.
Begins with the current element, Travels up the DOM tree until it finds a match for the supplied selector. The returned jQuery object contains zero or one element for each element in the original set.