Given a standard select as per below, is is possible by jQuery (or otherwise) to trigger a change event on individual options - As multiple may be selected, I don't want to trigger on the select but on the option?
<select multiple="">
<option>Test 2</option>
<option>Testing 3</option>
</select>
Something like:
$(`option`).trigger(`change`);
One way is to keep a reference of the last state of the multi-select, then compare to find the most recently clicked option.
let sels = [];
$(`select`).on(`change`, function() {
$(this).val().forEach(v => {
if (sels.indexOf(v) === -1) {
console.log(`The option most recently selected is ${v}`);
}
})
sels = $(this).val();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select multiple="">
<option value='2'>Test 2</option>
<option value='3'>Testing 3</option>
</select>
There is no change on an option. If you want it to act like a user is selecting option by option in the select, you would need to select the option and trigger the change event on the select.
const mySelect = document.querySelector("#mySelect");
mySelect.addEventListener("change", function () {
const selected = Array.from(mySelect.querySelectorAll("option:checked")).map(x => x.value);
console.log(selected);
});
function triggerEvent(elem, event){
const evt = document.createEvent("HTMLEvents");
evt.initEvent(event, true, true );
elem.dispatchEvent(evt);
}
const values = ['1','2','4'];
values.forEach(val => {
const opt = mySelect.querySelector(`[value="${val}"]`);
if (opt) {
opt.selected = true;
triggerEvent(mySelect, 'change');
}
});
/*
const values = ['1','2','4'];
const options = mySelect.querySelectorAll("option");
options.forEach(opt => {
const initial = opt.selected;
opt.selected = values.includes(opt.value);
if (opt.selected !== initial) {
triggerEvent(mySelect, 'change');
}
});
*/
<select id="mySelect" multiple>
<option value="1">one</option>
<option value="2">two</option>
<option value="3">three</option>
<option value="4">four</option>
</select>
The real solution is why is your page not set up to handle default values? Seems like you should just be able to call a method with the values and be done. Seems odd to rely on events.
Related
I have a dropdown menu that allows multiple selections. Now I want to make it when one particular option has selected all others to be disabled and enabled for selection. If that one particular is de-selected all others should be enabled again.
This is my select dropdown:
<select class="input-fields selectpicker" id="select_heigh" name="search[]" multiple>
<option value="all" selected>Search all</option>
<option value="tag">Tags</option>
<option value="username">Username</option>
<option value="email">Email</option>
<option value="full_name">Full Name</option>
</select>
And here is what I have tried for the js
$(document).ready(function() {
$('.selectpicker').selectpicker();
$('.selectpicker').on('change', function() {
if ($('option[value="all"]', this).is(':selected') && $(this).val().length > 1) {
$('option[value="all"]', this).prop('selected', false);
$('.selectpicker').selectpicker('refresh');
}
var selected = $(this).val();
if (selected.includes("tag")) {
$('option[value!="tag"]', this).prop('disabled', true);
} else {
$('option[value!="tag"]', this).prop('disabled', false);
}
if (selected.length > 3) {
$(this).selectpicker('setStyle', 'selected-count', 'btn-danger');
$(this).selectpicker('setTitle', selected.length + ' select(s)');
} else {
$(this).selectpicker('setStyle', 'selected-count', 'btn-default');
$(this).selectpicker('setTitle', 'Select');
}
});
});
I want when "Tag" is selected the other options to be disabled. When "Tag" is de-selected the others are enabled. When any other option is selected to no effect on others.
Also, the counting of selected choices doesn't work as expected. It should start showing Selected(3), Selected(4) ... after the third selection. Currently, it shows all of them not count of them.
I'm not that familiar with JS and not sure if I'm on the right path here
What the OP wants to achieve is a rather unexpected behavior of a native form control.
And in case one changes the behavior it should be based on using what form elements or elements in particular do support natively like the disabled- and the dataset-property.
An implementation then could be as simple as querying the correct select element and subscribing an event listener to any click event which occurres on the very select element. The change event can not be used since any further changes are impossible once a single option is selected but all other option are disabled. An option element's dataset gets used as lookup in order to detect whether the very element already has been selected before the current click handling.
function handleOptionClickBehavior({ target }) {
const optionNode = target.closest('option');
const nodeValue = optionNode?.value;
if (nodeValue === 'tag') {
const optionNodeList = [...optionNode.parentNode.children]
.filter(node => node !== optionNode);
const { dataset } = optionNode;
if (dataset.hasOwnProperty('selectedBefore')) {
Reflect.deleteProperty(dataset, 'selectedBefore');
optionNode.selected = false;
optionNodeList
.forEach(node => node.disabled = false);
} else {
dataset.selectedBefore = '';
optionNodeList
.forEach(node => node.disabled = true);
}
}
}
document
.querySelector('.selectpicker')
.addEventListener('click', handleOptionClickBehavior)
body { zoom: 1.2 }
<select class="input-fields selectpicker" id="select_heigh" name="search[]" size="5" multiple>
<option value="all" selected>Search all</option>
<option value="tag">Tags</option>
<option value="username">Username</option>
<option value="email">Email</option>
<option value="full_name">Full Name</option>
</select>
I am trying to make it possible in a "normal" html select element to pick more than one option.
And yes: I know that there's an attribute for the select element called "multiple" which makes this possible by creating a scrollable list with a customizable height.
However, this is not what I'm looking for. I don't want a scrollable list, but rather the drop-down list of a "singular" select to show up when activated and then one should be able to pick multiple option with ctrl button pressed down. Ideally, the drop-down list should disappear when one disengages the ctrl button.
Is there some way of overriding the default eventlistener to make a behaviour like this?
Here's what I've tried so far:
<!DOCTYPE HTML>
<meta charset="UTF-8">
<html>
<head>
</head>
<body>
<select id="varSel" name="varSel">
<option value="1">Variable 1</option>
<option value="2">Variable 2</option>
<option value="3">Variable 3</option>
<option value="4">Variable 4</option>
<option value="5">Variable 5</option>
</select>
<script>
let varSelector = document.getElementById("varSel");
var str = "";
var choices = [];
document.body.addEventListener('keydown', function(event)
{
const key = event.key;
if(key === "Control"){
str = "ctrlDown"
}
});
document.body.addEventListener('keyup', function(event)
{
const key = event.key;
if(key === "Control"){
str = "ctrlUp"
}
});
varSelector.addEventListener("change", function() {
var v = varSel.value;
if(str === "ctrlDown"){
choices.push(v);
console.log(choices);
/* Here I need some code to keep all the previous selected options
marked and prevent the drop-down list from hiding after selecting */
}
else{
choices = [v];
console.log(choices[0]);
}
event.preventDefault();
}, false);
</script>
</body>
</html>
Any help or advice is much appreciated, thanks.
May I suggest a different approach? You can still use the multiple attribute and add event listeners for the focus and blur events, which will modify the size attribute:
const mySelect = document.querySelector('#varSel');
mySelect.addEventListener('focus', () => {
const options = mySelect.querySelectorAll('option');
mySelect.setAttribute('size', options.length);
});
mySelect.addEventListener('blur', () => {
mySelect.setAttribute('size', 1);
})
<select id="varSel" name="varSel" size="1" multiple>
<option value="1">Variable 1</option>
<option value="2">Variable 2</option>
<option value="3">Variable 3</option>
<option value="4">Variable 4</option>
<option value="5">Variable 5</option>
</select>
I am trying to run 2 functions according to the value selected by drop-down box.
Code:
var activities = document.getElementById("stand");
activities.addEventListener("change", function() {
if (activities.options[activities.selectedIndex].value == "stand1") {
var footRight = new THREE.Mesh(new THREE.BoxGeometry(.040, 0.55, 0.05), wallMaterial);
partitionLeft.add(footRight);
footRight.position.set(-0.12, -0.11, 2);
} else {
var footRight = new THREE.Mesh(new THREE.BoxGeometry(.040, 0.55, 0.05), wallMaterial);
partitionLeft.add(footRight);
footRight.position.set(-4.12, -8.9, 6);
}
});
<div id="door-stand">
<label>Select the stand type:</label>
<select id="stand">
<option class="stand1" value="stand1"> Stand 1 </option>
<option class="stand2" value="stand2"> Stand 2 </option>
</select>
</div>
The issue is even-though the values from the drop-down list keep changing, any of the above functions ain't trigger.
I tried to print something when the value changed in drop-down list; but, anything did not print at all.
There is a console error when I change the values in the drop-down. The console error pops up only when changing the values. That's why I haven't noticed. It says
wallMaterial not defined
As you can see, after removing all the unnecessary code, this simple snippet works as expected:
const activities = document.getElementById('stand');
activities.addEventListener('change', (e) => {
console.log(`e.target.value = ${ e.target.value }`);
console.log(`activities.options[activities.selectedIndex].value = ${ activities.options[activities.selectedIndex].value }`);
});
<select id="stand">
<option class="stand1" value="stand1">Stand 1</option>
<option class="stand2" value="stand2">Stand 2</option>
</select>
This means there might be something else wrong in your code:
Maybe something is erroring out:
const activities = document.getElementById('stand');
activities.addEventListener('change', (e) => {
console.log('Change START');
activities.nonexistentFunction();
console.log('Change END');
});
<select id="stand">
<option class="stand1" value="stand1">Stand 1</option>
<option class="stand2" value="stand2">Stand 2</option>
</select>
Maybe you have some other change listeners that are calling Event.stopImmediatePropagation():
const activities = document.getElementById('stand');
activities.addEventListener('change', (e) => {
e.stopImmediatePropagation();
console.log('Change 1');
});
activities.addEventListener('change', (e) => {
console.log('Change 2');
});
<select id="stand">
<option class="stand1" value="stand1">Stand 1</option>
<option class="stand2" value="stand2">Stand 2</option>
</select>
You can use this.value to access the value of selected option inside your callback function:
document.getElementById('stand').onChange = function(){
console.log(this.value);
});
Using jQuery, upon a change/select event, how can I check and see if multiple select boxes contain any selected items? All I am looking for is how to capture and obtain a total count of this?
Based on a validation if not equal to 0, this would set a buttons default disabled attribute to false.
<form id="myform">
Cars
<select id="car">
<option value=""></option>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<br><br>
Fruits
<select id="fruits">
<option value=""></option>
<option value="apple">apple</option>
<option value="banana">banana</option>
<option value="pear">pear</option>
<option value="strawberry">strawberry</option>
<option value="mango">mango</option>
<option value="orange">orange</option>
</select>
</form>
$('#myform select).bind("change select",function() {
});
Assuming your <button> is within the form element, the following should work for you:
// binding the anonymous function of the on() method
// as the event-handler for the 'change' event:
$('#myform').on('change', function() {
// caching the $(this) (the <form>, in this case):
var form = $(this);
// finding the <button> element(s) within the <form>
// (note that a more specific selector would be
// preferable), and updating the 'disabled' property,
// finding all <option> elements that are selected,
// filtering that collection:
form.find('button').prop('disabled', form.find('select option:selected').filter(function() {
// retaining only those whose values have a length
// (in order to not-count the default 'empty'
// <option> elements:
return this.value.length;
// and then checking if that collection is
// equal to 0, to obtain a Boolean true
// disabling the <button>, or a false to
// enable the <button>:
}).length === 0);
// triggering the change event on page-load
// to appropriately enable/disable the <button>:
}).change();
$('#myform').on('change', function() {
var form = $(this);
form.find('button').prop('disabled', form.find('select option:selected').filter(function() {
return this.value.length;
}).length === 0);
}).change();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="myform">
Cars
<select id="car">
<option value=""></option>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<br>
<br>Fruits
<select id="fruits">
<option value=""></option>
<option value="apple">apple</option>
<option value="banana">banana</option>
<option value="pear">pear</option>
<option value="strawberry">strawberry</option>
<option value="mango">mango</option>
<option value="orange">orange</option>
</select>
<button>Submission button</button>
</form>
References:
change().
filter().
find().
on().
prop().
You can use the jQuery :checked selector to capture all elements that are checked. For the count, you can do:
$( "input:checked" ).length;
You can then do your condition to view if there are zero or more elements checked:
var selected = $( "input:checked" ).length;
if(selected > 0)
//do something
$('#myform select').on('change', function() {
var count = 0;
$('#myform').find('select').find('option').each(function(){
if ($(this).is(':selected')){
count++;
}
});
if (count < 0){
$('#mybutton').prop('disabled', false);
} else {
$('#mybutton').prop('disabled', true);
});
Grab all the selects on the page and just loop through them while adding a change event to each one.
Then in that change event, call a method that counts up how many selects have items selected.
https://jsfiddle.net/x833qr20/3/
// put an on change event on all the selects, can be done in onload
var ddl = $('select');
for (i = 0; i < ddl.length; i++) {
ddl[i].onchange = function() {
CountAllSelectedDDL();
}
}
// function that fires when one select gets changed
function CountAllSelectedDDL() {
var ddl = $('select');
var count = 0;
for (i = 0; i < ddl.length; i++) {
if (ddl[i].selectedIndex > 0) {
count++;
}
}
var button = document.getElementById('button');
if (count > 0) {
// set the buttons default disabled attribute to false
button.disabled = false;
} else {
button.disabled = true;
}
}
Hope this helps.
Here's a working example via jQuery
https://jsfiddle.net/wedh87bm/
$('#myform select').bind("change select",function() {
var completed = true;
$('#myform select').each(function(){
if($(this).val() == "")
{
completed = false;
}
});
if(completed)
{
$('#validate').prop("disabled",false);
} else
{
$('#validate').prop("disabled",true);
}
});
I have a select with loads of options. (Code below shortened for sake of example).
I want it to set the value of the input textfield "hoh" to "10" when you click/select all dropdown options, except one, that should set it to 50.
I imagined something like this would work, but its not. What am I doing wrong here?
<select>
<option onselect="document.getElementById('hoh').value = '50'">Hey</option>
<option onselect="document.getElementById('hoh').value = '10'">Ho</option>
<option onselect="document.getElementById('hoh').value = '10'">Lo</option>
....
</select>
<input type="text" id="hoh" value="10">
Something like this should work:
<script>
function myFunc(val) {
if (val == '50') {
document.getElementById('hoh').value = val;
} else {
document.getElementById('hoh').value = '10';
}
}
</script>
<select onchange="myFunc(this.value)">
<option value="1">one</option>
<option value="2">two</option>
<option value="50">fifty</option>
</select>
http://jsfiddle.net/isherwood/LH57d/3
The onselect event refers to selecting (or highlighting) text. To trigger an action when a dropbox selection changes, use the onchange event trigger for the <select> element.
E.g. Since you didn't already set the value attribute of your option tags.
<select id="myselect" onchange="myFunction()">
<option value="50">Hey</option>
<option value="10">Ho</option>
<option value="10">Lo</option>
....
</select>
and somewhere inside of a <script> tag (presumably in your HTML header) you define your javascript function.
<script type="text/javascript>
function myFunction() {
var dropbox = document.getElementById('myselect');
document.getElementById('hoh').value = dropbox[dropbox.selectedIndex].value;
}
</script>
I'm not sure it's wise to repeat the same value among different options in a droplist, but you could expand on this to implement the result other ways, such as if the sole option which will have value 50 is in a certain position, you could compare the selectedIndex to that position.
you could add an onchange event trigger to the select, and use the value of an option to show in the textbox
see http://jsfiddle.net/Icepickle/5g5pg/ here
<select onchange="setValue(this, 'hoh')">
<option>-- select --</option>
<option value="10">Test</option>
<option value="50">Test 2</option>
</select>
<input type="text" id="hoh" />
with function setValue as
function setValue(source, target) {
var tg = document.getElementById(target);
if (!tg) {
alert('No target element found');
return;
}
if (source.selectedIndex <= 0) {
tg.value = '';
return;
}
var opt = source.options[source.selectedIndex];
tg.value = opt.value;
}
Try this code
var inp = document.getElementById('hoh');
sel.onchange = function(){
var v = this.value;
if( v !== '50'){
v = '10';
}
inp.value = v;
};