storing content of dom elements inside an object - javascript

I have this function client_choice() which returns the stored value of dom elements if conditions are met
it iterates over each key and value , the keys and values are the content of dom elements
I tried to declare them outside the function and insert this objects as arguments, which does not work, I tried an click event which does not fire
also inserting them inside the function did not work either
question is how do i pass the content of the dom elements to the function ?
let file1 = $('#select_updateFile option:selected').text();
let file2 = $('#select_updateFile option').eq(2).text();
let column = $('.column_select option:selected').text();
// condition
let condition = $('.condition_select option:selected').text();
let update_data = {file1: column};
let conditon_data = {file2: condition};
function client_choice() {
const keyCondtion_true = (currentValue) => currentValue !== "select column" && currentValue !== "";
const valueCondition_true= (currentValue) => currentValue !== "select column" && currentValue !== "";
// variables
let meta_data = {...update_data, ...conditon_data};
if (Object.keys(meta_data).every(keyCondtion_true) && Object.values(meta_data).every(valueCondition_true)) {
return {"update": update_data, "condition": conditon_data}
} else {
console.log("both wrong")
return false
}
}
html
<select name="selectFile" id="selectFile">
<option value="">choose File</option>
<option class="file1" value="col1.xlsx">file1.txt</option>
<option class="file2" value="col2.xlsx">file2.xlsx</option>
</select>
<select name="column_select" class="columselect">
<option value="">choose Columns</option>
<option class="column" value="column1">column1</option>
<option class="column" value="column2">column2</option>
<option class="column" value="column3">column3</option>
<option class="column" value="column4">column4</option>
</select>
<select name="condition_select" class="condition_select">
<option value="">choose condtiton</option>
<option class="condtiton" value="condtiton1">condtiton1</option>
<option class="condtiton" value="condtiton2">condtiton2</option>
<option class="condtiton" value="condtiton3">condtiton3</option>
<option class="condtiton" value="condtiton4">condtiton4</option>
</select>
<button type="button" id="button">click me !!!</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

Related

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>

Update selected value in dropdown list depending on other lists selected values

