How to programmatically click an element with MooTools? - javascript

In jQuery, I've done stuff like this in the past:
$('#someCheckbox').click();
And everything works as if the user just clicked on the element normally.
However the same doesn't work in MooTools:
$('someCheckbox').fireEvent('click');
The checkbox doesn't get checked, nor do any of the bound event handlers fire.
Is there a way to do this?
I need the already bound "click" event handlers to fire, so just setting it's "checked" attribute isn't an option.

The click event should fire when fireEvent('click') is called. See http://mootools.net/shell/8bbgn/ for a demo I just set up.
The checkbox doesn't get checked, as expected. To do this, you must set the checked property to true:
$('someCheckbox').setProperty('checked', true);

Related

Javascript event not triggered if the change origin is not from the html?

I am trying to understand why the change event in the following example is not triggered (I'll show exactly where).
I have a checkbox, lets call it 'mainCheckbox', when checked - I want to check some other related checkboxes (so far working).
In addition when I uncheck one of the related checkboxes (child checkboxes) - I want to uncheck the mainCheckbox, this also works - but here is something I am failing to understand:
I am changing the checked property of the mainCheckbox (in the onchange handler of the 'childCheckbox'),
How come the onchange handler of mainCheckbox is not invoked?
Or how come the onchange event of the main checkbox is not triggered?
here is the code:
//binding to the 'mainCheckbox' change event:
$("[data-role='group']").bind("change", function(event){
//checking / unchecking all related checkboxes respectivly
$("li input[data-group='" + event.target.id + "'").prop('checked', $(this).prop("checked"));
})
//binding to the change event of every 'child checkbox'
$("li input[data-group]").bind("change", function(){
if (event.target.checked){
//if the child checkbox is now checked - I am checking if now all child checkboxes are checked,
//if so - I need to check the main checkbox.
if ($("[data-group=" + event.target.dataset.group + "]:checked").length == $("[data-group=" + event.target.dataset.group + "]").length){
$("#" + event.target.dataset.group).prop("checked", true);
}
//TODO: add this device to the selectedDevices array.
}
else {
//the checkbox is now unchecked - so I am unchecking the main checkbox -
//but here is my failing to understand part: I am unchecking the main checkbox -
//why the change event is not triggered? I thought that now all child checkboxes will be unchecked as well
//(I am happy they are not :) just failing to understand why)...
$("#" + event.target.dataset.group).prop("checked", false);
//TODO: remove this device from the selectedDevices array.
}
})
In general, the events are only fired in response to user actions, not actions in code. Setting the checked property on a checkbox does not fire its change event; the user changing the checkbox's checked state does.
This is also true for when you use code to set the value of an input, the selectedIndex (or value) of a select, etc.
It's also true in relation to the submit events on form elements: Calling an HTMLFormElement's submit function will submit the form without triggering its submit event. But, if you use jQuery to submit the form (e.g., if you call submit on a jQuery object wrapped around an HTMLFormElement), it does trigger its submit event handlers. This is an unfortunate by-product of jQuery's API design.
If you want to trigger an event, you can do that with jQuery's trigger function. So if it's appropriate, after setting checked, you could .trigger("change"). In general I advocate not generating synthetic predefined events like that (instead, just call whatever function you need to call, or use a synthetic custom event), but there are valid use cases.
Onchange event is fired when the element loses focus. Since you are changing the value programmatically, the element you are changing never loses focus. You may wish to check the oninput event.

What, if anything, is jQuery's change method doing here?

I'm familiar with attaching a handler to a checkbox's property change like this:
$(function(){
$("#chkbox").change(function(){
alert($(this).val())
});
});
However, doing this $("#chkbox").change(); will fire my alert, but the state of the checkbox won't actually change, which tells me that jQuery is just firing off handlers that it's already bound to an element. What is the use of calling it like [bourbon.io][1] does to close its modal?
$(".modal-fade-screen, .modal-close").on("click", function() {
$(".modal-state:checked").prop("checked", false).change();
});
If I omit the .change() at the end, the modal still closes and it seems everything works fine. What is the use of chaining change()? I ask, because I am trying to use Angular with this modal, and I need to invoke closing the checkbox's state so I can close the modal with some other buttons. angular.element(".modal-state:checked").prop("checked", false); seems to work fine, but since I'm not aware of anything like change in Angular
(it doesn't exist in jQlite), I want to be certain I'm not missing anything.
If you attach an change event listener to an element, every time a user triggers that event the event handler will fire. However, if you programmatically manipulate the element with change that would normally fire the event handler, the event handler would not fire. Therefore, you want trigger the change event manually once you made the change so that the event handler can be triggered.
$(".modal-state:checked").prop("checked", false).change();
//or $(".modal-state:checked").prop("checked", false).trigger('change');
What is the use of chaining change()? It all depends on what the change event handler does.

Why does preventDefault on checkbox click event returns true for the checked attribute?

I am just curious and need some explanation on the following situation.
Let's say i have an input element of type checkbox with an eventlistener attached to it, listening for the click event. I prevent the default behavior of the checkbox and log the checked state of the checkbox, which will always return true.
The visual representation of the checkbox is telling me that it is not checked. So i would assume that the checked state would return false. I am sure this must be something silly and i am definitively misunderstanding something here. The funny thing is, i am logging the event itself as well. Inside of the target property the checked property is set to false, just as i would have expected.
From my understanding, prevent default will cancel the event without stopping propagation, so what exactly is happening here?
It would be great if someone could enlighten me on this one. Here is the example.
var checkbox = document.getElementsByTagName('input')[0],
output = document.getElementById('output');
checkbox.addEventListener('click', function(evt) {
evt.preventDefault();
output.innerHTML = "Checkbox checked attribute is " + this.checked;
console.log(this.checked, evt.target.checked);
console.log(evt);
}, false);
<input type="checkbox" id="my-checkbox" />
<label for="my-checkbox">Checkbox with preventDefault().</label>
<div id="output"></div>
Actually, the result of the checked value in a click handler is implementation dependent.
As I tested in several browsers, Chrome/Firefox/Safari/Opera will always return true in this case, but IE/Edge's behavior gets a bit weird if you keep clicking on that checkbox element.
And I found this paragraph in the spec, which might be a explanation of this inconsistency:
Note: During the handling of a click event on an input element with a type attribute that has the value "radio" or "checkbox", some implementations may change the value of this property before the event is being dispatched in the document. If the default action of the event is canceled, the value of the property may be changed back to its original value. This means that the value of this property during the handling of click events is implementation dependent.
But when I removed the preventDefault statement, the results in IE/Edge are consistent with the other browsers, which confuses me.
So I don't think it is IE/Edge's intended behavior… Therefore I filed a bug on Microsoft Connect.
After all, if we presume Chrome's behavior to be standard-compliant, then the following might be a suitable explanation:
According to the HTML Spec, an input[type=checkbox] element's checkedness is restored at the canceled activation process, which comes after the event handlers according to the Activation section. So during the execution of event handlers, the element's checkedness hasn't been restored yet.
(The spec doesn't explicitly state that canceled activation steps must come after all the event handlers; but it's easy to infer because otherwise there's no way to determine the event's canceled state)
According to w3schools "The preventDefault() method cancels the event if it is cancelable, meaning that the default action that belongs to the event will not occur." The click event is cancelable (you can check it like this console.log("cancelable? "+ evt.cancelable);.
So from what I understand, the default behavior of click event for a checkbox object is to read the current state of a checkbox and alternate between true and false, consequently changing its state to checked and unchecked. In shorter words the default behavior is toggling; therefore, preventDefault() cancels that behavior.
In relation to checkboxes checked = true; unchecked = false.If you try to debug and follow eventListener step by step you will see that once you in it the unchecked box becomes "checked" even after stepping on evt.preventDefault() so when you call console.log(this.checked, evt.target.checked); at that time for the compiler your box is "checked", the checkbox goes back to "unchecked" state only when eventListener done execution. From this I can conclude that in case with checkboxes preventDefault() is actually activated(executed) at very last after all calls within event listener is executed.

jQuery Simulate onClick

I am trying to simulate an onclick event on a drop down.
I have an IE object that is going to a page and I need to change a dropdown which has an onchange event:
$('select[name="blah"]').val(3).trigger('change');
$('select[name="blah"]').change(function(){
alert('changed');
});
When I try this, I would expect the alert to fire as it's technically an onchange.
http://jsfiddle.net/3y5hmyf0/
Is there a way to acomplish this?
More Details
My tool is controlling another IE page through an object. It navigates to the page and finds the select drop down on the page. From there, if you did it manually it has an onchange event when making a selection.
I am trying to get jQuery to simulate as if it was being clicked by a person to it triggers that on change event.
I have tried .trigger and .change and couldnt get either of them to work.
The only reason your code does not work is the order you are executing it. You need to connect the handler before triggering it:
JSFiddle: http://jsfiddle.net/3y5hmyf0/1/
// Wire up event handler
$('select[name="blah"]').change(function(){
alert('changed');
});
// Now generate the event
$('select[name="blah"]').val(3).trigger('change');
Note: Your manual change trigger is still required as a change event must normally be triggered by user interaction. Setting the value is not enough.
$('select[name="blah"]').change(function(){
NotifyChanged();
});
function NotifyChanged() {
alert('changed');
}
If you want to test the logic in the changed function, just call it.

Why is checkbox changed twice?

I do this:
$("input[type='checkbox']").each(function() {
var current = $(this);
$("label[for='" + current.attr("id") + "']").on('click', function() {
current.change();
alert('1');
});
});
$("input[type='checkbox']").on("change", function() {
alert('2');
});
Now, when I click on the label, the checkbox first alert(1) is showing up once, but the second(2) showing up twice. Can you tell me why? (The checkbox is hidden, seems like the change happens twice somehow)
You don't have to add a separate event handler for the <label> tag. It will trigger the "click" on the <input>.
You're better off using "click" instead of "change" (especially with the newest jQuery). Old (perhaps new) IE versions don't trigger "change" on checkboxes until the focus changes.
edit the reason that the newest jQuery makes life better is that it fixes a long-standing bizarre "feature" of the library. Previously, programmatically triggering "click" would result in a call to any "click" handlers with the element in the state before the effect of the click took place. That is, if you call
$(myCheckbox).trigger("click");
and the element was checked, it would be checked in the call to the handler. However, when a real click happens, the browser flips the state of the "checked" attribute before calling handlers. That made life pretty weird, but as of 1.9 I'm pretty sure that's fixed.

Categories

Resources