I am trying to come up with a way that would automatically populate a drop down based on the value selected in a different drop down.
Lets say I have a drop down for State / Province. Depending which value gets selected it would fill in the Country drop down to be USA / CAN.
<select name="formState" class="form-control modeldropdown" id="state" required>
<option value="">State / Province</option>
<option value="">--- United States ---</option>
<option value="AL">Alabama - AL</option>
...
<option value="MH">Marshall Islands - MH</option>
<option value="">--- Canada ---</option>
<option value="AB">Alberta - AB</option>
<option value="BC">British Columbia - BC</option>
...
</select>
It would be easier to do it the reversed way (select a country then it filters) -- for that I would do something like this
var jsonText = '{"USA":{ '
+ '"Alabama": "Alabama",'
+ '"Alaska": "Alaska",'
+ '},'
+ '"CAN":{'
+ '"Alberta": "Alberta",'
+ '}}';
var json = JSON.parse(jsonText);
And then filter it based on which Country was selected, but is there an easy way to do the reversed?
The only way I can think to do this is by checking the value to see if it is:
var state = $('#state').val();
if ( state == 'Alabama' || state == 'Alaska'...)
...
You could make an object that maps from state/province to country:
const countryOfState = {
'Alabama' : 'USA',
'Alberta' : 'CAN'
};
let state = $('#state').val();
if (countryOfState[state] === 'USA') {
...
You can use indexOf to check if an element exists in an array like so:
const states = {
'USA': ['Alabama'],
'CAN': ['Alberta']
};
function getCountry(state) {
for (let country in states) {
if (states[country].indexOf(state) >= 0) {
return country;
}
}
return null;
}
console.log(getCountry('Alberta')); //CAN
Here's a slightly sideways approach using optgroup which I think works better for your data anyway. I've also utilised data attributes
$('#state').change(function() {
var optGroup = $(this.options[this.selectedIndex]).closest('optgroup');
var label = $(optGroup).prop('label');
var cCode = $(optGroup).data('countrycode');
$('#country').html('<option value="'+ cCode + '">' + label + '</option>');
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<select name="formState" class="form-control modeldropdown" id="state" required>
<option value="">State / Province</option>
<optgroup label="United States" data-countryCode="USA">
<option value="AL">Alabama - AL</option>
<!-- ... -->
<option value="MH">Marshall Islands - MH</option>
</optgroup>
<optgroup label="Canada" data-countryCode="CA">
<option value="AB">Alberta - AB</option>
<option value="BC">British Columbia - BC</option>
</optgroup>
</select>
<select id="country" name="country"><option disabled selected>Please Select State</option></select>
Related
I have the following JS for generating a dropdown list for provinces/states:
var populateList = function (list, element) {
element.append("<option val=''>Select...</option>")
list.forEach(function (val) {
element.append("<option val=" + val[0] + ">" + val[1] + "</option>");
})
}
var canProvinces = [
['ON', 'Ontario'],
['QC', 'Quebec'],
['NS', 'Nova Scotia'],
['NB', 'New Brunswick'],
['MB', 'Manitoba'],
['BC', 'British Columbia'],
['PE', 'Prince Edward Island'],
['SK', 'Saskatchewan'],
['AB', 'Alberta'],
['NL', 'Newfoundland and Labrador'],
['NT', 'Northwest Territories'],
['YT', 'Yukon'],
['NU', 'Nunavut']];
The idea I'm working towards is when the user switches countries in a form, the system can use populateList() to switch to a new list whenever the user switches countries. Then I use jQuery to put the province abbreviation in a hidden input field. Here is the code in the form:
<script src="list-of-provices/states-from-above.js"></script>
<input id="UserCountry" value="CA" type="text" /> <!-- to be converted to dropdown when issue resolves -->
<select id="province-select" name="province-select"></select>
<input id="Province" type="hidden"/>
<script>
$(document).ready(function () {
if ($('#UserCountry').val() == 'CA') {
populateList(canProvinces, $("#province-select"));
} else if ($('#UserCountry').val() == 'US') {
populateList(usaStates, $("#province-select"));
}
$('#province-select').bind('input propertychange', function () {
//something wrong here? Returns full name, not 2 letter abbreviation.
console.log($("#province-select").val())
$('#Province').val($("#province-select").val())
})
});
</script>
I haven't got to the Country switching part yet because, despite everything I've tried, $("#province-select").val() returns the Text from the dropdown, not the value. I have not been able to find a reason for this. Here is the HTML generated by the code:
<select id="province-select" name="province-select">
<option val="">Select...</option>
<option val="ON">Ontario</option>
<option val="QC">Quebec</option>
<option val="NS">Nova Scotia</option>
<option val="NB">New Brunswick</option>
<option val="MB">Manitoba</option>
<option val="BC">British Columbia</option>
<option val="PE">Prince Edward Island</option>
<option val="SK">Saskatchewan</option>
<option val="AB">Alberta</option>
<option val="NL">Newfoundland and Labrador</option>
<option val="NT">Northwest Territories</option>
<option val="YT">Yukon</option>
<option val="NU">Nunavut</option>
</select>
Is there something I am missing? $("#province-select").val() should return the val="" from the dropdown, but for me it returns the text.
Any thoughts?
You have a small mistake in your code. The attribute to be used for setting the value of option is value and not val. Replace your
element.append("<option val=" + val[0] + ">" + val[1] + "</option>");
with
element.append("<option value='" + val[0] + "'>" + val[1] + "</option>");
and you are good.
My JavaScript skills are pretty basic, but I've written this code where you select from the dropdown on the left (Select1) an option which shows only the specified options in the dropdown on the right (Select2), and hides the rest.
I've also put it in a codepen here, in case you want to fiddle.
The code seems to work in both of the above environments in Firefox 90.0.2, but it fails in both and writes nothing to the console in Chrome 92.0.4515.131.
Any ideas why it's working in Firefox but not Chrome (and others) and what I can do so it works on all major browsers.
I'm running Windows 10 and I'd like to avoid iQuery if practical, as I don't want to get into learning or using that yet, as I'm starting with the basics.
Thanks.
Here's the code:
<!DOCTYPE html>
<html>
<head>
<script>
function hide_options(select_id,type)
{
//alert("hide_options(select_id="+select_id+", type="+type+")");
console.log("hide_options(select_id="+select_id+", type="+type+")");
var x = document.getElementById(select_id);
for (i=1; i<x.options.length; i++)
{
x.options[i].style.display = "none";
}
x.options[0].selected = true;
if (type == 'A')
{ unhide_options(select_id,"one","two") }
if (type == 'B')
{ unhide_options(select_id,"two","three") }
if (type == 'C')
{ unhide_options(select_id,"two") }
}
function unhide_options(select_id,...opts)
{
//alert("unhide_options(select_id="+select_id+"opts="+opts+")");
console.log("unhide_options(select_id="+select_id+"opts="+opts+")");
for (i=0; i<opts.length; i++)
{
document.getElementById(select_id+"_"+opts[i]).style.display = "";
}
}
</script>
</head>
<body>
<p>Selecting an option in the "Select1" dropdown should show only those options in the "Select2" dropdown.</p>
<select name=select1>
<option>Select1...</option>
<option onclick="hide_options('field1','A')">Show options 1 + 2 only</option>
<option onclick="hide_options('field1','B')">Show options 2 + 3 only</option>
<option onclick="hide_options('field1','C')">Show option 2 only</option>
</select>
<select name=update_action id=field1>
<option value=''>Select2...</option>
<option value=one id=field1_one>One</option>
<option value=two id=field1_two>Two</option>
<option value=three id=field1_three>Three</option>
</select>
</body>
</html>
Perhaps Chrome doesn't emit an event on clicking an option - however, you can use the change event on the select
I've used data-* attributes for the options, and I also show/hide in the one loop
the showing object is just a nice easy way to configure what should show, so you don't need if/else if/else if etc - I find this easier to maintain then countless if else if`'s
const selects = document.querySelectorAll('.filterer');
const showing = {
A: ["one", "two"],
B: ["two", "three"],
C: ["two"]
};
selects.forEach(select => {
select.addEventListener('change', function(e) {
const {
target,
value
} = this[this.selectedIndex].dataset;
const show = showing[value] || [];
const x = document.getElementById(target) || [];
[...x]
.slice(1)
.forEach(option =>
option.style.display = (show.length === 0 || show.includes(option.value)) ? '' : 'none'
);
if (x && x[0]) {
x[0].selected = true;
}
});
});
<p>Selecting an option in the "Select1" dropdown should show only those options in the "Select2" dropdown.</p>
<select id="select1" name="select1" class="filterer">
<option>Select1...</option>
<option data-target='field1' data-value='A'>Show options 1 + 2 only</option>
<option data-target='field1' data-value='B'>Show options 2 + 3 only</option>
<option data-target='field1' data-value='C'>Show option 2 only</option>
</select>
<select name=update_action id=field1>
<option value=''>Select2...</option>
<option value=one id=field1_one>One</option>
<option value=two id=field1_two>Two</option>
<option value=three id=field1_three>Three</option>
</select>
<br/>
<hr/>
<select id="select2" name="select2" class="filterer">
<option>Select1...</option>
<option data-target='field2' data-value='A'>Show options 1 + 2 only</option>
<option data-target='field2' data-value='B'>Show options 2 + 3 only</option>
<option data-target='field2' data-value='C'>Show option 2 only</option>
</select>
<select name=update_action id=field2>
<option value=''>Select2...</option>
<option value=one id=field2_one>One</option>
<option value=two id=field2_two>Two</option>
<option value=three id=field2_three>Three</option>
</select>
Alternative. You mention in a comment that the Selects and Options are created dynamically on the server code
The following would allow you to do that, and to specify the visible selections given the current choice, all in the option data-values attribute
Nothing needs hard coding in javascript this way
const selects = document.querySelectorAll('.filterer');
selects.forEach(select => {
select.addEventListener('change', function(e) {
const { target, values } = this[this.selectedIndex].dataset;
const show = values.split(',').map(s => s.trim());
const x = document.getElementById(target) || [];
[...x]
.slice(1)
.forEach(option =>
option.style.display = (show.length === 0 || show.includes(option.value)) ? '' : 'none'
);
if (x && x[0]) {
x[0].selected = true;
}
});
});
<p>Selecting an option in the "Select1" dropdown should show only those options in the "Select2" dropdown.</p>
<select id="select1" name="select1" class="filterer">
<option>Select1...</option>
<option data-target='field1' data-values='one, two'>Show options 1 + 2 only</option>
<option data-target='field1' data-values='two, three'>Show options 2 + 3 only</option>
<option data-target='field1' data-values='two'>Show option 2 only</option>
</select>
<select name='update_action' id='field1'>
<option value=''>Select2...</option>
<option value='one' id='field1_one'>One</option>
<option value='two' id='field1_two'>Two</option>
<option value='three' id='field1_three'>Three</option>
</select>
<br/>
<hr/>
<br/>
<select id="select2" name="select2" class="filterer">
<option>Select1...</option>
<option data-target='field2' data-values='apple,banana'>Apple and banana</option>
<option data-target='field2' data-values='banana,pineapple'>Banana and pineapple</option>
<option data-target='field2' data-values='pineapple'>Pineapple</option>
</select>
<select name='update_action' id='field2'>
<option value=''>Select2...</option>
<option value='pineapple' id='field2_one'>Pineapple</option>
<option value='banana' id='field2_two'>Banana</option>
<option value='apple' id='field2_three'>Apple</option>
</select>
Sure, this may require changing server code, but your original code did have hard coded logic for A B and C - this code, the server code can emit anything it likes and the javascript doesn't need to be changed
I'm trying to create a html form which has two option dropdowns that are dynamic (the second's value dependant on the first). The value from the second option will then feed into the submit button, which is a link. The data for the buttons comes from a JSON file. I know I'll have to use JS & JQUERY to achieve this but I'm not great with JS.
The output for the first option I want is as as follows:
<select id="first_choice">
<option selected value="base">Please Select Country</option>
<!-- Appended options -->
<option value="Afghanistan">Afghanistan</option>
<option value="France">France</option>
<option value="United Arab Emirates">United Arab Emirates</option>
<option selected value="United Kingdom">United Kingdom</option>
</select>
Then if 'United Arab Emirates' were selected for example, the second dropdown should be filtered/populated as follows:
<select id="second-choice">
<option selected>Please Select Language</option>
<!-- Appended options -->
<option value="https://www.mysite.ae/lang=ar">Arabic</option>
<option value="https://www.mysite.ae/lang=en">English</option>
<option value="https://www.mysite.ae/lang=hi">Hindi</option>
<option value="https://www.mysite.ae/lang=fa">Persian</option>
<option value="https://www.mysite.ae/lang=ur">Urdu</option>
</select>
The value for the second option would then be used for the submit, which would be a link.
My JSON file is formatted as follows:
{
"Afghanistan":{
"Persian":"https://www.mysite.af/lang=fa",
"Pushto":"https://www.mysite.af/lang=ps",
"Pashto":"https://www.mysite.af/lang=ps"
},
"Albania":{
"Albanian":"https://www.mysite.al/lang=sq",
"English":"https://www.mysite.al/lang=en"
},
"United Kingdom of Great Britain and Northern Ireland":{
"English":"https://www.mysite.co.uk/lang=en"
},
"United Arab Emirates":{
"Arabic":"https://www.mysite.ae/lang=ar",
"English":"https://www.mysite.ae/lang=en",
"Hindi":"https://www.mysite.ae/lang=hi",
"Persian":"https://www.mysite.ae/lang=fa",
"Urdu":"https://www.mysite.ae/lang=ur"
}
As I said, I'm not great with Javascript so any help would be really appreciated!
This script will turn your data into a two-step selection in drop-down menus
var data = {
"Afghanistan": {
"Persian": "https://www.mysite.af/lang=fa",
"Pushto": "https://www.mysite.af/lang=ps",
"Pashto": "https://www.mysite.af/lang=ps"
},
"Albania": {
"Albanian": "https://www.mysite.al/lang=sq",
"English": "https://www.mysite.al/lang=en"
},
"United Kingdom of Great Britain and Northern Ireland": {
"English": "https://www.mysite.co.uk/lang=en"
},
"United Arab Emirates": {
"Arabic": "https://www.mysite.ae/lang=ar",
"English": "https://www.mysite.ae/lang=en",
"Hindi": "https://www.mysite.ae/lang=hi",
"Persian": "https://www.mysite.ae/lang=fa",
"Urdu": "https://www.mysite.ae/lang=ur"
}
}
var firstChoice = document.getElementById('first_choice');
var first = Object.keys(data);
for (var i = 0; i < first.length; i++) {
firstChoice.innerHTML += '<option value="' + first[i] + '">' + first[i] + '</option>';
}
firstChoice.addEventListener("change", function () {
if (this.value.length > 0) {
secondDropDown(this.value);
} else {
var sec = document.getElementById('second_choice');
sec.innerHTML = '';
}
});
function secondDropDown(x) {
var sec = document.getElementById('second_choice');
sec.innerHTML = '<option selected>Please Select Language</option>';
var y = data[x];
for (const [key, value] of Object.entries(y)) {
sec.innerHTML += '<option value="' + value + '">' + key + '</option>';
}
}
<select id="first_choice">
<option selected value="">Please Select Country</option>
<!-- Appended options -->
</select>
<select id="second_choice">
</select>
I want to hide the option in the selection box if the option is already selected in another box. I am not sure where the problem is in my code, I tried running it on different editors it didn't work. Here is my code:
<html>
<head>
<title>Currency Converter</title>
</head>
<body>
<script langauge="javascript">
function CheckDropDowns() {
ListOfSelectedCountires = [];
for (CountryNumber = 0; CountryNumber < 3; CountryNumber++) {
ListOfSelectedCountires[CountryNumber] = document.getElementById("country" + (CountryNumber + 1)).value;
}
for (algoritmCountryNumber = 0; algoritmCountryNumber < 3; algoritmCountryNumber++) {
for (countryOptions = 1; countryOptions < 5; countryOptions++) {
document.getElementById("country" + (algoritmCountryNumber + 1)).options[countryOptions].style.display = "block";
for (processedOption = 0; processedOption < 3; processedOption++) {
if (document.getElementById("country" + (algoritmCountryNumber + 1).options[countryOptions].value == ListOfSelectedCountires[processedOption]) {
document.getElementById("country" + (algoritmCountryNumber + 1)).options[countryOptions].style.display = "none";
}
}
}
}
}
</script>
<section>
<select id="country1" onchange="CheckDropDowns()">
<option value="">Choose</option>
<option value="1">Australia</option>
<option value="2">Indonesian Rupiah</option>
<option value="3">Chinese Yaun</option>
<option value="4">Japanese Yen</option>
</select>
Convert to
<select id="country2" onchange="CheckDropDowns()">
<option value="">Choose</option>
<option value="1">Australia</option>
<option value="2">Indonesian Rupiah</option>
<option value="3">Chinese Yaun</option>
<option value="4">Japanese Yen</option>
</select>
</section>
</body>
</html>
First determine which select needs to be filtered, then loop through the options setting display to block first(to undo the previous filter), and then if the option's value matches the selected value set it's display to none.
Edit
Above method does not work in every browser. The better HTML5 way is to set and remove the hidden attribute. I've updated the snippet.
window.CheckDropDowns = function(thisSelect) {
var otherSelectId = ("country1" == thisSelect.id) ? "country2" : "country1";
var otherSelect = document.getElementById(otherSelectId);
for (i = 0; i < otherSelect.options.length; i++) {
//otherSelect.options[i].style.display = 'block';
otherSelect.options[i].removeAttribute('hidden');
if (otherSelect.options[i].value == thisSelect.value) {
//otherSelect.options[i].style.display = 'none';
otherSelect.options[i].setAttribute('hidden', 'hidden');
}
}
}
<section>
<select id="country1" onchange="CheckDropDowns(this)">
<option value="">Choose</option>
<option value="1">Australia</option>
<option value="2">Indonesian Rupiah</option>
<option value="3">Chinese Yaun</option>
<option value="4">Japanese Yen</option>
</select>
Convert to
<select id="country2" onchange="CheckDropDowns(this)">
<option value="">Choose</option>
<option value="1">Australia</option>
<option value="2">Indonesian Rupiah</option>
<option value="3">Chinese Yaun</option>
<option value="4">Japanese Yen</option>
</select>
</section>
I don't know what's wrong with your code, the logic seems convoluted. You can't reliably hide options by setting their display to 'none', in some browsers they remain visible. If it was that simple, life would be easy.
You can hide options by removing them from the list, but then you have to remember where they came from so you can put them back when the selection changes.
In the following, each time an option is selected, if there's one stored it's put back and the one matching the selected option is removed. If the first option is selected, the stored one is just put back, nothing is removed.
This only depends on the two selects having the same class value, they could be related by some other value (e.g. a data-* property).
Hopefully the comments are sufficient.
var matchSelected = (function() {
// Store for "hidden" node
var nodeStore = {
sourceElement: null,
node: document.createDocumentFragment(),
index: null
};
return function(evt) {
// Get the element that got the event
var tgt = this;
// If there's a stored option, put it back
if (nodeStore.sourceElement) {
let sel = nodeStore.sourceElement;
sel.insertBefore(nodeStore.node.firstChild, sel.options[nodeStore.index]);
nodeStore.sourceElement = null;
nodeStore.node = document.createDocumentFragment();
nodeStore.index = null;
}
// If the selected option is the first one, stop here
if (tgt.selectedIndex == 0) return;
// Get all selects with the same className
var sels = document.querySelectorAll('.' + this.className);
// Get the "other" option
var other = sels[0] == this ? sels[1] : sels[0];
// Remove and keep the option on the other element that is the same
// as the selected option on the target element
nodeStore.sourceElement = other;
nodeStore.index = tgt.selectedIndex;
nodeStore.node.appendChild(other.options[tgt.selectedIndex]);
}
}());
window.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.countrySelect').forEach(
node => node.addEventListener('change', matchSelected, false)
);
}, false);
<select id="country1" class="countrySelect">
<option value="" selected>Choose</option>
<option value="1">Australia Dollar</option>
<option value="2">Indonesian Rupiah</option>
<option value="3">Chinese Yaun</option>
<option value="4">Japanese Yen</option>
</select>
Convert to
<select id="country2" class="countrySelect">
<option value="" selected>Choose</option>
<option value="1">Australia Dollar</option>
<option value="2">Indonesian Rupiah</option>
<option value="3">Chinese Yaun</option>
<option value="4">Japanese Yen</option>
</select>
i have a textarea text "ez.aaaa.value" i want to typing a text and when i select option , redirect automatically to google.com/search?tbm=isch&q= + ((value textarea))
image
Example :
........
<option value="href='http://www.google.com/search?tbm=isch&q=' + ez.aaaa.value">google search</option>
........
This should do it.
the location.href is what you would use to link out.
this refers to the select and selectedIndex returns the number of the selected option.
var sel = document.getElementById('mysel'),
query = document.getElementById('myquery');
sel.addEventListener('change' , function() {
console.log(this.options[this.selectedIndex].value + query.value);
// this would be how to link below
// location.href = this.options[this.selectedIndex].value + query.value;
});
<input type='text' id="myquery">
<select id="mysel">
<option>SELECT ONE</option>
<option value="http://google.com?q=">google</option>
<option value="http://bing.com?q=">bing</option>
</select>
Add select with ID outside of your option and then try this way
JS
var e = document.getElementById("select-menu");
var strUser = e.options[e.selectedIndex].value;
console.log(strUser);
HTML
<select id="select-menu">
<option value="href='http://www.google.com/search?tbm=isch&q=' + ez.aaaa.value">google search 1</option>
<option value="href='http://www.google.com/search?tbm=isch&q=' + ez.aaaa.value" selected="selected">google search 2</option>
</select>