i'm trying to figure out how can i make dynamic selection of values in few dropdown lists using Vanilla JS. I have 3 dropdown lists with same values. Each of them should have different value selected at the same time (duplicates not allowed). So once user changes another value in one list, value of another list should be updated accordingly. Basically, i need to swap their numbers in such case. But i can't complete the task as I'm quite new to JS and overall in programming. I tried following:
// defining initial values
var startPoint = document.querySelectorAll("select");
// function to recalculate value of each list on change
function calculateNewValues() {
var changes = new Array();
// getting updated values from lists as an array
var updatedValues = document.querySelectorAll("select");
// looping through array
for (let i = 0; i < updatedValues.length; i++) {
// if in updated array value of current index isn't equal to value
// of index in initial array
if (updatedValues[i].value != startPoint[i].value) {
// creating variable changes for tracking
changes[i] = updatedValues[i].value;
}
// if var changes has been defined (i.e. value of any list was updated)
if (changes.length > 0) {
// finding index of initial array with same value
var key = startPoint.findIndex(changes[i]);
// setting value of found index to previously stored value in updated list
updatedValues[key].value = startPoint[i].value;
}
}
updatedValues.forEach(element => {
console.log(element.value);
});
}
// event listeners for change of every dropdown list
const lists = document.querySelectorAll("select");
for (k = 0; k < lists.length; k++) {
lists[k].addEventListener("change", calculateNewValues, false);
}
<p>
<select name="list1" id="list1">
<option value="1" id="list1option1" selected>1</option>
<option value="2" id="list1option2">2</option>
<option value="3" id="list1option3">3</option>
</select>
</p>
<p>
<select name="list2" id="list2">
<option value="1" id="list2option1">1</option>
<option value="2" id="list2option2" selected>2</option>
<option value="3" id="list2option3">3</option>
</select>
</p>
<p>
<select name="list3" id="list3">
<option value="1" id="list3option1">1</option>
<option value="2" id="list3option2">2</option>
<option value="3" id="list3option3" selected>3</option>
</select>
</p>
i am probably doing some mistake when it comes to if (changes.length > 0) {
but i can't understand how i can make this part better.
Thanks a lot in advance.
You have assigned startPoint to querySelectorAll. Which will hold exact same objects whenever you write same querySelectorAll. So in your case startPoint and updatedValues will always same.
I have definen startPoint as an array of values and set its values in setStartingPointValues().
Added target as current list which is being updated.
Updated if (target.id == updatedValues[i].id && updatedValues[i].value != startPoint[i]) and retrieved target's old value.
var key = startPoint.findIndex(x => x == target.value); will find select with value similar to new value. If we found key != -1, then update that select with oldValue.
Call setStartingPointValues() at end of change event.
// defining initial values
var startPoint = [];
// store values for all select.
function setStartingPointValues() {
startPoint = [];
document.querySelectorAll("select").forEach(x => startPoint.push(x.value));
}
setStartingPointValues();
// function to recalculate value of each list on change
function calculateNewValues() {
let target = this;
let oldValue = 0;
// getting updated values from lists as an array
var updatedValues = document.querySelectorAll("select");
// looping through array
for (let i = 0; i < updatedValues.length; i++) {
// if in updated array value of current index isn't equal to value
// of index in initial array
if (target.id == updatedValues[i].id && updatedValues[i].value != startPoint[i]) {
// creating variable changes for tracking
// changes[i] = updatedValues[i].value;
oldValue = startPoint[i];
}
// if var changes has been defined (i.e. value of any list was updated)
// finding index of initial array with same value
var key = startPoint.findIndex(x => x == target.value);
// setting value of found index to previously stored value in updated list
if (key !== -1)
updatedValues[key].value = oldValue;
}
setStartingPointValues();
}
// event listeners for change of every dropdown list
const lists = document.querySelectorAll("select");
for (k = 0; k < lists.length; k++) {
lists[k].addEventListener("change", calculateNewValues, false);
}
<p>
<select name="list1" id="list1">
<option value="1" id="list1option1" selected>1</option>
<option value="2" id="list1option2">2</option>
<option value="3" id="list1option3">3</option>
</select>
</p>
<p>
<select name="list2" id="list2">
<option value="1" id="list2option1">1</option>
<option value="2" id="list2option2" selected>2</option>
<option value="3" id="list2option3">3</option>
</select>
</p>
<p>
<select name="list3" id="list3">
<option value="1" id="list3option1">1</option>
<option value="2" id="list3option2">2</option>
<option value="3" id="list3option3" selected>3</option>
</select>
</p>
Define good structure (store selected value somewhere) and rest should be easy
const lists = Array.from(document.querySelectorAll("#list")).map(element => {
const options = Array.from(element.children);
const selected = options.findIndex(child => child.selected) + 1;
return {
element,
options,
selected
}
});
const calculateNewValues = ({target}) => {
const value = Number(target.value);
const currentList = lists.find(pr => pr.element === target);
const list = lists.find(pr => pr.selected === value)
const oldValue = currentList.selected;
currentList.selected = value;
list.options[value - 1].selected = false;
list.options[oldValue - 1].selected = true;
list.selected = oldValue;
}
for(let {element} of lists) {
element.addEventListener("change", calculateNewValues, false);
}
<p>
<select name="list1" id="list">
<option value="1" selected>1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</p>
<p>
<select name="list2" id="list">
<option value="1">1</option>
<option value="2" selected>2</option>
<option value="3">3</option>
</select>
</p>
<p>
<select name="list3" id="list">
<option value="1">1</option>
<option value="2">2</option>
<option value="3" selected>3</option>
</select>
</p>

Change option values of select 2 if select 1 has a value with jquery

I require a bit of jQuery to do the following:
A user can currently select Program and/or a region.
If a user selects Program AND a Region I require the option values of the region dropdown to change to "?region=1" and "?region=2"
<select class="program" id="program">
<option value="program1.html">Program 1</option>
<option value="program2.html">Program 2</option>
</select>
<select class="region" id="region">
<option value="region1.html">Region 1</option>
<option value="region2.html">Region2</option>
</select>
Greatly appreciate the assist.
My attempt at JQuery:
$('#program').on('change', function () { if($(this).val() !="0") { } else { // no option is selected } })
You need to further extend the change event for #program and include a similar one for #region.
var programSelected = null;
var regionSelected = null;
$('#program').on('change', function(element) {
programSelected = $('#program option:selected').text();
updateRegionOptions();
});
$('#region').on('change', function(element) {
regionSelected = $('#region option:selected').text();
updateRegionOptions();
});
function updateRegionOptions() {
if(programSelected != null && regionSelected != null) {
$('#region option').each(function() {
var modifiedString = '?';
modifiedString += $(this).val().replace(/\d+/,'');
modifiedString = modifiedString.replace('.html','');
modifiedString += '=';
modifiedString += $(this).val().match(/\d+/);
$(this).val(modifiedString);
});
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="program" id="program">
<option value="" selected disabled>Select Program</option>
<option value="program1.html">Program 1</option>
<option value="program2.html">Program 2</option>
</select>
<select class="region" id="region">
<option value="" selected disabled>Select Region</option>
<option value="region1.html">Region 1</option>
<option value="region2.html">Region2</option>
</select>
Explanation of the logic above:
on('change' event for both #region and #program
Set the relevant variable programSelected or regionSelected depending on the change event
Run function updateRegionOptions();
If the variables programSelected and regionSelected both have a value
For each of the options in #region
Mutate the existing value to be of the form "?region=1" and "?region=2"
Update the value section of each of the option elements to have this value
The relevant JSFiddle for review.
If this solved your issue, please accept this answer :)

Multiple values of <option>

I would like to put multiple values in tag within select, so I could adress precisely one or few items.
Example:
<select id="select1">
<option value="pf, nn">NN</option>
<option value="pf, x2, jj">JJ</option>
<option value="pf, uu">UU</option>
<option value="pf, x2, oo">OO</option>
<option value="tt">TT</option>
<option value="rr">RR</option>
</select>
In my js I got that one function that depend on one value that is common for many items:
if (document.getElementById("select1").value = "pf";) {
// do something;
}
if (document.getElementById("select1").value = "x2";) {
// do some-other-thing;
}
But I don't want to use (cos' and with more options gonna get messy)
var sel1 = document.getElementById("select1").value
if (sel1="nn" || sel1="jj" || sel1="uu" || sel1="oo") {
// do something;
}
if (sel1="jj" || sel1="oo") {
// do some-other-thing;
}
Neverthelesst I need to be able to set item by precise one value
if (document.somethingelse = true) {
document.getElementById("select1").value = "oo";)
}
Is there a nice way to achieve this? Maybe use some other "value-like" attribute of option (but which?)?
Only JS.
I think you can do what you want with selectedOpt.value.split(",").includes("sth") code:
$(document).ready(function(e){
selectedChange($("#select1")[0])
});
function selectedChange(val) {
var selectedOpt = val.options[val.selectedIndex];
var status1 = selectedOpt.value.split(",").includes("x2");
var status2 = selectedOpt.value.split(",").includes("pf");
console.log(status1);
console.log(status2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="select1" onchange="selectedChange(this)">
<option value="pf,nn">NN</option>
<option value="pf,x2,jj">JJ</option>
<option value="pf,uu">UU</option>
<option value="pf,x2,oo">OO</option>
<option value="tt">TT</option>
<option value="rr">RR</option>
</select>

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>

Categories