Should the HTML <select> element dispatch `beforeinput` events? - javascript

The MDN page for beforeinput states that:
The DOM beforeinput event fires when the value of an <input>, <select>, or <textarea> element is about to be modified
<select> is clearly mentioned as supporting the beforeinput event.
This also seems to be true based on my simple reading of the spec:
Trusted Targets: Element (specifically: control types such as HTMLInputElement, etc.) or any Element with contenteditable attribute enabled
(emphasis mine)
However, no browser seems to implement it. I have checked Chrome, Safari and Firefox.
Am I understanding something incorrectly?
const sel = document.getElementById('pet-select')
sel.addEventListener('beforeinput', () => console.log('beforeinput!'))
sel.addEventListener('input', () => console.log('input!'))
<label for="pet-select">Choose a pet:</label>
<select name="pets" id="pet-select">
<option value="">--Please choose an option--</option>
<option value="dog">Dog</option>
<option value="cat">Cat</option>
<option value="hamster">Hamster</option>
<option value="parrot">Parrot</option>
<option value="spider">Spider</option>
<option value="goldfish">Goldfish</option>
</select>

The MDN page copied its summary from the input event page, which does indeed fire on this element. I did open a PR there to rectify this.
The beforeinput event isn't supposed to fire on <select>, just like it doesn't fire on non textual inputs:
addEventListener('input', () => console.log('input!'))
addEventListener('beforeinput', () => console.log('beforeinput!'))
<input type=text placeholder="here it fires"><br>
<input type=checkbox><br>
<input type=radio><br>
<input type=file><br>
<input type=color>
To understand that, we need to go back in History and see how the input event was first designed by the HTML's specs.
It's only after some times that it got moved to the W3C/UI-Events working group.
The beforeinput one on the other hand was drafted by the W3C/Editing group and then transferred to the W3C/UI-Events.
The discussions in the W3C/UI-Events group make it clear that their intent was for it to fire only for changes that came from user keyboard inputs. They even initially expected it to NOT fire for actions such as paste or cut.
Ok, but why does the input event fires on <select> and other non textual input elements?
That's because the HTML specs (now handled by WHATWG) actually still do define the input event and ask for it to happen:
For the <select> element they say:
When the user agent is to send select update notifications, queue an element task on the user interaction task source given the select element to run these steps:
Fire an event named input at the select element, with the bubbles and composed attributes initialized to true.
As for textual <input> they say:
When the input and change events apply (which is the case for all input controls other than buttons and those with the type attribute in the Hidden state), the events are fired to indicate that the user has interacted with the control. The input event fires whenever the user has modified the data of the control.
And for checkboxes:, radio, and file inputs you'll find something along these lines:
The input activation behavior is to run the following steps:
If the element is not connected, then return.
Fire an event named input at the element with the bubbles and composed attributes initialized to true.
Fire an event named change at the element with the bubbles attribute initialized to true.
The only mention to the beforeinput event in the HTML specs has been added only 11 days ago, but that PR only exposes the event globally, it doesn't change its definition.

Related

html native dropdown - open menu items on enter click

on select enter click, by default form gets submitted on.As per accessibility criteria, if focus is on select element on enter click it should open list items. I want to know is it possible to make accessible dropdown using native select element which will meet accessibility criteria
<div class="custom-dropdown">
<select id="cities" name="select">
<option value="1">Delhi</option>
<option value="2">Mumbai</option>
</select>``
</div>
I have prevented default submission behaviour.
$('.custom-dropdown').keydown(function (event) {
if (event.keyCode == 13) {
event.preventDefault();
return false;
}
});
I have tried keyup event to trigger click event but its not working
$('#cities').keyup(function (e) {
if (e.keyCode == 13) {
$("#cities").trigger("click");
}
});
I'm pretty sure the only element that will submit a form automatically is a submit button.
<input type="submit" value="foo">
or
<button>foo</button>
(the default type for a <button> element is "submit")
The <select> is not defined as submitting a form. Are you sure your focus is on the <select> when you press enter?
You should also look at the specs for "4.10.18.6. Form submission"
You're basing your concern on an example, not the specification:
The example listbox on this page implements the following keyboard interface
If you refer to Keyboard Interaction for the Listbox Design Pattern, the Enter key is not mentioned.
The example uses Enter, because the trigger for the listbox is a Button.
Also, in general, ARIA rules are meant for cases where you cannot use standard elements, according to the First rule of ARIA use
If you can use a native HTML element [HTML51] or attribute with the semantics and behavior you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so.
In other words, you shouldn't care about those rules, when you don't implement your own controls.

What event to handle choose option from <select>?

