Slicing elements from three select menus into and out of array - javascript

var select1 = document.getElementById('select1');
var select2 = document.getElementById('select2');
var array = [];
let sel1 = false;
function myFunct1() {
var one = select1.options[select1.selectedIndex].value;
if(array.length === 1 && !sel1) array.unshift(one);
else array.splice(0,1,one);
console.log(array);
sel1 = true;
}
function myFunct2() {
var two = select2.options[select2.selectedIndex].value;
array.splice(sel1, 1, two);
console.log(array);
}
function myFunct3() {
var three = select3.options[select3.selectedIndex].value;
}
<select id = 'select1' onchange = 'myFunct1()'>
<option disabled selected value> -- select an option -- </option>
<option value = 'Dog1'>Dog</option>
<option value = 'Cat1'>Cat</option>
<option value = 'Bear1'>Bear</option>
</select>
<select id = 'select2' onchange = 'myFunct2()'>
<option disabled selected value> -- select an option -- </option>
<option value = 'Dog2'>Dog</option>
<option value = 'Cat2'>Cat</option>
<option value = 'Bear2'>Bear</option>
</select>
<select id = 'select3' onchange = 'myFunct3()'>
<option disabled selected value> -- select an option -- </option>
<option value = 'Dog3'>Dog</option>
<option value = 'Cat3'>Cat</option>
<option value = 'Bear3'>Bear</option>
</select>
I have this method that works exactly how I want it with two select menus. So if you select twice in a row from the second select the array's length is never more than one until you select from the first. Now I want to incorporate a third select menu. Please help me make this work. I'm aware I could combine them all into one function and not have to deal with these issues but for my use, I can't do that. The main condition is that there is never multiple selections within the array from the same select menu and never any empty positions within the array that still count towards its length. so an array of [undefined, Cat2] does not occur.

The simple way is:
Create two arrays i.e realArr(to keep strings at original indexes). For example value from select1 will always we set to realArr[0] and from select2 to realArr[1]...
Second array showArr is array from which you will remove undefined using filter()
var select1 = document.getElementById('select1');
var select2 = document.getElementById('select2');
var select3= document.getElementById('select3');
var realArr = [];
var showArr = [];
function myFunct1() {
var one = select1.options[select1.selectedIndex].value;
realArr[0] = one;
showArr = realArr.filter(x => x !== undefined);
console.log(showArr);
}
function myFunct2() {
var two = select2.options[select2.selectedIndex].value;
realArr[1] = two
showArr = realArr.filter(x => x !== undefined);
console.log(showArr);
}
function myFunct3() {
var three = select3.options[select3.selectedIndex].value;
realArr[2] = three;
showArr = realArr.filter(x => x !== undefined);
console.log(showArr);
}
<select id = 'select1' onchange = 'myFunct1()'>
<option disabled selected value> -- select an option -- </option>
<option value = 'Dog1'>Dog</option>
<option value = 'Cat1'>Cat</option>
<option value = 'Bear1'>Bear</option>
</select>
<select id = 'select2' onchange = 'myFunct2()'>
<option disabled selected value> -- select an option -- </option>
<option value = 'Dog2'>Dog</option>
<option value = 'Cat2'>Cat</option>
<option value = 'Bear2'>Bear</option>
</select>
<select id = 'select3' onchange = 'myFunct3()'>
<option disabled selected value> -- select an option -- </option>
<option value = 'Dog3'>Dog</option>
<option value = 'Cat3'>Cat</option>
<option value = 'Bear3'>Bear</option>
</select>

Related

move option from one select to another select with JS

