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

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.

Related

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

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.

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

How to trigger a callback function when select list text changes (before onchange event fires)?

I have a <select> field like the below:
<select id="my-list" class="default">
<option value=0 selected disabled>Select an item</option>
<option value=1>First Item</option>
<option value=2>Second Item</option>
<option value=3>Third Item</option>
</select>
The default class on the <select> element sets the color to red (indicating to the user that an option needs to be selected here).
Once the user selects an item the class is removed so the color changes to black.
Now what I'm trying to achieve is that the color changes as soon as the text in the select box changes. The onchange event only fires if the user clicks on an item in the list or presses ENTER or the element loses focus.
But if the user hits S for example the text will change to "Second item" and the color remains red until he presses ENTER or tabs out of the field.
Listening for keydown events doesn't work because if the user hits say X the event fires but the text won't change because there is no matching item.
One possible solution could be to use the keydown event and then compare the text to "Select an item" though it doesn't seem very elegant. And how would I get the text that is displayed? jQuery's .text() or .html() return all the options, not just what is displayed.
After writing the last paragraph of my question the answer came to me.
Typing into a select box or using the up and down arrow keys will set the selected attribute to the option displayed. Using the keyup event instead of the keydown event can then be used to simply check the value of the selected option and if it's not 0 the class is removed and the color changes.
$("#my-list").keyup(function(){
if ($("#my-list option:selected").val() !== 0){
$("#my-list").removeClass("default");
}
});
It seems a bit clumsy so perhaps there is a better way, but it works.

Detect if the selected value in <select> is selected again [duplicate]

Here is my simple code:
$(".test").change(function(){
alert("user clicked");
});
<select class="test">
<option value="1">test1</option>
<option value="2">test2</option>
</select>
It's all simple and working, but I want to get that function called not only when user changes option, but when he clicks on the same option that is already selected, I've tried click event but it gets fired up before user even clicka on any option, what could I do?
doesn't work in chrome.
$(".test option").click(function(e){
console.log('click');
});
updated your fiddle.
put the click on the option
EDIT: looks like it isn't possible without a bunch of work like using click on the select and comparing the location it was clicked or something hokey like that.
I am not sure what the end goal is, but the click on the select might work if you can do the processing one extra time when they initially click into it.
another article on it:
If you mean that there is only one thing in the select (like in the problem I was having), you could create a default disabled option, and set that as the selected. This would mean that if you had one option, onchange would fire because the disabled was the one that was previously selected:
<option disabled selecte>Select an option</option>
<option> Only Option </option>

javascript or jquery event that fires whenever the selected value of a select changes

I know i can use the javascript event onchange, or the jquery event change, however, enother of these cover the senario when the user does not change the value of the select him self.
For example, when using javascripts onchange event if I have three cascading selects and I select the first one, and the second one populates and the default value if the second one is the one the user wants, the onchange event of the second select is never fired, hence the third select is never populated.
ideas?
two ways you can do
1>
on second <select> create first option with value= "[choose something]" this way user will be forced to choose some thing from select2
2> When you populate the second select ,trigger its onchange event
How about putting a dummy value at the beginning on the select ,like a blank option. So that the user is forced to select another that has a value.
Insert a dummy item in the second select as the first item:
<option value="">-- select one --<option>
That way the user must fire the change event to select an item,
Autopopulate the third select box with the values it should have for the default of the second is one option. Otherwise as others have suggested a Please Choose option that forces onchange to fire.
If your changing the content via javascript, you can also trigger the change event explicitly.

Categories