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.
Related
In one of "Add product" page, I've select field that shows/hides based on what we select on another select field. This is the code:
$(function() {
$('#warranty_periods').show();
$('#warranty_type').change(function(){
if($('#warranty_type').val() == '1') {
$('#warranty_periods').show();
} else {
$('#warranty_periods').hide();
}
});
});
My problem is how to hide it on the edit page if "warranty_type" was other than '1' while adding the product.
Thanks
If you want the same logic to be invoked when the page loads, then do exactly that. For example, you can define a function that you would use for the event you currently have as well as be immediately invoked. Something like this:
$(function() {
var toggleWarrantyPeriod = function(){
if($('#warranty_type').val() == '1') {
$('#warranty_periods').show();
} else {
$('#warranty_periods').hide();
}
};
toggleWarrantyPeriod();
$('#warranty_type').change(toggleWarrantyPeriod);
});
Try to logout the value of warranty_type using
console.log($('#warranty_type').val());
Check if you are getting the desired value
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())
});
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
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) {
I have radios button on the page, when the page load, it will use length action to check and then hide/show some elements.
When user click on the radio, it will then hide and show some elements.
I'm wondering is this correct way doing it? Or how can it be improved?
$(document).ready(function() {
if ($(".delivery_type:radio").length > 0) {
if ($('#methodPickup').is(':checked')) {
$(".methodDelivery").hide();
$("#addressBookSelectBlock").hide();
$(".customAddress").hide();
}
if ($('#methodDelivery').is(':checked')) {
$(".methodPickup").hide();
}
}
$(".delivery_type:radio").live('click', function() {
if ($(this).val() == "pickup") {
$(".methodDelivery").hide();
$(".methodPickup").show();
$("#addressBookSelectBlock").hide();
$(".customAddress").hide();
}
if ($(this).val() == "delivery") {
if ($(".selectAddressList").length == 0) {
$(".customAddress").show();
}
$(".methodDelivery").show();
$(".methodPickup").hide();
$("#addressBookSelectBlock").show();
}
});
});
You could combine all the hide() and show() functions together:
if ($('#methodPickup').is(':checked')) {
$(".methodDelivery, #addressBookSelectBlock, .customAddress").hide();
}
// etc...
Also, I'm not sure why you are using live() unless the radio buttons are being dynamically added or removed; just use click() if they are not dynamic.
Sharing some HTML and a little more information might help with more suggestions.