From two html selects, I would like to move when I click the button to move an option to another select with javascript vanila, and when it has been moved, it is removed from the select from where it was at the beginning. It should also work the other way around.
function move1() {
var x = document.getElementById("select1");
}
function move2() {}
<select id="select1">
<option value="0">1</option>
<option value="0">2</option>
<option value="0">3</option>
</select>
<button type="button" onclick="move1()">>></button>
<button type="button" onclick="move2()"><<</button>
<select id="select2"></select>
You can do it like this:
Fetch both selects with getElementById() and store them in select_1 and select_2 variables.
Check if selected option exists by compering selectedIndex property of the select with -1. It will be equal to -1 only if the user didn't select anything.
If selectedIndex is equal to -1, then do nothing because there is nothing to transfer to second select.
If selectedIndex is different from -1, it means that user selected something and option with that index should be transfered.
Create new option for second select with document.createElement('option') and copy the selected option values to the new option.
Remove the selected option of current select with select.options.remove(select.selectedIndex)
function move1() {
const select_1 = document.getElementById("select1");
const select_2 = document.getElementById("select2");
if(select_1.selectedIndex !== -1) {
const selected_option = select_1.options[select_1.selectedIndex];
let new_option = document.createElement('option');
new_option.value = selected_option.value
new_option.innerHTML = selected_option.innerHTML;
select_2.appendChild(new_option);
select_1.options.remove(select_1.selectedIndex)
}
}
function move2(){
const select_1 = document.getElementById("select1");
const select_2 = document.getElementById("select2");
if(select_2.selectedIndex !== -1) {
const selected_option = select_2.options[select_2.selectedIndex];
let new_option = document.createElement('option');
new_option.value = selected_option.value
new_option.innerHTML = selected_option.innerHTML;
select_1.appendChild(new_option);
select_2.options.remove(select_2.selectedIndex)
}
}
<select id="select1">
<option value="0">1</option>
<option value="0">2</option>
<option value="0">3</option>
</select>
<button type="button" onclick="move1()">>></button>
<button type="button" onclick="move2()"><<</button>
<select id="select2"></select>
Here's a version that can manage more than 2 sets of <select> and <button> pairs. If there are more than 2 pairs, all recieving <select> will add the selcted <option>. In the HTML a data-* attribute is added to each <option>:
<option data-idx="0" value='1'>1</option>
<option data-idx='1' value="2">2</option>
<option data-idx='2' value="3">3</option>
The value of data-idx is the <option>s original index position. In the event handler switchOPt(e) the data-idx value will be used to determine what index it should be placed in:
to.add(copy, +copy.dataset.idx);
All details are commented in the example.
/*
Collect all buttons into a HTMLCollection then convert it
into an Array. Same with all select
*/
const btnArray = [...document.querySelectorAll('button')];
const selArray = [...document.querySelectorAll('select')];
/*
Iterate through the array of buttons. Register each button
to the click event. The event handler is switchOpt(e)
*/
btnArray.forEach(btn => btn.addEventListener('click', switchOpt));
// Event handler always passes the Event Object
function switchOpt(e) {
/*
Determine the select that will send it's option by
matching it's #id vs this.name (the [name] of the button
the user clicked
*/
const from = document.getElementById(this.name);
// if the select doesn't have any options end function
if (from.childElementCount < 1) return;
/*
Determine the select that adds an option by .filter()
under the condition that it is NOT >from<
*/
let to = selArray.filter(sel => sel.id != from.id);
// Rereference >to< to be the select with the array
to = to[0];
// Determine which option has been selected
const opt = from.options[from.selectedIndex];
// Make a copy of the selected option
const copy = opt.cloneNode(true);
/*
Add >copy< to >to< the second parameter is the index
of the element that >copy< will be placed before it so
it'll always be in order
*/
to.add(copy, +copy.dataset.idx);
// Remove the option from >from<
opt.remove();
}
<!-- Assign each option a data attribute wuth the value
of it's index -->
<select id="A">
<option data-idx='0' value="1">1</option>
<option data-idx='1' value="2">2</option>
<option data-idx='2' value="3">3</option>
</select>
<button name='A' type="button">>></button>
<button name='B' type="button"><<</button>
<select id="B"></select>

Simplify setOptionByValue(selectElement, value) function for <select> element. How?

When data is received from a JSON api, one of the data properties is used to set the selected option value of a select html element.
The following code sets the option to be selected based on the select html element and the corresponding select option value passed in.
Is there a shorter version of this nowadays?
Take a look:
// Custom function to set select option by value
const setOptionByValue = (selectElement, value) => {
let options = selectElement.getElementsByTagName('option');
for (let i = 0, optionsLength = options.length; i < optionsLength; i++) {
// console.log(options[i].value);
if (options[i].value == value) {
selectElement.selectedIndex = i;
return true;
}
}
return false;
}
// The select element
const selectStatus = document.getElementById('selectStatus');
// Initially set status to Draft.
setOptionByValue(selectStatus, 'Draft');
<label for="selectStatus">Status:</label>
<select id="selectStatus">
<option value="0" selected>Select...</option>
<option value="Draft">Draft</option>
<option value="Pending">Pending</option>
<option value="Complete">Complete</option>
</select>
Just assign the value to the select element's value
// Custom function to set select option by value
const setOptionByValue = (selectElement, value) => {
selectElement.value = value;
}
// The select element
const selectStatus = document.getElementById('selectStatus');
// Initially set status to Draft.
setOptionByValue(selectStatus, 'Draft');
<label for="selectStatus">Status:</label>
<select id="selectStatus">
<option value="0" selected>Select...</option>
<option value="Draft">Draft</option>
<option value="Pending">Pending</option>
<option value="Complete">Complete</option>
</select>
Should the value of the option differ from its content and you wish to select by content:
// Custom function to set select option by value
const setOptionByValue = (selectElement, value) => {
selectElement.querySelectorAll('option').forEach((e) => {
if (e.innerHTML == value) {
selectElement.value = e.value;
}
})
}
// The select element
const selectStatus = document.getElementById('selectStatus');
// Initially set status to Draft.
setOptionByValue(selectStatus, 'Draft');
<label for="selectStatus">Status:</label>
<select id="selectStatus">
<option value="0" selected>Select...</option>
<option value="Draft">Draft</option>
<option value="Pending">Pending</option>
<option value="Complete">Complete</option>
</select>

