After execution of onclick-callback the 'checked' state is reset - javascript

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

Related

Aurelia one-way binding to a checkbox

I'm looking for a way to one-way bind a checkbox in aurelia, whilst still allowing the checkbox to accept a click from the user.
Assume a view similar to the following that displays one of a list of selectable items:
<template>
<div click.trigger="selected()">
<label......>${vm.code}</label>
<label....>${vm.description}</label>
<img...../>
<input type="checkbox" checked.one-way="vm.selected"></input>
</div>
</template>
The user should be able to click anywhere in the view to select the item, thus the click.trigger="selected()" is attached to the container. Within selected(), the vm.selected property that the checkbox is bound to is updated.
The checkbox should also be clickable as well, but should allow selection to be controlled by the selected() method.
readonly can not be used on the input control for the checkbox as that is used to control input.value and in this case it is the checked property that is of interest.
Calling preventDefault on the event args disables default checkbox checked behavior, which can be achieved in Aurelia by returning false from the click delegate. That would require attaching another handler to the input control, and has the problem that the click gets handled by the input control and doesn't bubble up to the delegate attached to the container (selected()) to actually control selection.
Maybe there is another approach to this that I am missing, one that I was considering was to use two font-awesome icons that look like checked and unchecked checkboxes and switch between the two based on the value of vm.selected.
Update
On the delegation of events this answer does solve the issue if you are not using a checkbox but the browser prevents the state from toggling on the checkbox so as we discussed the best approach is probably to use an icon or sprite to show the 'state' of the checked piece since the control should be one-way only, which can be accomplished like this -
<i class="fa fa-${this.selected ? 'check-square-o' : 'square-o'}"></i>
Original answer on delegation
If we use delegate instead of trigger then our event bubbles and we can handle it a bit more gracefully and prevent the state from changing -
<div click.delegate="clicked()">
<input type="checkbox" click.delegate="clicked(false)" checked.one-way="vm.selected" />
</div>
And then in our view model we can handle the click event that bubbles -
clicked(event){
if (event !== false) {
// do something
} else {
return false;
}
}
This isn't a perfect solution but it should prevent the event from occurring which changes the state of the control but still allow the event to take place at the div level.

Checkbox and onchange method usage

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');
});
}

jQuery: generate Select element

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);

jQuery click() and changing the checked value

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.

jQuery Javascript how to keep click event from going null

Here is a JSfiddle link to the script I am working with:
http://jsfiddle.net/TSM_mac/bnjWQ/
To use it, you first click the button and then on the element you want to modify.
As you notice, when you click the button to apply it to the div, the property is disabled and you can't just click on other objects. I want to be able to click the button, and apply it to any object without having to reclick the button.
The original code I wrote was not as tidy as this code, but a very helpful person wrote this for me to fix a problem I was having... I can't seem to enable this feature.
Just delete or comment out the line setting currentInput to null in the div.editable click handler and the if statement in the css property input click handlers. http://jsfiddle.net/bnjWQ/2/

Categories

Resources