I have a table with some rows that have checkboxes on the first column where if user clicks, it calls some javascript methods that disable the other fields of the respective rows.
The structure of these inputs is this:
<input type="checkbox" name="ans_R2057321_Q2060122" id="ans_R2057321_Q2060122" value="2002241" onclick="matrix.disableFields(this, 'R2057321');recalculateRowFormulas('2057321'); alignTDs();" />
I implemented a link where when user clicks on it, it has to select all these checkboxes, so I did it this way:
function noQuoteAllRowsOfCurrPage(){
jQuery("input:checkbox[id^=ans_R]").each(function(i,e) {
jQuery(e).prop('checked', true);
});
}
This simply iterates in each checkbox on the screen whose id starts with ans_R, and then check the CB state to true. It does works, but the problem is that the javascript functions called on the onclick property of the input checkboxes aren't running. First thing I did was changing from onclick to onchange, which should be the correct way to do that, since the state of checkbox is changing, but somehow it doesn't work... any ideas what of what can I do?
JQuery's .prop() function does not trigger the change event. You either can
1 - Trigger the event manually
jQuery(e).prop('checked', true).trigger('change');
2 - Use the .click() function that will check the input, and trigger the event as well..
jQuery(e).click();
I found what I was missing and since I saw several people with the same problem, I think my solution can be helpful for others..
I just added a trigger for 'change'.
function noQuoteAllRowsOfCurrPage(){
jQuery("input:checkbox[id^=ans_R]").each(function(i,e) {
jQuery(e).click();
jQuery(e).prop('checked', true).trigger('change');
});
}
Related
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);
Behold the following jsfiddle: http://jsfiddle.net/RA3GS/4/
If you check on the checkboxes manually, you see that they say they are checked when they are checked and remain checked. However, if you push the test buttons you'll see that they either say they are checked, and then become unchecked, or say that they are not checked, and say they are checked.
Here is the problem: if I choose not to set the checked value before hand, the checkbox is correctly checked at the end, but the clicked function incorrectly states that it is unchecked. If I do set the checked value, then the click() function correctly states that the checkbox is checked, but then some other event (un)helpfully unchecks the checkbox at the very end.
The jsfiddle is a test; in my real implementation I will have no control over the click() function on the input element, so it is not merely a matter of changing the login in the click function.
This is the behavior I want, exactly:
You click on the button.
Any click() function is triggered and believes the element to be checked.
All other events believe the checkbox to be checked.
When everything is said and done, the checkbox is still checked.
Simpler example
I've put a simpler jsfiddle here:
http://jsfiddle.net/49jUL/
Without changing the status function, I want the console to display identically no matter which checkbox you check. Current output is:
clicking on manual
A tester received the following event change
Value: 100 Checked: true
A tester received the following event click
Value: 100 Checked: true
clicking on controller
A tester received the following event click
Value: 100 Checked: true
A tester received the following event change
Value: 100 Checked: false
I find it interesting that if I click on the manual radio button, change is called first and then click, whereas if I trigger click, click is called and then change.
Note that when I've tried calling it as $target.change().click() then it simply calls change, then click, then finally change again with checked set to false.
From my comment--
The checked field is a property, rather than an attribute, so I would recommend using the appropriate accessor and mutator for the "checked" status:
$('#checkBoxElId').prop("checked");
and
$('#checkBoxElId').prop("checked", true/false);
Alternatively you can use the is() function with the :checked pseudo selector to see if it's checked:
$('#checkBoxElId').is(':checked');
The "checked" attribute does not change after the initial loading of the checkbox. See the jQuery documentation on prop() for more information about the state of checkboxes.
EDIT: Solution
After finding a bug report explaining this behavior, I did a little experimentation with the workaround documented in the bug's comments: the use of triggerHandler("click") instead of calling click().
click() is just a shortcut for trigger("click"), which will trigger a matching event on all elements found by the selector, and will also invoke the native handler. triggerHandler("click"), OTOH, will only trigger the event for the first element found by the selector, and will prevent the default (native) behavior from occurring. It's the native behavior that is messing with the "checked" state of the checkboxes. By avoiding it, you get the desired behavior.
Here's an updated jsFiddle with my solution.
You can not be simply triggering the click on the check box, you need to verify the current status, and then act accordingly:
$('#pushbutton').on("click", function() {
var $obj = $('#myCheckBoxID');
$obj.prop('checked', !$obj.prop('checked'));
alert('now check is: ' + $obj.prop('checked'));
});
See this Fiddle Example!
EDITED
Followed improvement given by ThiefMaster on the first comment.
This drives me mad. I just can't understand it.
I wrote a filter-function based on checkboxes and clicking on their labels. I'm checking the 'checked' state of checkboxes and show mathed elements of the list (the rest elements are hidden). I use 3rdparty plugin that stylizes checkboxes (cut from example) and makes checkboxes checked while other onClick event does the filtering.
The problem is that after 'checked' state is successfully set inside a callback-function it "suddenly" becomes reset! I can't understand why that happens.
I implemented the base logic (without stylizing) here: http://jsfiddle.net/3Xtuh/13/
and ask all to help me solve this, please.
The problem is that you are invoking the click event manually, and then when your function is done running, the default click event is invoked.
By passing the event variable to your click handler and calling event.preventDefault(); fixes this behavior.
See example here: http://jsfiddle.net/3Xtuh/14/
The HTML label will check the associated checkbox even if it´s hidden (using CSS) so there´s no need to reinvent the wheel.
You should use the change() event. Try this demo and view your console.
It's default browser behavior that's messing your js script. By default, clicking on a label that is either wrapped around checkbox or have valid for attribute set, is toggling checked state of that checkbox.
You've attached custom onclick handler on labels.
So what's going on is that when clicking on a label? Your click handler gets fired (in in you alter state of target checkbox), and then
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.
I have a jquery function that binds all tr's with the class item to a click function that will redirect to another page. inside this tr though is a checkbox. How can i allow this checkbox to function correctly instead of acting on the tr's click function?
You might want to post code, but briefly, I would add a separate click function just for the password, and in it, call event.stopPropagation().
Here is what you are looking for:
jquery stop child triggering parent event
You can also bind it to a click function which stops the even from being passed on via return false.
$('#checkbox').click(function() { return false; })
Another way would be to position your checkbox above the tr. This would however not size the tr with the checkbox in it (as you made it independent).
This could be done with position:absolute, or you could also try z-index (although I’m not sure this will work with events).