How to set the default value on select dropdowns with javascript after AJAX call

I have a program that generates a table rows based on part selections from a dropdown menu. On each row that is created, I have a <td> element that contains a dropdown for quantity. My problem is that when a new part is selected thus creating a new row, all my quantity dropdowns reset back to the default value of 1. I tried fixing it with "selected = true;" but that doesn't seem to work. Basically, I need to set the selected value of each quantity dropdown to stay as whatever selected value it was last set at when the user adds a new row. I'm using an ajax call to generate the data from a SQL table on each new row.
Here is the function which is called from the select dropdown. I've omitted a lot of unnecessary code:
function update(){
var selectLists = document.getElementsByName("qty_dropdown");
for(var i = 0; i < selectLists.length; i++){
var firstSelectList = selectLists[i].value;
}
}
Here is my dropdown:
<td>
<select name = "qty_dropdown" onChange = "update()">
<option value = '1'> 1 </option>
<option id = '2'value = '2'> 2 </option>
<option value = '3'> 3</option>
<option value = '4'> 4 </option>
<option value = '5'> 5 </option>
<option value = '6'> 6 </option>
<option value = '7'> 7 </option>
<option value = '8'> 8 </option>
<option value = '9'> 9 </option>
<option value ='10'> 10</option>
</td>
</select>
The function you are performing inside update() (i renamed it to add() ) should be performed on the addition of new row.
function add(){
var selectLists = document.getElementsByName("qty_dropdown");
var firstSelectList=[];
for(var i = 0; i < selectLists.length; i++){
firstSelectList.push(selectLists[i].value);
}
document.getElementById("inject").innerHTML+="<select name = 'qty_dropdown' onChange = 'update()'> <option value = '1'> 1 </option> <option id = '2'value = '2'> 2 </option> <option value = '3'> 3</option> <option value = '4'> 4 </option> <option value = '5'> 5 </option> <option value = '6'> 6 </option> <option value = '7'> 7 </option> <option value = '8'> 8 </option> <option value = '9'> 9 </option> <option value ='10'> 10</option> </select> ";
for(var i = 0; i < selectLists.length-1;i++){
selectLists[i].value=firstSelectList[i];
}
}
this function add() will add a new row without resetting previous dropdown.
Demo : https://jsfiddle.net/0wur28ot/
What i did is save the value in array before adding new row and then i assigned values to the dropdown accordingly after row addition.
Here is one way you can do it. You can keep a variable around that keeps track of the most recently selected dropdown value, and when you add a new dropdown to the DOM, it will use that value as its initial value.
var lastUpdatedDropdownValue = "";
function update(event) {
lastUpdatedDropdownValue = event.target.value;
}
function addNewDropdown() {
var dropdown = document.querySelector("[name=qty_dropdown]");
var newDropdown = dropdown.cloneNode(true); // make sure no duplicate IDs. If your elements that are being cloned have IDs, remove them before re-inserting into the DOM
document.getElementById("dropdownContainer").append(newDropdown);
var selectedOption = newDropdown.querySelector("[value='" + lastUpdatedDropdownValue + "']");
selectedOption.selected = true;
}
<button onclick="addNewDropdown()">Add New Dropdown</button>
<div id="dropdownContainer">
<select name="qty_dropdown" onChange="update(event)">
<option value='1'>1</option>
<option value='2'>2</option>
<option value='3'>3</option>
<option value='4'>4</option>
<option value='5'>5</option>
<option value='6'>6</option>
<option value='7'>7</option>
<option value='8'>8</option>
<option value='9'>9</option>
<option value='10'>10</option>
</select>
</div>

Remove the duplicate values and combinations in html select option