I have an select with options which are loaded by ajax. After that user chooses option and additional data is pulled from ajax.
Of course at least one these options is selected as soon as select is filled with options so when I listen for change of this option:
$('article select.fetchedPosts').on('change', function () {
//do stuff and things
})
and user wants to fetch data for first (by default already selected) option the event is not firing because nothing has changed...
So is there any event in JS which would fire everytime user chose something from select, using keyboard or mouse?
You can do default instead of Option 1 Which option as "Select Option", and the user will have to replace the selection.
<select>
<option>select option...</option>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
change should be the correct event. According to MDN docs:
When the user commits the change explicitly (e.g. by selecting a value from a 's dropdown with a mouse click, by selecting a date from a date picker for [...]
There's actually an example select at the end of the page, where you can experiment clicking options or selecting with your keyboard, and each time it fires the event.
It may also change depending on your browser:
Different browsers do not always agree whether a change event should be fired for certain types of interaction. For example, keyboard navigation in elements never fires a change event in Gecko until the user hits Enter or switches the focus away from the

Triggering an event

I have a target website where there is the following dropdown menu.
<select class="categories-options" data-level="1" name="level1-option" id="level1-option" required="">
<option value="">default</option>
<option value="p1" data-href="/callback/p1">P1</option>
<option value="p2" data-href="/callback/p2">P2</option>
<option value="p3" data-href="/callback/p3">P3</option>
</select>
When an item is selected from the menu, it triggers a "change" event and a function is called when this event happens. I have debugged the event using Chrome and you can see the debugging output when I selected an item from the dropdown menu. I have taken a screenshot from the debugger.
Now, let me explain what I am trying to do. I use a javascript function to select an item from the dropdown menu using the following code:
var id= document.getElementById('level1-option');
setSelectedValue(id, "p2");
$('#level1-option').trigger("select");
In the last line, I try to trigger the same event that happens originally in the webpage as if I manually selected the item. however, it doesn't trigger anything. |I see in the debug output that the event is triggered by class. I have tried many different things but didn't work. Could anyone shed some light on this issue? How can I trigger the same event that happens in that webpage using jquery or javascript?
Your code:
$('#level1-option').trigger("select");
...will trigger an event called select (which isn't related to the value of a form field change), but the event you stopped on in the debugger is change, not select:
If you want to trigger the change event, trigger the change event:
$('#level1-option').trigger("change");
// Difference is here -------^
Side note: Because you're using jQuery, your code can be simpler, you dont need the getElementById or the setSelectedValue:
$('#level1-option').val("p2").trigger("change");
Try this
$('#level1-option').trigger("change");

Select drop-list item without triggering onchange event?

I want to populate a drop-list with several items and select a default item:
<select onchange="DoSomething(this)">
<option value="abb">This is the second item</option>
<option value="abc" selected>This is the third item</option>
etc...
</select>
However I don't want the onChange event to fire (or I want the code triggered by onChange to be ignored) until the user selects an item. At the moment the onChange event fires as the page loads and the selected item is chosen by default.
Can I wrap this code in PHP to achieve this - if so how?
?!
Manipulating the HTML DOM directly in JavaScript doesn't fire events. You can even call myForm.submit() and the browser will not fire the form's onsubmit event, therefore bypassing client-side onsubmit validation.
I don't know what you've tried, but this is one way to select for example the first item of the drop-down list:
document.getElementsByTagName('select')[0].getElementsByTagName('option')[0].selected = true;
(http://jsfiddle.net/Jawh6/)
Crude, I know. Usually your forms and fields would be named or otherwise identified so you can address them more excplicitly: e.g. document.myForm.mySelect.options[0].selected = true;
Since your PHP is already setting the 'selected' attribute on the option (or your question isn't very well tagged), this would be the best place to set the default option when the page loads, that requires no JavaScript at all.
If you're interested in how to get PHP to write out the HTML for a select element and correctly assign the selected attribute to the intended option, I reckon you need to write a new question to attract the PHP folk.
Either you have other calls to your DoSomething function, or you've oversimplified your example and you're actually using a framework to bind the event handler to the field and maybe you accidentally called your function instead of assigning it, e.g.:
mySelect.onchange = DoSomething(); // oops, this calls DoSomething right away.
mySelect.onchange = DoSomething; // this sets DoSomething as the event handler.

Workaround: <Select>ing the first <option> never fires an onchange event

I have a select-option block on a webpage, and I want it to fire for ANY of the options that get selected in it. However, the first option never fires onselect: Not even if a later option was selected previously.
For example, if my code reads:
Settings:
Sensitivity: <select id="sensitivity" onchange="if (this.selectedIndex) ajaxUpdateConfig();">
<option value="25">25%</option>
<option value="50">50%</option>
<option value="100" selected>100</option>
</select>
...then selecting the first option, 25%, never fires the onchange() event.
Similarly, if the first option is the default value, and the user changes away from it and then wants to return back to it, that doesn't fire the onchange event, either.
Note: I'm aware that the standard answer to the "First selection doesn't generate onchange events" problem is to make a dummy (disabled) first option. But that doesn't fit the design of this page: The menu represents shows the current status while offering the options that the user could change the settings to. Having a dummy entry is bad interface design, for this page.
this.selectedIndex is 0 for the first option.
0 is falsy, so your if never fires.
Get rid of the if entirely; there's no reason for it.

Categories