Dynamic country states dropdown menu - javascript

Hey I'm trying to create a form with a dropdown menu containing states are automatically filtered based on selected country. That is, only show the states of the selected country
JQuery
$("#shipment_sender_attributes_state_code").parent().hide()
$('#shipment_sender_attributes_country_code').change(function() {
states = $("#shipment_sender_attributes_state_code").html()
country = $('#shipment_sender_attributes_country_code :selected').val()
options = $(states).filter("optgroup[label='" + country + "']").html()
$states = $('#shipment_sender_attributes_state_code')
if (options) {
$states.html(options)
$states.parent().show()
} else {
$states.empty()
$states.parent().hide()
}
})
It works the first time I select a country, but if I select another, and then go back, the states variable remains empty and no drop down is shown. Any advice?
Form:
<optgroup label="us">
<option value="AA">Armed Forces Americas (AA)</option>
<option value="AE">Armed Forces Europe (AE)</option>
<option value="AK">Alaska (AK)</option>
<option value="AL">Alabama (AL)</option>
<option value="AP">Armed Forces Pacific (AP)</option>
<option value="AR">Arkansas (AR)</option>
....
<optgroup label="ca"><option value="AB">Alberta (AB)</option>
<option value="BC">British Columbia (BC)</option>
<option value="MB">Manitoba (MB)</option>
<option value="NB">New Brunswick (NB)</option>
<option value="NL">Newfoundland and Labrador (NL)</option>
....
EDIT JSfiddle
Can't quite get the fiddle working, but it's something like this
http://jsfiddle.net/d6cm5v6g/2/

Use var to declare your variables.
var states...
var country...
var options...
If you don't do that you are creating global variables

You need to do a minor change to your code:
$(function(){
$("#shipment_sender_attributes_state_code").parent().hide()
var states = $("#shipment_sender_attributes_state_code").html()
$('#shipment_sender_attributes_country_code').change(function() {
var country = $('#shipment_sender_attributes_country_code :selected').val()
var options = $(states).filter("optgroup[label='" + country + "']").html()
var $states = $('#shipment_sender_attributes_state_code')
if (options) {
$states.html(options)
$states.parent().show()
}
else {
$states.empty()
$states.parent().hide()
}
})
});
You need to move states outside the change function because in your else you do this $states.empty(), so the next time there is no html to filter(all options and optgroups are gone). This way you store the original value in an object.
I change the Afganistan value to "ca" in order for testing purposes(you can switch between Afganistan and United States)
Working fiddle:http://jsfiddle.net/robertrozas/4vxjpjLv/2/

Related

display a part of value in select option

I have a select drop-down with country and code. In drop-down option, for user experience and understanding i am displaying name of the country along with country code.
As a normal functionality when a user selects any value from the drop-down that value gets displayed inside the input like this
however i want that only the country code should get displayed like this
Part of my code
<select name="countrycode" class="form-control pf-country" id="countrycode">
<option data-countryCode="IN" value="91">Code</option>
<option data-countryCode="IN" value="91">India (+91)</option>
<option data-countryCode="US" value="1">USA (+1)</option>
<optgroup label="Other countries">
<option data-countryCode="DZ" value="213">Algeria (+213)</option>
<option data-countryCode="AD" value="376">Andorra (+376)</option>
</optgroup>
</select>
The entire code is available here
Can anyone please suggest how to do it.
As per my understanding, You can try this one. As this example providing exact output as you mentioned in your questions.
https://silviomoreto.github.io/bootstrap-select/examples/#selected-text
Basically we're trying to change innerText of selected-option. It can be achieved easily by adding onchange event listener to the select tag.
But there's a little problem, on changing innerText we lose previous value of innerText, solution by #KKK solves problem but leaves this little thing.
Following code handles problem in complete ways. We're adding data-innerText atribute with previous value of innerText and also id="previous" to identify it. Please check this demo.
function simpleTweak(select){
var previouslySelectedTag = document.getElementById('previous');
if(previouslySelectedTag!=undefined){
previouslySelectedTag.innerText = previouslySelectedTag.getAttribute('data-innerText');
previouslySelectedTag.setAttribute('id','');
}
var innerText = select.options[select.selectedIndex].innerText;
select.options[select.selectedIndex].setAttribute('data-innerText',innerText);
select.options[select.selectedIndex].setAttribute('id','previous');
var value="(+"+select.options[select.selectedIndex].value+")";
select.options[select.selectedIndex].innerText = value;
}
As I understood, you need to change the display text after selecting the option, is it? If so, you can do it like this.
You can set the selected index's text in onchange event. But it will reset the text in the option when you click the dropdown again. You may need to change it back if you prefer.
function displayCountryCode() {
var countrycode = document.getElementById("countrycode");
countrycode.options[countrycode.selectedIndex].text = '+' + countrycode.value;
}
<select name="countrycode" class="form-control pf-country" id="countrycode" onchange="displayCountryCode()">
<option data-countryCode="IN" value="91">Code</option>
<option data-countryCode="IN" value="91">India (+91)</option>
<option data-countryCode="US" value="1">USA (+1)</option>
<optgroup label="Other countries">
<option data-countryCode="DZ" value="213">Algeria (+213)</option>
<option data-countryCode="AD" value="376">Andorra (+376)</option>
</optgroup>
</select>
The following JavaScript code will change the text of the selected option when you select it and change it back when you select a different one.
It does this by saving the values of the country name and country number as HTML5 data attributes (option.dataset.countryName & option.dataset.countryNumber)
Doing it this way, you don't have to change the format of the HTML from what you provided in your post.
I used vanilla JavaScript, so it'll work with or without jQuery.
window.addEventListener('load', () => {
let select = document.getElementsByName('countrycode')[0]
let options = document.getElementsByTagName('option')
for (let i = 1; i < options.length; i++) {
let option = options[i]
let matches = option.innerText.match(/(.*?) (\(\+\d+\))/)
option.dataset.countryName = matches[1]
option.dataset.countryNumber = matches[2]
// Set the value in the collection again now that the object has been changed
options[i] = option
}
select.addEventListener('change', () => {
for (let i = 1; i < options.length; i++) {
let option = options[i];
option.innerText = option.dataset.countryName + ' '
option.innerText += option.dataset.countryNumber
}
let option = document.querySelector('option:checked')
if (option !== options[0]) {
option.innerText = option.dataset.countryNumber
}
})
})
There's also a demo at CodePen