I have a dynamically generated <select> field with <option>.
<select>
<option value=""></option>
<option value=""></option>
<option value=""> False</option>
<option value=""> True</option>
<option value="">False False</option>
<option value="">False True</option>
<option value="">True</option>
<option value="">True True</option>
</select>
I would like to remove the duplicate occurrences and combinations. The final <select> field with <option> should look like :
<select>
<option value=""></option>
<option value="">False</option>
<option value="">True</option>
</select>
Here is how my fiddle looks like. Been trying to solve this for hours.
var values = [];
$("select").children().each(function() {
if (values.length > 0) {
var notExists = false;
for (var x = 0; x < values.length; x++) {
var _text = this.text.replace(/\s/g, "");
var value = values[x].replace(/\s/g, "");
if (values[x].length > _text.length) {
//console.log('>>+', value, ' || ', _text, value.indexOf(_text))
notExists = value.indexOf(_text) > -1 ? true : false;
} else {
//console.log('>>*', value, ' || ', _text, _text.indexOf(value))
notExists = _text.indexOf(value) > -1 ? true : false;
}
}
if (notExists) {
//this.remove();
values.push(this.text);
}
} else {
values.push(this.text);
}
});
Any help to solve this is appreciated.
You can use map() to return all options text and use split() on white-space. Then to remove duplicates you can use reduce() to return object. Then you can empty select and use Object.keys() to loop each property and append to select.
var opt = $("select option").map(function() {
return $(this).text().split(' ')
}).get();
opt = opt.reduce(function(o, e) {return o[e] = true, o}, {});
$('select').empty();
Object.keys(opt).forEach(function(key) {
$('select').append(' <option value="">'+key+'</option>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select>
<option value=""></option>
<option value=""></option>
<option value="">False</option>
<option value="">True</option>
<option value="">False False</option>
<option value="">False True</option>
<option value="">True</option>
<option value="">True True</option>
</select>
You can loop through each of this children text , then use substring to get the first text & put it in an array.
Once done empty the select element and append the newly created options
var _textHolder=[]; // NA empty array to hold unique text
var _options="";
$("select").children().each(function(item,value) {
var _textVal = $(this).text().trim(); // Remove white space
//get the first text content
var _getText = _textVal.substr(0, _textVal.indexOf(" "));
// if this text is not present in array then push it
if(_textHolder.indexOf(_getText) ==-1){
_textHolder.push(_getText)
}
});
// Create new options with items from _textHolder
_textHolder.forEach(function(item){
_options+='<option value="">'+item+'</option>'
})
// Empty current select element and append new options
$('select').empty().append(_options);
JSFIDDLE
I would do with pure JS ES6 style. This is producing a words array from the whitespace separated options element's innerText value regardless the words are in the front, middle or the end; and it will create a unique options list from that. Basically we are concatenating these arrays and getting it unified by utilizing the new Set object. The code is as follows;
var opts = document.querySelector("select").children,
list = Array.prototype.reduce.call(opts, function(s,c){
text = c.innerText.trim().split(" ");
return new Set([...s].concat(text)) // adding multiple elements to a set
},new Set());
list = [...list]; // turn set to array
for (var i = opts.length-1; i >= 0; i--){ //reverse iteration not to effect indices when an element is deleted
i in list ? opts[i].innerText = list[i]
: opts[i].parentNode.removeChild(opts[i]);
}
<select>
<option value=""></option>
<option value=""></option>
<option value=""> False</option>
<option value=""> True</option>
<option value="">False False</option>
<option value="">False True</option>
<option value="">True</option>
<option value="">True True</option>
</select>

How can I remove options with the same text from a select element?

I have a select element that shows multiple options with the same text:
<select name="tur" id="tur">
<option value="1">a</option>
<option value="2">a</option>
<option value="3">a</option>
<option value="4">a</option>
<option value="5">b</option>
<option value="6">b</option>
<option value="7">c</option>
<option value="8">d</option>
</select>
Using JavaScript, I would like to remove these duplicates so that only one of each is shown:
<select name="tur" id="tur">
<option value="1">a</option>
<option value="5">b</option>
<option value="7">c</option>
<option value="8">d</option>
You can loop through the <option> elements, checking each one to see if its text content is in an array. If it is, remove the <option>. If not, add its content to the array. This will remove options that are redundant in the list.
Try it out: http://jsfiddle.net/FXq8W/
​var array = [];
​$('#tur option').each(function() {
var $th = $(this);
var text = $th.text();
if( $.inArray(text, array) > -1 ) {
$th.remove();
} else {
array.push( text );
}
});​​​​​​​​​​​​​​
http://api.jquery.com/jquery.inarray/
var remove = [], values = {}, value, i;
var options = document.getElementById('tur').getElementsByTagName('option');
for (i=0; i<options.length; i++) {
value = options[i].innerHTML.replace(/^\s*|\s*$/g, '');
if (value in values) remove.push(options[i]);
else values[value] = true;
}
for (i=0; i<remove.length; i++) {
remove[i].parentNode.removeChild(remove[i]);
}

Categories