Normally, when a user selects an item in a <select>, the 'change' event gets fired.
However, when you change the value of the same <select> with $('select').val('something'), the event doesn't get fired.
I know I could do:
$('select').val('something').trigger('change');
but that's not the problem I'm trying to solve...
Is there a way to get the change event working, without manually triggering it?
I put together a quick JsFiddle to better explain the problem, check it out:
http://jsfiddle.net/W723K/1/
Cheers
It's not possible, unless you manually trigger the change function. If you don't like typing that code several times, extend the jQuery object. Fiddle: http://jsfiddle.net/W723K/2/
(function($){
$.fn.changeVal = function(value){
return this.each(function(){
$(this).val(value).trigger('change');
});
}
})(jQuery);
//Usage:
$('select').changeVal('something');
Related
I'm trying to use FancySelect.js to style the select boxes used on WooCommerce and have managed a few but I'm struggling with the Variation form on product pages.
While FancySelect triggers a change event on the original select box, it appears to affect nothing. Looking at the javascript used in the variations form, it looks like they've unbinded the change event on the select box and are handling it some other way, by triggering events on the .variations_form instead. I can't seem to get it to work though.
My code is something along the lines of:
$('.summary select').fancySelect().on('change.fs', function() {
$(this).trigger('change.$');
$('.variations_form').trigger('woocommerce_variation_select_change');
});
I've tried triggering multiple events but none seem to have any affect.
Any ideas?
Thanks.
So it turns out that the original trigger didn't work, for reasons I can't quite work out. However, manually triggering a change event on the original select box worked to some degree, but it wouldn't update fancySelect's "Trigger" element. I think this was because the original select's options didn't get a :selected attribute (for whatever reason). I've had to add a custom event to fancySelect to manually trigger it's updateText() method.
Updated code:
$('.summary .options li').on('click', function(){
$('.summary select').trigger('change').trigger('select.fs');
});
And the additional event for fancySelect (which I'll try contribute to if I get chance):
sel.on('select.fs', function(){
updateTriggerText();
});
Cheers.
I have problems testing my JavaScript. A part of my test looks like
$('#activityType').val("33");
$('#favorite').click();
The $('#activityType') is a select field and I want to select the option with value "33". Now I expected, that this would be a change, so that my function in my program like
$('body').on('change', '.item-select', function() {
var itemRow = $(this).parent().parent();
changeBookableItemInputFields(itemRow);
});
will be executed.
The $('#activityType') has got the class-attribute item-select, so I don´t understand, why $('#activityType').val("33"); is no change. I changed the value and the css-attribute is there. The body should be able to find it and the function should be executed.
Can anybody tell me, why it doesn´t work?
Changing a value with JavaScript does not trigger the events, you need to manually fire it. jQuery makes that easy with .trigger(eventName)
$('#activityType').val("33").trigger("change");
Use trigger() for calling any event using program.
change event is for user types into the input.
You can manually call the any event event using after setting the value:
$('#activityType').trigger("change");
I am new to jQuery and found a couple of different approaches for this online but nothing worked for me so I hope someone can help me.
I have a number of Selects. Each of them has one option with a class "defaultSel" to indicate that this should be selected as the default when a certain event is triggered.
My approach was the following which does change the Selects value but I can't get it to actually trigger the change (neither adding .change() nor .trigger('change') worked for me here).
Also, if there is a way to avoid .each here at all please let me know as well.
My jQuery:
$(this).closest('div').nextAll('div.hiddenDiv').show().find('.defaultSel').each(function(){
$(this).prop('selected', true).change();
});
Many thanks in advance for any help,
Mike
If your option is the thing with the defaultSel class then this should work:
$(this).closest('div').nextAll('div.hiddenDiv').show().find('select:has(option.defaultSel)').each(function(){
$(this).find('option.defaultSel').prop('selected', true).end().change();
});
Just changing two things here:
find('select:has(option.defaultSel)')
will get the select set you're actually wanting, and
$(this).find('option.defaultSel').prop('selected', true).end().change();
this here is the select so you need to find the default option, then end() will return you to the select and you can trigger change() on it.
I have a table with data, and when I click on a cell in a certain column, I want it to change into a select dropdown for the user to choose a category for that row (which will be written to the database by AJAX but that'll come later).
I've done something similar before with text boxes using this, which works great, but I'm not sure if I'm modifying it correctly.
I've created a JSFiddle which shows the problem I'm having. I click on the text and it turns into a select element as expected, but when I click on that to choose an option, the dropdown doesn't stay open and I can't select anything. Debugging has shown me that when I click the dropdown, it runs the $("td.ChooseType").click() routine again so I've tried to suppress that by removing the class then adding it back on on selection, but that hasn't solved it. On the rare occasion that the dropdown stays open, I am unable to select anything by either mouse or keyboard.
All of the users will be on IE8 unfortunately, so I need it to be compatible with that.
Thanks!
You need to use event delegation, as otherwise that click event is always bound to that td - regardless of whether its class changes.
Simply change:
$("td.ChooseType").click(function() {
To:
$("table").on('click', '.ChooseType', function () {
JSFiddle demo.
Purely as an alternative to the accepted answer, you can remove an attached handler with unbind. So instead of adding and removing the class, you could unbind and rebind your handler. Only requirement is that the function can't be in-line, but has to be declared separately.
example: http://jsbin.com/qiqunici/1/edit
var handler = function () {
$(this).unbind('click', handler); //unbind the clicked element only
//create and change the element
//inside the select-change event, instead of addClass, re-attach:
{
//$(this).parent().addClass("ChooseType").text(selected).find('select').remove();
$(this).parent().click(handler).text(selected).find('select').remove();
}
};
$("td.ChooseType").click(handler);
I have two inputs that together form a single semantic unit (think an hours and minutes input together forming a time input). If both inputs lose focus I want to call some Javascript function, but if the user merely jumps between those two, I don't want to trigger anything.
I've tried wrapping these two inputs in a div and adding an onBlur to the div, but it never triggers.
Next I tried adding onBlurs to both inputs and having them check the other's :focus attribute through jQuery, but it seems that when the onBlur triggers the next element hasn't received focus yet.
Any suggestions on how to achieve this?
EDIT: Someone questioned the purpose of this. I'd like to update a few other fields based on the values contained by both these inputs, but ideally I don't want to update the other fields if the user is still in the process of updating the second input (for instance if the user tabs from first to second input).
I made a working example here:
https://jsfiddle.net/bs38V/5/
It uses this:
$('#t1, #t2').blur(function(){
setTimeout(function(){
if(!$('#t1, #t2').is(':focus')){
alert('all good');
}
},10);
});
var focus = 0;
$(inputs).focus(function() { focus++ });
$(inputs).blur(function() {
focus--;
setTimeout(function() {
if (!focus) {
// both lost focus
}
}, 50);
});
An alternative approach is to check the relatedTarget of the blur event. As stated in the MDN documentation this will be the element which is receiving the focus (if there is one). You can handle the blur event and check if the focus has now been put in your other input. I used a data- attribute to identify them, but you could equally well use the id or some other information if it fits your situation better.
My code is from an angular project I've worked on, but the principle should translate to vanilla JS/other frameworks.
<input id="t1" data-customProperty="true" (blur)="onBlur($event)">
<input id="t2" data-customProperty="true" (blur)="onBlur($event)">
onBlur(e: FocusEvent){
const semanticUnitStillHasFocus = (val.relatedTarget as any)?.dataset?.customProperty === "true";
// Do whatever you like with this knowledge
}
What is the purpose of this behavior ?
The blur event triggers when a field looses focus, and only one field can gain focus at a time.
What you could do, in case of validation for instance, is to apply the same function on blur for both the fields and check the values of the fields altogether.
Without a context, it is difficult to help you more.
d.