sort a dropdown list with added atrribute or id

Currently I am working on a site where I do not have access to the perl generated options of a drop down list. The drop downs are populated dynamically and not all options are available to all users.
The code I am able to work with is shown here.
<select class="fielddrop" name="PRIMARY_POS" size="1" style="width: 187px;" ></select>
PRIMARY_POS
populates each option that is able to be selected.
The actual output as seen when the page renders is
<select class="fielddrop" name="PRIMARY_POS" size="1" style="width: 187px;">
<option value="0">None Selected
<option value="155935">Option4
<option value="155934">Option3
<option value="155905">Option2
<option value="155933">Option1
<option value="155932">Option5
</select>
What I need to be able to do is set a sort order based on a hidden attribute that is assigned based on the text value
So in the above example. I need the drop downs ( Important as their are mulitple drop downs on the page ) to be able to be sorted by a not yet created attribute
So that the above code might then be
<option value="0">None Selected
<option sortvalue="5" value="155935">Option4
<option sortvalue="4" value="155934">Option3
<option sortvalue="3" value="155905">Option2
<option sortvalue="2" value="155933">Option1
<option sortvalue="1" value="155932">Option5
</select>
The sortvalue being set base don the Text value of the option select. So that a sortvalue of 5 would be assign to Option4. Just a smaple as the text will need to be assigned.
End result should be that the Drop down list now has a custom attribute of Sortvalue and the select drop down is now sorted by that value.
Once again, I can not directly change the attributes but can manipulate the results. Hope that was easy to follow, which I doubt :/
You can create an object where the keys are the text and values are sort order. Then loop over options and add attribute based on that map
var optsMap = {
"Option4": 5,
"Option5": 1
......
};
var $select = $('select[name=PRIMARY_POS]')
$select.find('option').attr('data-sortvalue', function(){
return optsMap[$(this).text()] ||0;
}).sort(function(a,b){
return +($(a).data('sortvalue')||0) - +($(b).data('sortvalue')||0);
}).appendTo($select);
You can then read the value using:
$select.change(function(){
alert($(this).find(':selected').data('sortvalue'));
})
If all you are needing is sorting and don't need attribute can remove one step
DEMO
Common practice is to prefix those "added attributes" with data. You could try something like this with jQuery, if I'm understanding you correctly.
Example fiddle: https://jsfiddle.net/30cvudz8/7/
<select class="my-select">
<option data-sort-value="3" value="1">Option 1</option>
<option data-sort-value="5" value="2">Option 2</option>
<option data-sort-value="4" value="3">Option 3</option>
<option data-sort-value="1" value="4">Option 4</option>
<option data-sort-value="2" value="5">Option 5</option>
</select>
var optionList = new Array();
$('select.my-select option').each(function() {
optionList[optionList.length] = $(this).attr('data-sort-value')+'::'+$(this).val();
});
optionList.sort(); // sort it
var newOptionList = '';
for(var i = 0; i < optionList.length; i++) {
// recreate option
var parts = optionList[i].split('::');
newOptionList += '<option value="'+parts[1]+'" data-sort-value="'+parts[0]+'">Option '+parts[1]+'</option>';
}
// wipe and repopulate the select list
$('select.my-select').html(newOptionList);
To add an attribute (like data-sort-value) after you have a select list, you can do something like this:
$('select.original option').each(function() {
var sortingValue = getSortingValueFromText($(this).text());
$(this).attr('data-sort-value', sortingValue);
});

