using is(':last') to check the last element - javascript

I have a list of input elements. I want to bind a keyup event handler to them, so that whenever user hits Enter, he goes to the next field. But if the input is the last input, then I want to fire the click event of a button, so that user goes to another level. My code is like this:
$('.loginBody input:visible').keyup(function (e) {
if (e.keyCode == 13) {
if ($(this).is(':last')) {
$('#next').click();
}
else {
$(this).closest('input').focus();
}
}
});
However, seems that is(':last') doesn't work. What's wrong?

:last returns the last element of a collection, and $(this) is only a single element collection.
Try using the :last-child selector instead, which will check whether your <input> is really the last one in that group.
Alternatively, if your fields aren't all in the same parent, reverse the sense of your test:
if ($('input').filter(':last').is(this)) {
// this is the last input
}
NB: using .filter(':last') rather than input:last per recommendations at http://api.jquery.com/last-selector/

UPDATED: You could create two different bindings:
$('.loginBody input:last').keyup(function (e) {
if (e.which == 13) {
$("#result").html("last one");
}
});
$('.loginBody input').not(":last").keyup(function (e) {
if (e.which == 13) {
$("#result").html("not last one");
}
});
Here is a working example: http://jsfiddle.net/6gYXk/1/

have you tried is(':last-child') pseudoclass instead?
:last-child means "if this element is the last child of its parent". Note that only element nodes (HTML tags) count, these pseudo-classes ignore text nodes.
edit:
also to focus closest sibling element use:
$(e.target).next('input').focus();
so full code can be:
$('.loginBody input:visible').keyup(function (e) {
if (e.keyCode == 13) {
if ($(this).is(':last-child')) {
$('#next').click();
} else {
$(e.target).next('input').focus();
}
}
});
i've prepared an example at: http://jsfiddle.net/HhvUF/

