A <select> element looks like this:
<select id="ok">
<option value="one">First</option>
<option value="two" selected>Second</option>
</select>
Initially, the Second text value is shown, because the selected attribute is present.
If I manually change it (using mouse click), it shows the new chosen value in UI, but the <select> remains the same in HTML:
<select id="ok">
<option value="one">First</option>
<option value="two" selected>Second</option>
</select>
I can get the current select value:
document.getElementById('ok').value
or the current selected index:
document.getElementById('ok').selectedIndex
via JavaScript (or jQuery), but I don't know where these values come from.
Are they stored in DOM or somewhere else?
How does JavaScript know which is the current value in UI?
Is it stored in DOM?
Yes, it is stored in the DOM.
Whenever a change event is detected DOM is updated and the updated value is stored in the value object.
When you use document.getElementById("ok").value you are able to access the latest selection in JavaScript.
You can check this in:
Firefox Inspector view
Show DOM Properties
Filter by value:
Chrome DevTools
Select the element > Properties
Expand the select and use the vertical scroll to go to value:
Related
I have a datalist that is created on the fly based on the user's selection from a group select menu. After the group is selected, the datalist is created. The datalist allows users to choose from a "dropdown" list or just start typing in the input box and have the list filtered accordingly. It is structured like this:
<div id="projectSelect">
<input type="text" name="ProjTitle" id="ProjTitle" placeholder="~ select project ~" list="projectList" autocomplete="off" value="">
<datalist id="projectList">
<select id="projectOptions">
<option data-projid="390" value="Project 1">Project 1</option>
<option data-projid="391" value="Project 2">Project 2</option>
<option data-projid="392" value="Project 3">Project 3</option>
</select>
</datalist>
</div>
In the default use case, the user double-clicks on the input box, a drop down appears, a project is selected (clicked) and the rest of the page (a report) is populated. This all works great.
In the alternate use case for the page, the groupid and a particular projid are passed to the page via a stored browser value.
In this case, the presence of the 'groupid' triggers the group selector just fine and the datalist element is populated just as if the user had made the group choice. All good so far.
What I'm having difficulty doing is interacting with the datalist via jquery to select the item matching the projid that is passed AND displaying the resulting title of the project in the input control. The title of each project is the "value" of each option.
From lots of other references I've found, the way to select an item in a datalist is to actually set the value of the associated input like this:
$('#ProjTitle').val("Project 1");
This doesn't work in my case, because the value being passed to the page is the projid that is in the data-projid value for each option and not the project title that is the "value" of each option.
One approach I thought of using for this was to select (using jQuery) all of the datalist options and then use $.each() to loop over the items and find the matching projid. If I could do this, I would then get the valueof that option and pass it to ('#ProjTitle').val().
However, when I use jQuery to select the options like this:
let $options = $(document).find('option');
$options is empty.
Are the options for a datalist not accessible with jQuery for some reason? in the Firefox developer tools the options are greyed out as if they are hidden. If they can not be accessed directly, how can I get the "value" of the option that matches the projid?
What other approach could I use to set the selected value of the datalist (based on the projid)?
Edit
I am suspicious that the dynamic loading of the content is in play here. The code to set the datalist is inside the $(function() { }) block of javascript so execution occurs after page load. Nonetheless, if I add console.log($('#ProjectList')); (or '#ProjectSelect') to the javascript I get the following in Firefox Developer Tools:
Normally, I'd be able to access all the nodes for the element.
I think the comments in the demo are sufficient to explain things, but feel free to ask any questions if you need a more details.
/* Assume this is the id passed to your page: */
const projid = 392
/*
Select the option element with a matching data-projid attr
and store the actual value for the selected option.
*/
const val = $(`[data-projid="${projid}"]`).val()
/*
Select the input that is a direct descendant of the
#projectSelect element and set the value for it
to the project name
*/
$('#projectSelect > input').val(val)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<div id="projectSelect">
<input type="text" name="ProjTitle" id="ProjTitle" placeholder="~ select project ~" list="projectList" autocomplete="off" value="">
<datalist id="projectList">
<select id="projectOptions">
<option data-projid="390" value="Project 1">Project 1</option>
<option data-projid="391" value="Project 2">Project 2</option>
<option data-projid="392" value="Project 3">Project 3</option>
</select>
</datalist>
</div>
Given the following jQuery plugin: http://selectric.js.org/index.html which replaces the functionality of that of a regular select box by using custom UL LI lists,
Based on the plugins documentation, I know that you can programmatically select an option value if you already know the index to select by using the following code:
$('#idofselectbox').prop('selectedIndex', 3).selectric('refresh');
But they do not include a sample to be able to find and select an option value by a value.
For example,
Let's say i'd like to select the option value named 'apples' without actually knowing its index in the select box. Is this even remotely possible?
<select id="idofselectbox">
<option value="oranges">oranges</option>
<option value="pears">pears</option>
<option value="apples">apples</option>
<option value="strawberries">strawberries</option>
</select>
You can set the value as if it's a regular combo box, then call refresh on selectic to refresh the UI.
$('#idofselectbox').val('apples').selectric('refresh');
I have a dropdown value which is proving very difficult to set in the console. I have tried using Jquery .val and using document.getEWlementById.value and both will not set the item. Does anyone know how I can set the value of the dropdown using the value? I think the problem is that it is using Knockout which makes it more difficult to set it dynamically.
Here is the HTML:
<select id="sourceShippingLocations" data-bind="options: $root.ShippingLocations, optionsText:'Name', optionsCaption:'Select location', value: $root.SelectedOriginShippingLocation" class="form-control" title="">
<option value="">Select location</option>
<option value="">doo Warehouse</option>
<option value="">moo</option>
<option value="">Manchester</option>
</select>
Knockout doesn't make it "more difficult to set dynamically". It just works differently.
In knockout, a viewmodel dictates what happens in the view. In other words: you don't set the value of the select through modifying the attribute directly, but you change the selected value of the underlying model and knockout manages the UI state for you.
Each of the <option> elements represents a value in an array named $root.ShippingLocations. The selected value is stored in $root.SelectedOriginShippingLocation.
In the viewmodel, you'd update the current selection by doing something like:
this.SelectedOriginShippingLocation(this.ShippingLocations()[0])
(this sets the selection to the first shipping location)
If you want to see this in action without having to modify the viewmodel, you can hack this in your console:
var root = ko.contextFor(document.getElementById("sourceShippingLocations")).$root;
root.SelectedOriginShippingLocation(ko.unwrap(root.ShippingLocations)[0]);
// change 0 for the index you like
I faced with a strange behaviour of select element. So, I have a select element with several options. One of option is empty - it's required by plugin to output placeholder.
I needed functionality that would clear selected options and I wrote something like:
$(element).val('');
$(element).find("option:selected").removeAttr("selected");
The thing is that "selected" attribute is still here and it's on old option - you can see it in the code sample.
So, I have 2 questions:
1) Why .val() method of jQuery library do not update "selected" attribute in options list?
2) Why I can not update "selected" attribute in my case? If I switch these statements it's working:
$(element).find("option:selected").removeAttr("selected");
$(element).val('');
Code sample:
$(function(){
$("#unselect").click(function(){
$("#lang_type").val('');
$("#lang_type").find("option:selected").removeAttr("selected");
alert($("#lang_type").html());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<select id="lang_type">
<option value=""></option>
<option value="01">01 - Language of text</option>
<option value="02">02 - Original language of a translated text</option>
<option selected="selected" value="03">03 - Language of abstracts</option>
<option value="04">04 - Rights language</option>
<option value="05">05 - Rights-excluded language</option>
<option value="06">06 - Original language in a multilingual edition</option>
<option value="07">07 - Translated language in a multilingual edition</option>
<option value="08">08 - Language of audio track</option>
<option value="09">09 - Language of subtitles</option>
</select>
<button id="unselect">Unselect</button>
EDIT:
You can use prop(false) property like this
$(function(){
$("#unselect").click(function(){
$("#lang_type").val('');
$("#lang_type").find("option:selected").prop('selected',false);
});
});
Like #yezzz said, read this :
Note: Do not use removeProp() method to remove native properties such as checked, disabled, or selected. This will remove the property completely and, once removed, cannot be added again to element. Use .prop() to set these properties to false instead.
If I'm not mistaken, a multi-select can be initially unselected, but once any option is selected, it can not be unselected any more. RFC 1866 states in section 8.1.3:
The initial state has the first option selected, unless a SELECTED attribute is present on any of the elements.
This lets me to believe that one option MUST always be selected. Obviously, different browsers interpret this differently...
But it does not seem to be a jQuery issue, rather a browser implementation issue.
The selected attribute reflects merely the initial state of the select input. You shouldn't really care about removing it, as it affects nothing once a different option is selected (either by the user or by a script on your page).
The current state of the input can be read or modified via the selectedIndex property, where a value of -1 means no option is selected (which never is the default, as there always is an option selected initially). However, you seem to want to select a particular "empty" option.
Setting the value on a select box results in the corresponding option being selected, which, in your case, is the very first one.
The code probably does exactly what you want. So don't mind checking the HTML, as the selected attribute - again - is unrelated to the current state of the input.
The :selected selector, however, matches the elements that are currently selected. Your first snippet selects an option, thus making it :selected, then attempts to remove a non-existent attribute from it. The second snippet of yours assumes that the selection remains on the option that was initially selected, and then removes the attribute from it. What follows is the "empty" option getting selected, and no more steps need to be taken, as that's all it takes to select an option.
To summarize: you can safely drop all the code that deals with the removal of the selected attribute, as it doesn't affect the current state of the element, the state being already tied to the correct option.
I have a select that looks like this:
<select id = "baz"
name = "Baz"
size = 1>
<option value="A1"> foo</option>
<option value="A2"> bar</option>
...etc
<option value="A99"> bat</option>
</select>
I've pulled this code from Firebug (and edited it), as the options themselves are read from the server by a CGI #include.
The value of the select is eventually read by JavaScript as follows:
var $input_baz = $("#baz");
...
var baz_pl = $input_baz.val();
Problem: the select is in a hidden div, and no selections have been made, but baz_pl contains the value A1. Why is .val() returning the first entry when nothing has been selected, and is there a simple fix for this? The select appears in a popup, and I can add code to detect if the popup 'Ok' button has been clicked, but I'd rather do it properly if possible.
The first option is always selected by default. You could add a dummy entry as first one, with a value that does not occur otherwise in the list.
For example:
<option value="-1">-- Please select --</option>