Update Select Menu based off another Selection

I have a list of states (USA) that includes Canadian provinces,
<select>
<optgroup label="United States">
<option value="AL">Alabama (AL)</option><option value="AK">Alaska (AK)</option><option value="AE">APO state (AE)</option><option value="AO">APO state (AO)</option><option value="AP">APO state (AP)</option><option value="AZ">Arizona (AZ)</option>
</optgroup>
<optgroup label="Canada">
<option value="AB">Alberta (AB)</option><option value="BC">British Columbia (BC)</option><option value="MB">Manitoba (MB)</option><option value="NB">New Brunswick (NB)</option><option value="NL">Newfoundland and Labrador (NL)</option></optgroup>
</select>
Then I have another select menu that includes 2 options, USA & Canada. (USA is default selected)
I want that if Canadian province is selected, disable USA as country in second select menu. and if Canada is selected in second select menu, remove USA states from first select menu.
I only found ways to populate the second select menu after choosing the first (like this http://jsfiddle.net/FK7ga/), but what I try is to show all by default, and update after selecting either one.
You can do something like this:
$("#filter").on("change", function() {
$states = $("#states");
$states.find("optgroup").hide().children().hide();
$states.find("optgroup[label='" + this.value + "']").show().children().show();
$states.find("optgroup[label='" + this.value + "'] option").eq(0).prop("selected", true);
});
See this working DEMO
#letiagoalves:
I've just edited your fiddle by changing show/hide to attr('disable','disable'); and removeAttr('disable'); This causes the list to stay, but prevent the wrong state group to get selected.
Just my 2 cents.
Was able to make it work as I wanted, with the help of #letiagoalves, Below is the code
$("#countries").on("change", function ()
{
if ($("#countries").find(":selected").val())
{
$states = $("#states");
$states.find("optgroup").hide().children().hide();
$states.find("optgroup[label='" + this.value + "']").show().children().show();
$states.find("optgroup[label='" + this.value + "'] option").eq(0).prop("selected", true);
}
else
{
$states.show().children().show().children().show();
}
});
$("#states").on("change", function () {
$countries = $("#countries");
if ($("#states").find("option:selected"))
{
var c = $("#states").find("option:selected").parent().attr("label");
$countries.find("option[value='" + c + "']").prop("selected", true);
$("#countries").change();
}
});
Still trying to make it work with #Alex-Amthor's idea of disable, will update answer if I succeed. meanwhile here is a demo on jsfiddle

Set HTML attribute value using java Script

I have html drop down list,which has country list. Now I want to set current country as a default value of list. I found the JavaScript code for get country using Geolocation.
My code:
function getCountry(var name) {
if(name==geoip_country_name()) {
return "selected";
}
}
Then I need to set the selected attribute of the option list.
I tried this:
<option value="Sri Lanka" selected="getCountry('sri Lanka')">Sri Lanka</option>
But this is not correct.
Basically I want to set selected attribute value using JavaScript function
How do I do that?
Use the window.onload event, and just set the dropdown's value. Keep in mind that your hard coded country names may differ from the geo service.
<script>
window.onload = function(){
document.getElementById("country").value = geoip_country_name();
}
</script>
<select id="country" name="country">
<option value="Sri Lanka">Sri Lanka</option>
<option value="UK">UK</option>
<option value="USA">USA</option>
<select>
Basically you can do it like this:
<html>
<body>
<select id="country">
<option id="germany" value="Germany">DE</option>
<option id="uk" value="UK">UK</option>
<option id="usa" value="USA">USA</option>
</select>
<script>
var selectedCountry = 'uk'; //getCountry
var index = document.getElementById(selectedCountry).index;
document.getElementById("country").selectedIndex=index;
</script>
Start the script after your select is rendered.
Note, that this example might not be best practice. I'm also not sure if it works in all browsers (Opera works). You might use an appropriate framework like JQuery, Mootools, ...
The selected attribute is not automatically evaluated as JS code. Assuming you have stored the desired country name in the variable country, could try this instead:
var country = "Sri Lanka";
var select = document.getElementById('myselect'); //Change to the ID of your select element
for (var i = 0; i < select.options.length; i++){
if(select.options[i].value == country)
select.selectedIndex = i;
}
If you are using JQuery following line should solve your problem:
$('select').val(geoip_country_name());
If geoip_country_name returns names in lower case, While initializing the select list, value for each option be in lower case.

javascript Change the Dropdown values based on other dropdown

I have a requirement When selected a dropdown value, it has to filter or remove the values of other dropdown which has index that should be always greater than selected index of first dropdown.
Ex: First Dropdown values:
01:00
01:30
02:00 // suppose i select 02:00 here
02:30
03:00
03:30
04:00
04:30
05:00
05:30
Second Dropdonw Values (on selected 02:00 in the above dropdown should look like below)
02:30
03:00
03:30
04:00
04:30
05:00
05:30
(Im using C# with Asp.net here.)
Any javascript to achieve above would be greatly appreciated
and using script as below as Salman Suggested
<body onload="select()">
<script language="javascript">
function select(){
var select1 = document.getElementById("ddlFrom");
var select2 = document.getElementById("ddlTo");
select1.onchange = function filterDDL() { // empty select2
while (select2.firstChild) {
select2.removeChild(select2.firstChild);
}
if (select1.selectedIndex == 0)
{
return;
}
for (var i = select1.selectedIndex; i < select1.options.length; i++)
{
var o = document.createElement("option");
o.value = select1.options[i].value;
o.text = select1.options[i].text;
select2.appendChild(o);
}
}
}</script>
but not working...please help on this
Thanks in advance
Edit (using jQuery to get desired results):
<select id="one">
<option value="01:00">01:00</option>
<option value="01:30">01:30</option>
<option value="02:00">02:00</option>
<option value="02:30">02:30</option>
<option value="03:00">03:00</option>
<option value="03:30">03:30</option>
</select>
<select id="two"></select>
<script type="text/javascript">
$(function () {
$("#one").change(function (e) {
$("#two").empty();
var options =
$("#one option").filter(function(e){
return $(this).attr("value") > $("#one option:selected").val();
}).clone();
$("#two").append(options);
});
});
</script>
Vanilla JavaScript solution and demo.
HTML
<select name="select1" id="select1">
<option value="">-- select an option --</option>
<option value="01:00">01:00</option>
<option value="01:30">01:30</option>
<option value="02:00">02:00</option>
<option value="02:30">02:30</option>
<option value="03:00">03:00</option>
<option value="03:30">03:30</option>
<option value="04:00">04:00</option>
<option value="04:30">04:30</option>
<option value="05:00">05:00</option>
<option value="05:30">05:30</option>
</select>
<select name="select2" id="select2">
</select>
JavaScript
// this function must be wrapped inside onload event
var select1 = document.getElementById("select1");
var select2 = document.getElementById("select2");
select1.onchange = function() {
// empty select2
while (select2.firstChild) {
select2.removeChild(select2.firstChild);
}
if (select1.selectedIndex == 0) {
return;
}
for (var i = select1.selectedIndex; i < select1.options.length; i++) {
var o = document.createElement("option");
o.value = select1.options[i].value;
o.text = select1.options[i].text;
select2.appendChild(o);
}
}
There are multiple ways to achieve this, each might be good for a different useage.
Filter by value
#Craig has suggested it already. Give the dropdown options values. When something's selected in the first one, values lower or equal to its value are removed from the second dropdown: http://jsfiddle.net/q8mLH/
Using an array of available pairs
Create an array of the pairs you're interested in, then when select 1 is changed, update select2 available options based on what is defined in your array of allowed pairs: http://jsfiddle.net/AU6hq/
AJAX + database pairs
I'm not going to specify an example here, sorry, but the general idea is this: you need to have some tables in your database, let's say "countries" and "cities", where each country has an ID, and each city has its own unique ID plus the ID of the country where it lies. You'll want to display only the cities in the selected country, probably.
You bind the change() event to the counties select and load the contents of the second select via an ajax call, querying the database for the cities that lie in the selected country.
There might be more, but I don't quite feel like thinking too much today ;). Anyway, I hope this helps.
[EDIT]
My examples use jQuery, I hope it's not a problem.

Categories

Resources