The nicest solution might well be to use nextAll to see if there are any subsequent sibling elements:
if ($(this).nextAll().length) {
$(this).closest('input').focus();
} else {
$('#next').click();
}
NB that I have turned the if around to make it easier to read.
If you need to check only for input elements, you can supply a selector:
if ($(this).nextAll('input').length) {

Related

OR condition for running function

I have button (".moreAlertsBtn") that run function when user click on it
I would like to run the same function if user click on another button that contain the id "#alertsBtn"
how do I add OR condition?
$(document).on('click','.moreAlertsBtn',function() { }
also - inside the function, can i add contision if user click on the first button and another if he click on the second?
Just separate them using comma(,) like this:
$(document).on('click','.moreAlertsBtn, #alertsBtn',function() { });
can i add condition if user click on the first button and another if
he click on the second?
$(document)
.on('click','.moreAlertsBtn, #alertsBtn',function() {
if($(this).hasClass('moreAlertsBtn')) {
//.moreAlertsBtn clicked
} else {
//#alertsBtn clicked
}
});
how do I add OR condition?
You can use the comma, which in CSS is "or" (but keep reading):
$(document).on('click','.moreAlertsBtn, #alertsBtn',function() { });
But:
also - inside the function, can i add contision if user click on the first button and another if he click on the second?
If you're going to do that, then it makes more sense to use separate handlers:
$(document).on('click','.moreAlertsBtn',function() { });
$(document).on('click','#alertsBtn',function() { });
But answering the question, yes, you can tell like this:
if (this.id === "alertsBtn") {
// It's #alertsBtn
} else {
// Must be .moreAlertsBtn
}
E.g.:
$(document).on('click','.moreAlertsBtn, #alertsBtn',function() {
if (this.id === "alertsBtn") {
// It's #alertsBtn
} else {
// Must be .moreAlertsBtn
}
});
That works because jQuery will call your handler with this referring to the DOM element you "hooked" the event on (even when you're actually doing delegation, as you are in your examples).
You can use comma in-between selectors as follows :
$(document).on('click','.moreAlertsBtn,#alertsBtn',function() { }

find select option with selected property using javascript

I have a view that loads select elements dynamically into the page on certain button clicks. Each of these selects have the same id value followed with an index value based on how many times the button is clicked. so the id would be like
id="my_id_" + numOfClicks;
I have also given all these selectors the same class value
class="selects"
What is the best way to have an event handler for when the selected option changes in any of the drop downs. right now I have the following:
$('.selects').change(function() {
if($('this option:selected').val() == 0) {
}
else {
}
});
So what I'm trying to do is first get the right select element using "this" then figure out which of the options are selected. Is there a better/more efficient way to do this?
As you say these get added at runtime, you'll want a delegated event handler. Within the handler, as the comments have pointed out, it's just $(this).val() to get the selected value of that select box. So:
$("selector for some container they're in").on("change", ".selects", function() {
if($(this).val() == 0) {
}
else {
}
});
For instance, if they're all inside an element with the class container, then:
$(".container").on("change", ".selects", function() {
if($(this).val() == 0) {
}
else {
}
});
If there's no other suitable container, you can just use $(document).on(..., but usually it's better to handle things a bit closer to where they are than that.
Side note: Values are always strings, but == will coerce, so "0" == 0 is true. Still, it's useful to remember that they're strings.
Assuming html input.selects:
$('body').on('change', '.selects', function() {
if($(this).val() == '0') {
}
else {
}
});
http://jsfiddle.net/r4pxx0yy/1/
No quote around this.

jQuery - set data() variable from $(this).val()

I have an e-mail form on my website, with four fields. Three text inputs and a text area. Each field has a default value attribute which serves as its label. I would like these values to be automatically unset/reset on their element's focus and focusout events.
I have the following JavaScript/jQuery code, which creates this behaviour.
$('input,textarea').data('default', "bleh");
$('input,textarea').focus(function() {
if($(this).val() === $(this).data('default')) {
$(this).val('');
}
});
$('input,textarea').focusout(function() {
if ($(this).val() === '')
{
$(this).val($(this).data('default'));
}
});
My problem comes in the storing of the initial data('default') attribute. I had tried using .data('default', $(this).val())... but apparently that is illegal and $(this) is not recognized.
I have tried to find a clean jQuery way to iterate over each of the elements, but I can't seem to find one.
Is there an easy way, using jQuery, to achieve what I want?
Unless I'm mistaken, there's no reason to be setting data properties on the element, you can make use of the elements defaultValue property:
$('input, textarea').focus(function() {
if (this.value === this.defaultValue) {
this.value = '';
}
});
$('input, textarea').focusout(function() {
if (!$.trim(this.value).length) {
this.value = this.defaultValue;
}
});
Here's a fiddle
There is no this, because you're not in a callback. You'll have to iterate over each matched element, setting their default one at a time.
The "clean jQuery way" is simply with each:
$('input,textarea').each(function () {
$(this).data('default', $(this).val());
});
You need iterate through the input elements and then set the value to data using .each()
$('input,textarea').each(function(){
var $this = $(this);
$this.data('default', $this.val())
});

Testing which element has focus when one lost it

What I am trying to do is to test when an element (a SELECT) loses its focus if the focus has been transfered to another specific element (another SELECT). I want to trigger something when the focus is lost and is not on one of the two.
The problem is I test in the first select when it has lost the focus (with the blur event) if the other select has it, but the DOM is not yet updated.
Here's an exemple of what I did:
$select1.on("blur", function() {
if($select2.is(":focus"))
{
// do something
}
else
{
// do something else
}
});
$select1 and $select2 are just two variables that contain the element. I read that JQuery adds an identifier ":focus" when an element gains the focus, but the way I did it, it doesn't work.
In all cases, it goes into the else "do something else".
Matt is right about the order of events but you can be a little more creative.
For example use a setTimeout to delay the check for blur so you know you already fired your focus. Simple.
$select1.on("blur", function() {
window.setTimeout(function() {
if($select2.is(":focus"))
{
// do something
}
else
{
// do something else
}
},100);
});
Try that one.
Because the blur event is distinctly fired before the focus of the new element is, the only thing you can do is set a variable in one event and detect it in the other.
$select1.on('blur', function (e) {
var $that = $(this);
setTimeout(function () {
if (($that.data('focussed') || 0) > e.timeStamp - 5) {
// Do something
} else {
// Something else
}
}, 1);
});
$select2.on('focus', function (e) {
$select1.data('focussed', e.timeStamp);
});
See it working here; http://jsfiddle.net/uZAMm/

Remove class on click anywhere, unless a certain textbox is clicked on

I am trying to improve the following script a little:
$(document).click(function(event) {
$('.home.active').click();
$('.home').removeClass("active");
});
This works, but it works when I don't want it to work. For example, I have a textbox. If that textbox gets focus, the class should not be removed, but if anything else on the page is clicked, the class should be removed. So I tried the following, which does not work:
$(document).click(function(event) {
if( $('#txtHomeSearch').focus() ) {
// don't remove class
} else {
$('.home.active').click();
$('.home').removeClass("active");
}
});
This stops the class being remove altogether, no matter where I click, and the textbox always has focus.
You can use event.target to determine the id of the clicked element:
$(document).click(function(event) {
if (event.target.id === "txtHomeSearch") {
// Don't remove class.
} else {
$('.home.active').click();
$('.home').removeClass("active");
}
});
you can find the source of the event using the target property.
if ($(event.target).prop('id') == 'txtHomeSearch') {
//don't remove class
}
You can try. You might need to drop the # from #txtHomeSearch I can't remember off the top of my head.
$(document).click(function(event) {
if( $(this).attr('id') == '#txtHomeSearch') {
// don't remove class
} else {
$('.home.active').click();
$('.home').removeClass("active");
}
});
Use
$(document).click(function(event) {
if( event.target.id == 'txtHomeSearch' )
return;
$('.home.active').click();
$('.home').removeClass("active");
});
Whatever the $('.home.active').click(); does, might screw it up.
You can use the event.target property to cross-check the element.
The problem is your if( $('#txtHomeSearch').focus() ) ... that's not checking if it's in focus, its GIVING it focus.
to select a focused element you can use the jquery(1.6) :focus selector, use $(document.activeElement) for future reference

Categories