I'm trying to show/hide the cart button depending on 2 separate select field values.
My logic is this:
Display the cart button if selectId #pa_custom-engraving = 'no' OR if selectId #pa-color != 'custom-print'. Otherwise I want to hide the cart.
This is what I have so far which works unless you continue to toggle the select fields they cancel each other out. How can I combine this into proper 'OR' conditional statement?
JS
document.getElementById('pa_custom-engraving').addEventListener('change', function () {
var style = this.value == 'no' ? 'block' : 'none';
document.getElementsByClassName('woocommerce-variation-add-to-cart')[0].style.display = style;
});
document.getElementById('pa_color').addEventListener('change', function () {
var pstyle = this.value !== 'custom-print' ? 'block' : 'none';
document.getElementsByClassName('woocommerce-variation-add-to-cart')[0].style.display = pstyle;
});
HTML
<select id="pa_custom-engraving">
<option value="">Choose an option</option>
<option value="no">No</option>
<option value="yes">Yes</option>
</select>
<select id="pa_color">
<option value="">Choose an option</option>
<option value="black">Black</option>
<option value="white">White</option>
<option value="custom-print">Custom Print</option>
</select>
Add the same listener to both selects. On change, look at both select values, and apply the conditions separated by ||:
const cartButton = document.querySelector('.woocommerce-variation-add-to-cart');
const selects = ['#pa_custom-engraving', '#pa_color'].map(c => document.querySelector(c));
for (const select of selects) {
select.addEventListener('change', () => {
const displayStyle= selects[0].value === 'no' || selects[1].value !== 'custom-print'
? 'block'
: 'none';
cartButton.style.display = displayStyle;
});
}
You can take the all selected value in an array and check if the array includes/not include the value you want to match:
var sel = Array.from(document.querySelectorAll('#pa_custom-engraving, #pa_color'));
sel.forEach(function(el){
el.addEventListener('change', function () {
var val = sel.map(i => i.value);
var style = val.includes('no') || !val.includes('custom-print') ? 'block' : 'none';
document.getElementsByClassName('woocommerce-variation-add-to-cart')[0].style.display = style;
});
});
<select id="pa_custom-engraving">
<option value="">Choose an option</option>
<option value="no">No</option>
<option value="yes">Yes</option>
</select>
<select id="pa_color">
<option value="">Choose an option</option>
<option value="black">Black</option>
<option value="white">White</option>
<option value="custom-print">Custom Print</option>
</select>
<button class="woocommerce-variation-add-to-cart">woocommerce-variation-add-to-cart</button>
Related
I have 2 picklists with the same values. In the 1st picklist, it has more values than the 2nd picklist. So when the user selects some value from the 2nd picklist, it is showing the same value in the 1st one.
But I would like to show if the value Testing 1 is selected in picklist 1 then the same value should show in the 2nd picklist. If the user selects Testing 2 from the 1st picklist then the 2nd picklist should also show the same value.
Not sure how to achieve this. Could someone help me with this?
var sMap = {};
sMap["ABC"] = ["Test2ABC", "Style"];
sMap["CDE"] = ["Test2CDE", "style"];
sMap["EFG"] = ["Test2EFG", "style"];
function onChangeRadio(ele) {
var id = $(ele).attr("id");
var type = $(ele).attr("type");
var tagName = $(ele).prop("tagName");
if (tagName.toLowerCase() == "select") {
var val = $(ele).val();
$('#codes').append($("<option value='" + val + "'>" + val + "</option>"));
setsc(val);
} else {
var Code = Object.keys(sMap).find(key => sMap[key].includes(id));
setsc(Code);
}
}
function setsc(val) {
$('[name="Code"]').val(val);
window.dispatchEvent(new Event('resize'));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<td id="TD1">
<input type="hidden" name="Test1" id="hidden-test1" value="">
<input list="codes" name="Code" id="slist" class="Mandatory">
<datalist id="codes">
<option value="">-- Choose one --</option>
<option value="ABC">Testing 1</option>
<option value="CDE">Testing 2</option>
<option value="EFG">Testing 3</option>
<option value="ABC">worker</option>
<option value="NAP">Port</option>
</datalist>
</td>
<select name="T-Test2" id="Test2" onchange="onChangeRadio(this)">
<option value="" selected="">Choose one</option>
<option value="ABC">Testing 1</option>
<option value="CDE">Testing 2</option>
<option value="EFG">Testing 3</option>
</select>
You need to detect the onchange event on the datalist. You do that by checking the input event on the <input>.
You can use the inputType on the InputEvent to filter out any unwanted onInput events. This is "insertReplacementText" on Firefox 81 and null for Chrome/Edge 86. If you need to support IE11 you will need to validate the value is valid.
$("#slist").on("input", (event) => {
// Detect change on the datalist
if (event.inputType == "insertReplacementText" || event.inputType == null) {
console.log(event.target.value);
})
Other explains areinside the below code.
var sMap = {};
sMap["ABC"] = ["Test2ABC", "Style"];
sMap["CDE"] = ["Test2CDE", "style"];
sMap["EFG"] = ["Test2EFG", "style"];
function onChangeRadio(ele) {
var id = $(ele).attr("id");
var type = $(ele).attr("type");
var tagName = $(ele).prop("tagName");
if (tagName.toLowerCase() == "select") {
var val = $(ele).val();
$('#codes').append($("<option value='" + val + "'>" + val + "</option>"));
setsc(val);
} else {
var Code = Object.keys(sMap).find(key => sMap[key].includes(id));
setsc(Code);
}
}
function setsc(val) {
$('[name="Code"]').val(val);
window.dispatchEvent(new Event('resize'));
}
$("#slist").on("input", (event) => {
// Detect change on the datalist
if (event.inputType == "insertReplacementText" || event.inputType == null) {
let selectedValue = event.target.value;
if (!selectedValue) return;
// Get the text of the option associate with the value
let optionData = $(`#codes > option[value="${selectedValue}"]`).text();
console.log(optionData);
// Append in the <select>
// if the otpion is not existed, use a temporary attribute, so we can clear it out later
let selectedOption = $(`#Test2 > option[value="${selectedValue}"]`)[0];
if (selectedOption) {
// selected option exists, show it
selectedOption.selected = 'selected';
} else {
// selected option doesn't exist, add then show
// Clear the temporary options out of the select
$('#Test2 > [temporary="true"]').remove();
$('#Test2').append($('<option>', {
value: selectedValue,
text: optionData,
selected: true,
temporary: true,
}));
}
}
});
// Whenever you change the value on the select, clear out the temporary options
$('#Test2').on('change', (e) => {
$('#Test2 > [temporary="true"]').remove();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<td id="TD1">
<input type="hidden" name="Test1" id="hidden-test1" value="">
<input list="codes" name="Code" id="slist" class="Mandatory">
<datalist id="codes">
<option value="">-- Choose one --</option>
<option value="ABC">Testing 1</option>
<option value="CDE">Testing 2</option>
<option value="EFG">Testing 3</option>
<option value="HIJ">worker</option>
<option value="NAP">Port</option>
</datalist>
</td>
<select name="T-Test2" id="Test2" onchange="onChangeRadio(this)">
<option value="" selected="">Choose one</option>
<option value="ABC">Testing 1</option>
<option value="CDE">Testing 2</option>
<option value="EFG">Testing 3</option>
</select>
I am trying to sort option alphabetically
My Html is
<select id="myOpt">
<option value="" selected data-default>Select Name</option>
<option value="3">John Snow</option>
<option value="34">Arya Stark</option>
<option value="54">Sansa Stark</option>
<option value="4">Hound</option>
</select>
js
var options = $("#myOpt option");
options.detach().sort(function(a,b) {
var at = $(a).text();
var bt = $(b).text();
return (at > bt)?1:((at < bt)?-1:0);
});
options.appendTo("#myOpt");
it sorts option correctly but now instead of selected option it shows last option. My question is how to show selected option instead of last option and can it be done by another client side method? since for big list it making page slow
Try this,
var options = $("#myOpt option");
var selectedVal = '';
options.detach().sort(function(a,b) {
var at = $(a).text();
var bt = $(b).text();
if($(a).attr('selected') || $(b).attr('selected')){
selectedVal = $(a).attr('selected') ? $(a).val() : $(b).val();
return false;
}
return (at > bt)?1:((at < bt)?-1:0);
});
options.appendTo("#myOpt");
$('#myOpt').val(selectedVal);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="myOpt">
<option value="" selected data-default>Select Name</option>
<option value="3">John Snow</option>
<option value="34">Arya Stark</option>
<option value="54">Sansa Stark</option>
<option value="4">Hound</option>
</select>
Don't select the 1st option to sort. var options = $("#myOpt option:not(:eq(0))");
You may use web workers to avoid browser frize if this a big list.
also, you can put it inside setTimeout to push it in event loop
$(function() {
var options = $("#myOpt option:not(:eq(0))");
options.detach().sort(function(a, b) {
var be = $(b);
var ae = $(a);
if (be.attr('selected')) {
selectedVal = be.val();
return 1;
}
if (ae.attr('selected')) {
selectedVal = ae.val();
return -1;
}
var at = ae.text();
var bt = be.text();
return (at > bt) ? 1 : ((at < bt) ? -1 : 0);
});
options.appendTo("#myOpt");
$("#myOpt").val(selectedVal);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="myOpt">
<option value="" selected data-default>Select Name</option>
<option value="3">John Snow</option>
<option value="34">Arya Stark</option>
<option value="54">Sansa Stark</option>
<option value="4">Hound</option>
</select>
$(function() {
var options = $("#myOpt option");
options.detach().sort(function(a, b) {
var be = $(b);
var ae = $(a);
if (be.attr('selected')) {
selectedVal = be.val();
return 1;
}
if (ae.attr('selected')) {
selectedVal = ae.val();
return -1;
}
var at = ae.text();
var bt = be.text();
return (at > bt) ? 1 : ((at < bt) ? -1 : 0);
});
options.appendTo("#myOpt");
$("#myOpt").val(selectedVal);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="myOpt">
<option value="" selected data-default>Select Name</option>
<option value="3">John Snow</option>
<option value="34">Arya Stark</option>
<option value="54">Sansa Stark</option>
<option value="4">Hound</option>
</select>
To do the sort using native JavaScript may actually give you somewhat more readable code, while taking advantage of operations (like shift/unshift) that jQuery does not implement.
The selection issue is occurring because an option detached from it's parent select cannot be selected - so you need to either select the first option again.
document.addEventListener("DOMContentLoaded", function() {
var options = $("#myOpt option").detach()
options = $.makeArray(options);
var first = options.shift();
options.sort( (a,b) => a.text.localeCompare(b.text) );
options.unshift(first);
$("#myOpt").append(options);
$("#myOpt option").eq(0).prop("selected", true)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="myOpt">
<option value="" selected data-default>Select Name</option>
<option value="3">John Snow</option>
<option value="34">Arya Stark</option>
<option value="54">Sansa Stark</option>
<option value="4">Hound</option>
</select>
You may want to simply just leave the selected element alone and just detach/sort the others, which ends up being quite a bit simpler:
document.addEventListener("DOMContentLoaded", function() {
var options = $("#myOpt option").not('[value=""]').detach();
options.sort( (a,b) => a.text.localeCompare(b.text) );
$("#myOpt").append(options);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="myOpt">
<option value="" selected data-default>Select Name</option>
<option value="3">John Snow</option>
<option value="34">Arya Stark</option>
<option value="54">Sansa Stark</option>
<option value="4">Hound</option>
</select>
I dynamically generate additional forms on a page using Django Model Formsets. The user can generate as many forms as they need. This is done in a Vuejs method.
My issue is changing the options of the second select of the form that the first select value was chosen. I was thinking about trying on focus or on click to get the select that was last changed, but I'm not sure how that would work.
I do track the current count of forms on the page.
In the example below. If the user changed form_select_0 to One, I need form_subselect_0 to only have options C and D, but the selects in form_1 should not be altered.
Example:
<form id = form_0>
<select id="form_select_0">
<option value="one">One</option>
<option value="two">Two</option>
</select>
<select id="form_subselect_0">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="D">D</option>
</select>
</form>
<form id = form_0>
<select id="form_select_1">
<option value="one">One</option>
<option value="two">Two</option>
</select>
<select id="form_subselect_1">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="D">D</option>
</select>
</form>
Follow-up:
Added vue method (below) for how I'm currently adding Vuejs models to the Django Model Formsets. Question: Is there a better way?
addForm: function () {
this.count++
let form_count = this.count
form_count++
let formID = 'id_form-' + this.count
incremented_form = this.vue_form.replace(/form-\d/g, 'form-' + this.count)
this.formList.push(incremented_form)
this.$nextTick(() => {
let total_forms = document.getElementsByName('form-TOTAL_FORMS').forEach
(function (ele, idx) {
ele.value = form_count
})
})
},
As stated above this was my final answer due to no response:
addForm: function () {
this.count++
let form_count = this.count
form_count++
let formID = 'id_form-' + this.count
incremented_form = this.vue_form.replace(/form-\d/g, 'form-' + this.count)
this.formList.push(incremented_form)
this.$nextTick(() => {
let total_forms = document.getElementsByName('form-TOTAL_FORMS').forEach
(function (ele, idx) {
ele.value = form_count
})
})},
I'm trying to get the value of the option which have the attribute "selected" to compare it to the current option selected.
function onChangeOption(opt) {
var update_value = opt.value;
var selectedValue = '???'; // get selected attribute
if (update_value != selectedValue) {
// Do some things
}
}
<select class="form-control" onchange="onChangeOption(this)">
<!-- I wanna got the content of option selected=selected-->
<option selected="selected" value="1">1</option>
<option value="2">2</option>
</select>
// save initial selected value to a variable
var initSelected = $('.form-control option:selected').val();
$('select').on('change', function() {
// check if the selected value is the same as the initial one was
if(this.value == initSelected) {
console.log('same values');
} else {
console.log('not same values');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="form-control">
<option selected="selected" value="1">1</option>
<option value="2">2</option>
</select>
Just add change event listener.And get the selected value.You can achieve comparision between selected value and changed value by maintaining an array.Like below.
values = []//creates an array
select = document.querySelector('#myselect');
values.unshift(select.value);
//console.log(values);
select.addEventListener('change',function(){
update_value = this.value;
console.log(this.value);
if (update_value != values[0]) {
// alert('Not matched');
console.log('Not matched');
}
else{
//alert('Matched');
console.log('Matched')
}
});
<select class="form-control" id="myselect">
<option selected="selected" value="1"> 1 </option>
<option value="2"> 2 </option>
</select>
I think alexis actually wants something more like this:
function onChangeOption(opt) {
var update_value = opt.value;
var options = document.getElementsByTagName("option");
if (options[0].getAttribute("selected")=="selected") {
var selectedValue = options[0].value;
} else {
var selectedValue = options[1].value;
}
if (update_value != selectedValue) {
// If the selected option's value is not equal to the value of the option with the attribute "selected", then do... (this way, you can change the attribute to any of the options!)
console.log(selectedValue);
}
}
<select class="form-control" onchange="onChangeOption(this)">
<option selected="selected" value="1">1</option>
<option value="2">2</option>
</select>
Comment the result and if you need anything else. Glad to help.
You can always store previously selected values, if you want to access them somehow later on: working example.
HTML:
<select id="mySelect" class="form-control" onchange="onChangeOption(this)">
<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>
</select>
<p>Previous: <span id="prev"></span></p>
<p>Current: <span id="curr"></span></p>
JS:
var selectElem = document.getElementById("mySelect");
var prev = document.getElementById("prev");
var curr = document.getElementById("curr");
var allEverSelected = [ selectElem.value ];
selectElem.addEventListener("change", function(evt){
allEverSelected.push( this.value );
prev.innerHTML = allEverSelected[allEverSelected.length - 2];
curr.innerHTML = allEverSelected[allEverSelected.length - 1];
});
To access default value, just get the <select> value after DOM loads.
selected attribute on <option> tag exist only to make other than first <option> element inside <select> default option, i.e.:
<select>
<option value="1">1</option>
<option selected value="2">2</option>
</select>
Above select's default value is 2.
I think this is the one what you want. Try it.
function onChangeOption(opt) {
var update_value = opt.value;
console.log(update_value);
var selectedValue;// = '???'; // get selected attribute
// I think this is the one you want
//If you want to select the HTML element,
selectedValue=document.querySelector("option[value='"+update_value+"']");
console.log(selectedValue);
//
if (update_value != selectedValue) {
// Do some things
}
}
//onChangeOption(document.querySelector('form'));
function start(){
while(typeof document.querySelector('form')!=typeof {}){}
onChangeOption(document.querySelector('.form-control'));
}
<body onload="start()">
<select class="form-control" onchange="onChangeOption(this)">
<option selected="selected" value="1">1</option>
<!-- I wanna got this -->
<option value="2">2</option>
</select></body>
1) I have two drop downs with exactly the same values. I want the drop down 2 to display the values based on the selection of items of drop down 1. So the selected index of drop down 2 will be equal to or more than the selected index of drop down 1. ( this code is working)
but When I add one more drop down and based on its items the other two dropdowns should behave as:
2) If I select TCD in the first Dropdown and change to value B in the second dropdown the value should be B in the third dropdown too but If I select BCD from the first dropdown it should retain the values of other two dropdown from the previous selection.( should not go back to A)
The first part is working but the second part is having issues.
Fiddle : 1) http://jsfiddle.net/wtLm4805/2/
Fiddle with three dropdowns : 2) http://jsfiddle.net/wtLm4805/3/
while (select2.firstChild) {
select2.removeChild(select2.firstChild);
}
for (var i = 0; i < select1.options.length; i++) {
var o = document.createElement("option");
o.value = select1.options[i].value;
o.text = select1.options[i].text;
(i < select1.selectedIndex)
? o.disabled = true
: o.disabled = false ;
select2.appendChild(o);
}
Where am I going wrong ?
You can go somewhere along these lines
var typeValue = 'TCD'; // default initialisation
$('#Type').change(function(){
var value = $(this).val();
console.log(value);
if(value == 'TCD')
{
typeValue = 'TCD';
// change something in other selects too
}
else if(value == 'MCD')
{
typeValue = 'MCD';
}
else if(value == 'BCD')
{
$('#SELECTA').val('B');
$('#SELECTB').val('B');
typeValue = 'BCD';
}
});
$('#SELECTA').change(function(){
var value = $(this).val();
console.log(value);
if(typeValue = 'TCD')
{
$('#SELECTB').val(value);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<select name="Type" id="Type" >
<option value="TCD">TCD</option>
<option value="MCD" >MCD</option>
<option value="BCD" >BCD</option>
</select>
<select id="SELECTA" class="SELECTA">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="D">D</option>
</select>
<select id="SELECTB" class="SELECTB" >
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="D">D</option>
</select>
Since you have only one element with class SELECTA and one with class SELECTB, these will always be undefined:
var select1 = document.getElementsByClassName("SELECTA")[1];
var select2 = document.getElementsByClassName("SELECTB")[1];
var select1 = document.getElementsByClassName("SELECTA")[2];
var select2 = document.getElementsByClassName("SELECTB")[2];
If you're trying to target the options, you could move the classes to the options themselves, or you could reference them like this:
document.getElementsByClassName("SELECTA")[0].options[1]
Not sure why you're deleting/adding items to the SELECTB element, but is this what you're going for?
function clickButton() {
var Type= document.getElementById('Type');
var select1= document.getElementById('SELECTA');
var select2= document.getElementById('SELECTB');
if(Type.value === 'TCD') {
for(var i = 0 ; i < select1.options.length ; i++) {
select2.options[i].disabled= i < select1.selectedIndex;
}
select2.value= select1.value;
}
else {
for(var i = 0 ; i < select2.options.length ; i++) {
select2.options[i].disabled= false;
}
}
}
<select name="Type" id="Type" onchange="clickButton()">
<option value="TCD">TCD</option>
<option value="MCD">MCD</option>
<option value="BCD">BCD</option>
</select>
<select id="SELECTA" onchange="clickButton()">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="D">D</option>
</select>
<select id="SELECTB">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="D">D</option>
</select>