Adding a class to elements depending on their length - javascript

I'm trying to loop through elements and check their length, then add a class if parents have more than 2 elements.
Now the class is been added to all parent elements.
My code is like this:
let CheckOptions = [...document.querySelectorAll(".value select option")]
let checkSelects = [...document.querySelectorAll(".value select")]
checkSelects.forEach(checkSelect => {
if(CheckOptions.length >= 2){
CheckOptions.forEach(checkSelects => checkSelect.classList.add("active"));
}
})
.active {
background-color: red;
<div class="value">
<select class="select">
<option class="option">1</option>
<option class="option">2</option>
<option class="option">3</option>
<option class="option">4</option>
</select>
</div>
<div class="value">
<select class="select">
<option class="option">1</option>
<option class="option">2</option>
</select>
</div>
<div class="value">
<select class="select">
<option class="option">1</option>
<option class="option">2</option>
<option class="option">3</option>
<option class="option">4</option>
</select>
</div>
What I'm doing wrong here?

We can access a select's options by the options select property so we check the length of that property's value is greater than 2, if so, we add the class active to the current select.
Try the following .js code:
let checkSelects = [...document.querySelectorAll(".value select")]
checkSelects.forEach(checkSelect => {
const options = checkSelect.options
if (options.length > 2) {
checkSelect.classList.add("active")
}
})
Also, in order to get the length, instead of getting the options property of the checkSelect, you can just get the length by checkSelect.length property.
So it would be:
let checkSelects = [...document.querySelectorAll(".value select")]
checkSelects.forEach(checkSelect => {
if (checkSelect.length > 2) {
checkSelect.classList.add("active")
}
})

Related

How to refresh a select list in html

I have a drop-down list where depending on the selected value, the next drop-down list shows specific values. when changing the value of the first list and then going back to the old value, the second list does not update. keeps the same value selected before. How can I make the second list update to the value I marked as selected by default whenever I change the value of the first list?
I hope you guys were able to understand me, and I thank you for your time.
Here's the code:
<select onchange="showprd('hidevalue', this), showprd2('hidevalue2', this)">
<option value="" disabled selected hidden>Selecione</option>
<option value="0">São Francisco</option>
<option value="1">Bradesco</option>
</select>
<br>
<br>
<select hidden id="hidevalue">
<option value="" disabled selected hidden>Selecione o produto</option>
<option value="pleno">Pleno</option>
<option value="integrado">Integrado</option>
</select>
<select hidden id="hidevalue2">
<option value="" disabled selected hidden>Selecione o produto</option>
<option value="junior">Junior</option>
<option value="senior">Senior</option>
</select>
</body>
<script>
function showprd(id, elementValue) {
document.getElementById(id).style.display = elementValue.value == 0 ? 'block' : 'none';
}
function showprd2(id, elementValue) {
document.getElementById(id).style.display = elementValue.value == 1 ? 'block' : 'none';
}
</script>
TL;DR. Control the input value changes in one place.
Please see the updated snippet below. html structure hasn't been changed, but I've removed the inline js call and updated the id names. JavaScript blocks are commented in details.
In a nut-shell, this code listens for any change to the parent select dropdown. Whenever a change occurs, its child dropdowns will reset their values and toggle their visibility accordingly.
// Assign each dom element to a variable
const primarySelect = document.querySelector('#primary');
const childSelect1 = document.querySelector('#child1');
const childSelect2 = document.querySelector('#child2');
const defaultValues = document.querySelectorAll('.default');
function resetInputs() {
// Reset the child select options to default
defaultValues.forEach(option => option.selected = true);
}
function handlePrimary(e) {
// Reset the child select values whenever the parent value changes
resetInputs();
// `input` value is always a string. Here we're converting it to a number
const val = parseFloat(e.target.value);
// Toggle visibility of child select dropdowns
[childSelect1, childSelect2].
forEach((select, i) => select.style.display = val === i ? 'block' : 'none');
}
primarySelect.addEventListener('change', handlePrimary);
<select id="primary">
<option value="" disabled selected hidden>Selecione</option>
<option value="0">São Francisco</option>
<option value="1">Bradesco</option>
</select>
<br>
<br>
<select hidden id="child1">
<option class="default" value="" disabled selected hidden>Selecione o produto</option>
<option value="pleno">Pleno</option>
<option value="integrado">Integrado</option>
</select>
<select hidden id="child2">
<option class="default" value="" disabled selected hidden>Selecione o produto</option>
<option value="junior">Junior</option>
<option value="senior">Senior</option>
</select>
If I understood correctly, the expected behavior is when the second or third <select> is hidden, the <select> should go back to default (the first <option>?). If so, then remove disabled and hidden from the first <option> of the second and third <select> then add the following:
selectObj.hidden = true;
selectObj.selectedIndex = 0;
The example below has a <form> wrapped around everything (always use a form if you have more than one form control. By using HTMLFormElement interface I rewrote the code and can reference all form controls with very little code. Inline event handlers are garbage so don't do this:
<select id='sel' onchange="lame(this)">
Instead do this:
selObj.onchange = good;
OR
selObj.addEventListener('change', better)
Read about events and event delegation
const UI = document.forms.UI;
UI.onchange = showSelect;
function showSelect(e) {
const sel = e.target;
const IO = this.elements;
if (sel.id === "A") {
if (sel.value === '0') {
IO.B.hidden = false;
IO.C.hidden = true;
IO.C.selectedIndex = 0;
} else {
IO.B.hidden = true;
IO.B.selectedIndex = 0;
IO.C.hidden = false;
}
}
}
<form id='UI'>
<select id='A'>
<option disabled selected hidden>Pick</option>
<option value="0">0</option>
<option value="1">1</option>
</select>
<br>
<br>
<select id="B" hidden>
<option selected>Pick B</option>
<option value="0">0</option>
<option value="1">1</option>
</select>
<select id="C" hidden>
<option selected>Pick C</option>
<option value="0">0</option>
<option value="1">1</option>
</select>
</form>
I give you an example for your reference:
let secondList = [
[{
value: "pleno",
text: "Pleno"
},
{
value: "integrado",
text: "Integrado"
}
],
[
{
value: "junior",
text: "Junior"
},
{
value: "senior",
text: "Senior"
}
]
]
function update(v){
let secondSelectBox=document.getElementById("second");
secondSelectBox.style.display="none";
let optionList=secondList[v.value];
if (optionList){
let defaultOption=new Option("Selecione o produto","");
secondSelectBox.innerHTML="";
secondSelectBox.options.add(defaultOption);
optionList.forEach(o=>{
let vv=new Option(o.text,o.value);
secondSelectBox.options.add(vv);
})
secondSelectBox.style.display="block";
}
}
<select onchange="update(this)">
<option value="" disabled selected hidden>Selecione</option>
<option value="0">São Francisco</option>
<option value="1">Bradesco</option>
</select>
<select hidden id="second">
</select>

Adjust the width of dropdown according to the length of the text

I have a dropdown option. Here's my code -
<span class="header"> COMPARE </span>
<span class="dropdown">
<select class="select_box" id="opts">
<p></p>
<option value="default">Select a dataset</option>
<option value="population">POPULATION</option>
<option value="popdensityperacre">POPULATION DENSITY</option>
<option value="percapitaincome">INCOME</option>
<option value="percentnonwhite">RACIAL DIVERSITY</option>
<option value="percentinpoverty">POVERTY</option>
<option value="medianhomevalue">HOME VALUE</option>
<option value="unemploymentrate">UNEMPLOYMENT</option>
<option value="percapitacriminalarrests">CRIME</option>
<option value="percapitaencampments">HOMELESSNESS</option>
<option value="medianhoursofsummerfog">FOG</option>
<option value="percentinliquefaction">LIQUEFACTION</option>
</select>
</span>
<span class="header"> BY NEIGHBORHOOD </span>
Right now, the width of the dropdown box is set to the width of the largest item (population density). How can I make it so the width of the dropdown dynamically adjusts for each option? Specifically, when the dropdown is static and not selected.
First of all span - an inline element so you better use divs. It is a bad practice to put block or inline-block elements inside inline elements.
As mentioned above, it is much better to use some library for that.
Then you can use such script. Width of options calculated on initial select width and width of widest option.
findMaxLengthOpt is looking for an option with a longest text content. There is using a spread operator, that transform HTMLCollection of elements to array, so we can use Array methods such as reduce. This operator gets elements out of iterable object and put them into a new array.
Read this docs and this tutorial.
let selectList = document.querySelector("#opts")
// get initial width of select element.
// we have to remember there is a dropdown arrow make it a little wider
let initialWidth = selectList.offsetWidth
// get text content length (not a value length) of widest option.
let maxOptValLen = findMaxLengthOpt(selectList)
// calc width of single letter
let letterWidth = initialWidth / maxOptValLen
let corCoef = 1.875; // Based on visual appearance
console.log(initialWidth, maxOptValLen)
selectList.addEventListener("change", e => {
let newOptValLen = getSelected(e.target).textContent.length
let correction = (maxOptValLen - newOptValLen) * corCoef
let newValueWidth = (newOptValLen * letterWidth) + correction
console.log('new width', newValueWidth, 'new option len', newOptValLen)
e.target.style.width = newValueWidth + "px"
}, false);
function getSelected(selectEl) {
return [...selectEl.options].find(o => o.selected)
}
function findMaxLengthOpt(selectEl) {
return [...selectEl.options].reduce((result, o) => o.textContent.length > result ? o.textContent.length : result, 0)
}
<div class="header">
<p>COMPARE
<select class="select_box" id="opts">
<option value="">Select a dataset</option>
<option value="population">POPULATION</option>
<option value="popdensityperacre">POPULATION DENSITY</option>
<option value="percapitaincome">INCOME</option>
<option value="percentnonwhite">RACIAL DIVERSITY</option>
<option value="percentinpoverty">POVERTY</option>
<option value="medianhomevalue">HOME VALUE</option>
<option value="unemploymentrate">UNEMPLOYMENT</option>
<option value="percapitacriminalarrests">CRIME</option>
<option value="percapitaencampments">HOMELESSNESS</option>
<option value="medianhoursofsummerfog">FOG</option>
<option value="percentinliquefaction">LIQUEFACTION</option>
</select>
BY NEIGHBORHOOD </p>
</div>

How to handle with same id in different onChange function?

handleselectenquiryId(e) {
let attribute = document.getElementById(e.target.value);
let sectorattrribute = attribute.getAttribute("data-items");
this.setState({ enquiryId: e.target.value }, ()=>{
let data = {
id : sectorattrribute
}
UserAction._getSingleEnquiry(data);
});
}
handleselectBookingId(e) {
let attribute = document.getElementById(e.target.value);
let sectorattrribute = attribute.getAttribute("data-item");
console.log(sectorattrribute);
this.setState({ bookingId: e.target.value }, ()=>{
let data = {
id : sectorattrribute
}
UserAction._getSingleBooking(data);
});
}
<div className="col-sm-4 col-6">
<h2 className="card-inside-title">Enquiry Id</h2>
<select className="c-select form-control box_ip" onChange={this.handleselectenquiryId.bind(this)} value={this.state.enquiryId}>
<option value='-1' disabled>Select Enquiry</option>
{this.state.enquirieslist.enquiries.map((el) => <option id={el.enquiryId} data-items={el.id} value={el.enquiryId}>{el.enquiryId}</option>)}
</select>
</div>
<div className="col-sm-4 col-6">
<h2 className="card-inside-title">Booking Id</h2>
<select className="c-select form-control box_ip" onChange={this.handleselectBookingId.bind(this)} value={this.state.bookingId}>
<option value='-1' disabled>Select Booking</option>
{this.state.bookinglist.bookings.map((el) => <option id={el.bookingId} data-item={el.id} value={el.bookingId}>{el.bookingId}</option>)}
</select>
</div>
I am having two dropdowns which has values 1 and 2 in both select tags.
data-items and data-item attribute i am maintaining in both respectively as both el.id is unique when onChange of handleselectBookingId it is taking the id of handleselectenquiryId onchange,
May I know what was the error i was doing.
As i was handling document.getElementById is this the proper way to work or any way to resolve this.
It's not good to use document.getElementById(e.target.value) in react as it has ref for acessing DOM nodes.
you can use ref in your case like this:
first, assign a ref to your options:
<select className="c-select form-control box_ip" onChange=
{this.handleselectenquiryId.bind(this)} value={this.state.enquiryId}>
<option value='-1' disabled>Select Enquiry</option>
{this.state.enquirieslist.enquiries.map((el) => <option ref={val => this[el.enquiryId] = val} data-items={el.id} value={el.enquiryId}>{el.enquiryId}</option>)}
</select>
then access to their data-items attribute value like this in your onChange handler:
this[e.target.value].attributes['data-items'].value)

javascript to dynamically change the dropdown

Attached the screenshot of my web page.
In that picture, under Regression type dropdown list box, there are three values consider 1, 2 and 3
So if I select 1 or 2, drop down below that "F1" should not appear. If value3, then it should appear.
To do this I have added onload under body tag.
HTML CODE:
<div class = "cl-regr" id="div-regr">
<select name = "regr" id="drop-regr">
<option selected="selected" disabled>-----Select-----</option>
<option value = "1"> ips </option>
<option value = "2"> ips sanity </option>
<option value = "3"> Features </option>
</select>
</div>
<div class = "cl-ftr" id="div-ftr" onchange="displayFeatureList()">
<select name = "ftr" class = "cl2" id="drop-ftr">
<option value = "f1"> F1 </option>
<option value = "f2"> F2 </option>
<option value = "f3"> F3 </option>
<option value = "f4"> F4 </option>
</select>
</div>
RESPECTIVE SCRIPT IN SEPARATE .js FILE:
function func1(){
$(".cl-ftr").each(function() {
var that = $(this);
that.find("div.cl2").style.visibility="hidden";
});
};
function displayFeatureList(){
var d_obj = document.getElementById("drop_reg").value;
var op = d_obj.options[d_obj.selectedIndex].value;
if (op == 3){
document.getElementById("drop_ftr").style.visibility = 'visible';
}
else{
document.getElementById("drop_ftr").style.visibility = 'hidden';
}
};
where I'm calling func1 from body tag
<body onload="func1()">
Problems I'm facing are,
1)Whenever the page loads, the "F1" dropdown list box of first row is hiding (ie, ClientIP - 10.213.174.90)
2) If I change the value, displayFeatureList function is not making any effects.
Any help would be much appreciated!!
you are syntax was wrong
$(this) is jquery object style.visiblity its dom function
Use with css() jquery function .style.visiblity is not a jquery object.
For better my suggestion use css .cl2{visiblity:hidden} instead of js
cl2 class in select element not with div so remove the div with cl2 in selector like find('cl2')
fix the id name typo - instead of _
Add change event with first select
Get the value from dropdown direct call the selectelement.value.no need specify index
function func1() {
$(".cl-ftr").each(function() {
var that = $(this);
that.find(".cl2").css('visibility', "hidden");
});
};
function displayFeatureList() {
var d_obj = document.getElementById("drop-regr").value
if (d_obj == '3') {
document.getElementById("drop-ftr").style.visibility = 'visible';
} else {
document.getElementById("drop-ftr").style.visibility = 'hidden';
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body onload="func1()">
<div class="cl-regr" id="div-regr">
<select name="regr" id="drop-regr" onchange="displayFeatureList()">
<option selected="selected" disabled>-----Select-----</option>
<option value = "1"> ips </option>
<option value = "2"> ips sanity </option>
<option value = "3"> Features </option>
</select>
</div>
<div class="cl-ftr" id="div-ftr" >
<select name="ftr" class="cl2" id="drop-ftr">
<option value = "f1"> F1 </option>
<option value = "f2"> F2 </option>
<option value = "f3"> F3 </option>
<option value = "f4"> F4 </option>
</select>
</div>
With all respect, your code quality is not very good.
It's filled with typos (changing _ to -, missing single letters for ids etc.) This way, nothing will ever work. Take more care.
An id has to be unique. If an id appears twice in the same HTML document,
the document is not valid by definition. (It still loads though, but you have to expect errors.) You maybe want to keep the ids an add a dynamic number (row number)to keep them unique
If you use jQuery, use it by default. Don't mix up jQuery(func1()) and JS DOM methods(displayFeatureList)
I reduced your code to the following (I commented the whole JS code for better understanding):
$(document).ready(function() { //run when page loading is complete
$(".regessionTypeCell").each(function() { //for each regessionTypeCell class (parent div, might be a table cell in your case)
$(this).find(".drop-regr").change(function(event) { //set onChange function for the containing drop-regr class
var conditionalDropdown = $(this).find(".cl-ftr"); //get the conditional dropdown element
if ($(this).find(".drop-regr").val() == 3) { //if selected index is equal 3
conditionalDropdown.show(); //show dropdown
} else {
conditionalDropdown.hide(); //hide dropdown
}
}.bind($(this))); //bind this to the inner function
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="regessionTypeCell">
<div class="cl-regr">
<select name="regr" class="drop-regr">
<option selected="selected" disabled>-----Select-----</option>
<option value="1"> ips </option>
<option value="2"> ips sanity </option>
<option value="3"> Features </option>
</select>
</div>
<div class="cl-ftr" style="display:none">
<select name="ftr" class="drop-ftr">
<option value="f1"> F1 </option>
<option value="f2"> F2 </option>
<option value="f3"> F3 </option>
<option value="f4"> F4 </option>
</select>
</div>
</div>
<div class="regessionTypeCell">
<div class="cl-regr">
<select name="regr" class="drop-regr">
<option selected="selected" disabled>-----Select-----</option>
<option value="1"> ips </option>
<option value="2"> ips sanity </option>
<option value="3"> Features </option>
</select>
</div>
<div class="cl-ftr" style="display:none">
<select name="ftr" class="drop-ftr">
<option value="f1"> F1 </option>
<option value="f2"> F2 </option>
<option value="f3"> F3 </option>
<option value="f4"> F4 </option>
</select>
</div>
</div>

JavaScript - Dropdown value dependent

I have two dropdown right now. I want to when the user selects "NO" the other automatically selects "YES" and vice versa.
I'm assuming I use JS here to make this occur, but not sure where to start. Below is my dropdown html code. If someone could help me get started, it would be helpful.
Code:
<div class="cmicrophone" id="cmicrophone">Currently:
<select id="cmicrophone" name="cmicrophone">
<option value=" " selected = "selected"> </option>
<option value="on">ON</option>
<option value="off">OFF</option>
</select>
</div>
<div class="microphone" id="microphone">Microphone:
<select id="microphone" name = "microphone">
<option value=" " selected="selected"> </option>
<option value="on" >ON</option>
<option value="off">OFF</option>
</select>
</div
You can assign a same class to each select element and bind change event listener.
$('.elem').on('change', function() {
if ($(this).val() == 'on') {
$('.elem').not(this).val('off');
} else {
$('.elem').not(this).val('on');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="cmicrophone" id="cmicrophone">Currently:
<select id="cmicrophone" class='elem' name="cmicrophone">
<option value="" selected = "selected"></option>
<option value="on">ON</option>
<option value="off">OFF</option>
</select>
</div>
<div class="microphone" id="microphone">Microphone:
<select id="microphone" class='elem' name="microphone">
<option value="" selected = "selected"></option>
<option value="on">ON</option>
<option value="off">OFF</option>
</select>
</div>
A good starting point might be listening for changes on one select, and when the change happens, selecting the other <select> and setting the right value
Here's a vanilla JS solution (no jquery required).
The idea here is to:
select both <select> elements and save them into variables to refer to later using document.querySelector
add input event listeners on both elements that call a function to handle the event
then use inside the function selectElement.selectedIndex to check the selected index of one element and use that to set the value of the other.
// select the `<select>` elements
const cmicrophone = document.querySelector('#cmicrophone');
const microphone = document.querySelector('#microphone');
// define function to handler the events
function inputHandler(thisSelect, otherSelect) {
if (thisSelect.selectedIndex == 1) {
otherSelect.selectedIndex = 2;
} else if (thisSelect.selectedIndex == 2) {
otherSelect.selectedIndex = 1;
} else {
thisSelect.selectedIndex = 0;
otherSelect.selectedIndex = 0;
}
}
// add event listeners that will 'fire' when the input of the <select> changes
cmicrophone.addEventListener('input', event => {
inputHandler(cmicrophone, microphone);
});
microphone.addEventListener('input', event => {
inputHandler(microphone, cmicrophone);
});
<div>Currently:
<select id="cmicrophone" name="cmicrophone">
<option value=" " selected = "selected"> </option>
<option value="on">ON</option>
<option value="off">OFF</option>
</select>
</div>
<div>Microphone:
<select id="microphone" name="microphone">
<option value=" " selected="selected"> </option>
<option value="on" >ON</option>
<option value="off">OFF</option>
</select>
</div>
One more thing to add: You assigned the same value to multiple ids. You should only assign one unique id per element.

Categories