Image of empty list
Showing populated options within inspector
I dynamically add options through a JS file based on the DB items. They sometimes populate when I CTRL+SHIFT+R hard refresh the page but not every time.
They never populate when I do a regular refresh (ctrl+r).
I am genuinely so confused how the options could be populated inside the inspector but not actually visible..
The JS is also surrounded with $(document).ready(function ()) so to my knowledge it only runs once the page is ready.
Function where I populate one of the dropdowns
function renderEndUseDropdown()
{
var endUseList = new Set(filteredProductList.map((element) => element.endUse));
var endUse = Array.from(endUseList);
var endUseSelection = document.getElementById("processname");
for(var i = 0; i < endUse.length; i++)
{
if(endUse[i] !== '')
{
var option = endUse[i];
var displayElement = document.createElement("option");
displayElement.textContent = option;
displayElement.value = option;
endUseSelection.add(displayElement);
}
}
}
The above code would be adding options to this block of HTML
<div class="col-xs-12 col-sm-6 col-md-2">
<select class="selectpicker" multiple="multiple" data-live-search="true" title="End Use" id="processname" multiple data-actions-box="true">
</select>
</div>
Since you are using bootstrap-select, this needs to be done.
So your function could be updated like below.
function renderEndUseDropdown()
{
var endUseList = new Set(filteredProductList.map((element) => element.endUse));
var endUse = Array.from(endUseList);
var endUseSelection = document.getElementById("processname");
for(var i = 0; i < endUse.length; i++)
{
if(endUse[i] !== '')
{
var option = endUse[i];
var displayElement = document.createElement("option");
displayElement.textContent = option;
displayElement.value = option;
endUseSelection.add(displayElement);
}
}
$('#processname').selectpicker('refresh');
}
Related
I am trying to create 2 drop down menus, where the first list is linked to the second list (the second list is updated each time I select something in the first one).
I have some code that works, but it seems a little bit confusing to me.
Also this is working only if the script is in the body. If I move it to the head it doesnt work.
Why?
Can the same thing be implemented in some other way for example with the use of a 2d array, with the use on only Javascript?
var sel1 = document.querySelector('#sel1');
var sel2 = document.querySelector('#sel2');
var options2 = sel2.querySelectorAll('option');
function giveSelection(selValue) {
sel2.innerHTML = '';
for (var i = 0; i < options2.length; i++) {
if (options2[i].dataset.option === selValue) {
sel2.appendChild(options2[i]);
}
}
}
giveSelection(sel1.value);
<h1><b>Title</b></h1>
<select id="sel1" onchange="giveSelection(this.value)">
<option value="0"></option>
<option value="a">a</option>
<option value="b">b</option>
</select>
<select id="sel2">
<option data-option="a">apple</option>
<option data-option="a">airplane</option>
<option data-option="b">banana</option>
<option data-option="b">book</option>
</select>
Yes... It should not work. because when the script is in the head section. #self1 object and the #sel2 DOM elements are not on the DOM when it executes. when It's in the body section DOM elements are created on the DOM. one way to make it work is to bring those element referencing variables inside of the function as below.
function giveSelection(selValue) {
var sel1 = document.querySelector('#sel1');
var sel2 = document.querySelector('#sel2');
var options2 = sel2.querySelectorAll('option');
sel2.innerHTML = '';
for (var i = 0; i < options2.length; i++) {
if (options2[i].dataset.option === selValue) {
sel2.appendChild(options2[i]);
}
}
}
And believe me, It is not an efficient way. It's a best practice to include javascript to the bottom of the page and CSS to the top of the page. Including your script in the bottom of the body section is alright.
In order to use that script from head section you need to use window.onload that will fired when the DOM is ready.
In your case you can do something like that:
<head>
<script>
const load = () => {
sel1 = document.querySelector('#sel1');
sel2 = document.querySelector('#sel2');
options2 = sel2.querySelectorAll('option');
giveSelection(sel1.value);
}
function giveSelection(selValue) {
sel2.innerHTML = '';
for (var i = 0; i < options2.length; i++) {
if (options2[i].dataset.option === selValue) {
sel2.appendChild(options2[i]);
}
}
}
window.onload = load;
</script>
</head>
codepen
function populateList(givenID)//givenID from the select tag
{
var select = document.getElementById("givenID"),
listData = ["1","2"];
for(var i = 0; i < listData.length; i++)
//Loops through array and creates a new DOM node and appends array contents to the object
{
var option = document.createElement("OPTION"),
txt = document.createTextNode(listData[i]);
option.appendChild(txt);
option.setAttribute("value",listData[i]);
select.insertBefore(option,select.lastChild);
}
}
<body >
<select id="slt" whenpageloads="populateList">
<!--When the page loads the select tag will be populated -->
<option>
default
</option>
</select>
</body>
You can call onload like Arun has mentioned on body load.
<body onload="populateList('slt')">
or
This will be better choice if you want to load more than one select boxes.
window.onload = function() {
populateList('slt');
};
Apart from that there was one more mistake in your code, as givenID is variable.
var select = document.getElementById(givenID);
instead of
var select = document.getElementById("givenID");
function populateList(givenID)//givenID from the select tag
{
var select = document.getElementById(givenID);
listData = ["1","2"];
for(var i = 0; i < listData.length; i++)
{
var option = document.createElement("OPTION"),
txt = document.createTextNode(listData[i]);
option.appendChild(txt);
option.setAttribute("value",listData[i]);
select.insertBefore(option, select.lastChild);
}
}
window.onload = function() {
populateList('slt');
};
<body>
<select id="slt">
<option>
default
</option>
</select>
</body>
Complete JS novice. I want a "Request A Quote" button to auto-populate a dropdown menu on a new page based on the product and url. Each product quote button links to the same form but with a different hash value in the url which matches an option in the dropdown menu.
Example:
User clicks "Request A Quote" for 'Product A'
User is sent to www.example.com/request-a-quote/#Product A
Product dropdown menu (id=product-select) on form already reads "Product A"
This code works on Chrome, but not for anything else. What am I doing wrong?
//Get select object
var objSelect = document.getElementById("product-select");
var val = window.location.hash.substr(1);
//Set selected
setSelectedValue(objSelect, val)
function setSelectedValue(selectObj, valueToSet) {
for (var i = 0; i < selectObj.options.length; i++) {
if (selectObj.options[i].text== valueToSet) {
selectObj.options[i].selected = true;
return;
}
}
}
I found that applying decodeURIComponent() cleaned up my val variable.
Also, building links as www.example.com/request-a-quote/#Product A is important. If the forward slash is not before the hash, mobile Safari will ignore everything after the hash and it won't work.
Below is my final solution:
//Get select object
var objSelect = document.getElementById("product-select");
var val = decodeURIComponent(window.location.hash.substr(1));
//Set selected
setSelectedValue(objSelect, val)
function setSelectedValue(selectObj, valueToSet) {
for (var i = 0; i < selectObj.options.length; i++) {
if (selectObj.options[i].text== valueToSet) {
selectObj.options[i].selected = true;
return;
}
}
}
Without seeing more code.... The option tag officially supports the value attribute vs text which is the user readable name. We use value as an identifier:
selectObj.options[i].value == valueToSelect;
You will also need to change the select.options markup to use the value attribute rather then text.
UPDATE more info as requested:
The purpose of text is to provide a user readable option. We use value to identify the selection to the server and in your case the URL hash. By using the value attribute, you can use URL safe values and user readable text.
The fix you posted in your answer is really bad practice and will become problematic as the complexity of your code increases.
This example will work in all browsers and is the proper way to implement.
//Simulate hash
window.location.hash = '2'
var val = window.location.hash.substr(1);
var selectEle = document.getElementById('select')
setSelectedValue(selectEle, val)
function setSelectedValue(selectObj, valueToSet) {
for (var i = 0; i < selectObj.options.length; i++) {
var selection = selectObj.options[i]
if (selection.value == valueToSet) {
selection.selected = true;
}
}
}
<select name="selections" id="select">
<option value="1">Product A</option>
<option value="2">Product B</option>
<option value="3">Product C</option>
</select>
So I'm trying to change an image based on which option the user selects from a dropdown menu. My images for now are "cyan.png", "magenta.png", "yellow.png", "black.png", and "fuschia.png".
My HTML
<select name="color" multiple>
<option>Cyan</option>
<option>Magenta</option>
<option>Yellow</option>
<option>Black</option>
<option>Fuschia</option>
</select>
My JavaScript
// This part tries to load all images onto the carArray variable
var nameArray = new Array("cyan.png", "magenta.png", "yellow.png", "black.png", "fuschia.png");
var carArray = new Array;
for(var i = 0; i < carArray.length; i++) {
carArray[i] = new Image;
carArray[i].src = nameArray[i];
}
// This part tries (and fails) to change the image when the user selects a color from a dropdown menu
window.onload = function() {
var colorPicker = document.getElementsByName("color").selectedIndex;
var options = document.getElementsByName("color").options;
document.getElementById("photo").src = carArray[options[colorPicker];
}
Could you please help me understand what the problem is, and how to fix it.
If you bind your function on window.onload, it will only fire once at windows loading. You probably want to bind it on the select onchange event.
E.g.:
function pickColor() {
var colorPicker = document.getElementsByName("color").selectedIndex;
var options = document.getElementsByName("color").options;
document.getElementById("photo").src = carArray[options[colorPicker]];
}
<select name="color" onchange="pickColor()" multiple>
...
As #LightStyle suggests, you should avoid inline event assignments. I don't know your DOM, so for simplicity I'll add an id (it must be unique in the page) to your select. You can then do the following:
document.getElementById('color').onchange = function() {
var colorPicker = document.getElementsByName("color").selectedIndex;
var options = document.getElementsByName("color").options;
document.getElementById("photo").src = carArray[options[colorPicker]];
}
<select name="color" id="color" multiple>
Every relevant "question that may already have [my] answer" uses jQuery, which I am not using.
So, is there any simple way to get the values of selected options in a <select multiple> tag, or do I have to loop through all the options to see which ones are selected and manually build an array?
Side-question: Which browsers don't support selectElement.value and instead require selectElement.options[selectElement.selectedIndex].value?
You can use select.selectedOptions. However, this returns an HTMLCollection, so you still have to clean it to get a string array. http://jsfiddle.net/9gd9v/
<select multiple>
<option value="foo" selected>foo</option>
<option value="bar">bar</option>
<option value="baz" selected>baz</option>
</select>
and:
var select = document.querySelector("select");
var values = [].map.call(select.selectedOptions, function(option) {
return option.value;
});
If you end up wanting to loop through and grab the selected values you could use something like this:
function loopSelected()
{
var txtSelectedValuesObj = "";
var selectedArray = new Array();
var selObj = document.getElementById('selectID');
var i;
var count = 0;
for (i=0; i<selObj.options.length; i++) {
if (selObj.options[i].selected) {
selectedArray[count] = selObj.options[i].value;
count++;
}
}
txtSelectedValuesObj = selectedArray;
alert(txtSelectedValuesObj);
}
You can view an example HERE, adapted from this example.
.
You could also simply track the selected options via the onchange event in real-time and collect them whenever you want them. I admit it's still looping, but at least you're not doing it every time you need to retrieve the selected options, and it has the added bonus of being simple (come retrieval time, anyway...). Working fiddle: http://jsfiddle.net/cyg9Z/
var Test;
if (!Test) {
Test = {
};
}
(function () {
Test.trackSelected = function (e) {
var selector = document.getElementById('selector'),
selected = [],
i = 0;
for (i = 0; i < selector.children.length; i += 1) {
if (selector.children[i].selected) {
selected.push(selector.children[i].value)
}
}
selector.selMap = selected;
};
Test.addListeners = function () {
var selector = document.getElementById('selector'),
tester = document.getElementById('tester');
selector.onchange = Test.trackSelected;
tester.onclick = Test.testSelected;
};
Test.testSelected = function () {
var div = document.createElement('div');
div.innerText = document.getElementById('selector').selMap.join(', ');
document.body.appendChild(div);
};
Test.addListeners();
}());