I have this code trying to create a drop-down search box for the Shopify store Which can find available inks and toner available in store and show the result on the new page!
so right now the drop-down menu not Working Properly ( not going to the next section!)
How can I fix this?
the website is www.DoorStepInk.com
<div class="printer-finder-widget embedded" data-family-label="Select a Printer Family" data-model-label="Select a Printer Model" data-activated="true">
<p class="as-h2">Ink & Toner Finder</p>
<p class="as-h3">Save up to 80% on Printer Supplies</p>
<div class="select-house has-options">
<label for="select_brand" class="fancy-label"><span>Select a <b>Printer Brand</b></span></label>
<select id="select_brand" class="select-brand">
<option value="">Select a Printer Brand</option>
<option value="7">Brother</option>
<option value="9">Canon</option>
<option value="10">Dell</option>
<option value="11">Epson</option>
<option value="13">HP</option>
<option value="20">Lexmark</option>
<option value="28">Pitney Bowes</option>
<option value="37">Xerox</option>
<option value="17706">More Brands</option>
</select>
</div>
<div class="select-house">
<label for="select_family" class="fancy-label"><span>Select a <b>Printer Family</b></span></label>
<select id="select_family" class="select-family" disabled="">
<option value="">Select a Printer Family</option>
</select>
</div>
<div class="select-house">
<label for="select_model" class="fancy-label"><span>Select a <b>Printer Model</b></span></label>
<select id="select_model" class="select-model" disabled="">
<option value="">Select a Printer Model</option>
</select>
</div>
<script>
require(['mage/storage'], function(storage) {
'use strict';
var finders = Array.from(document.querySelectorAll('.printer-finder-widget'));
finders.forEach(function(finder) {
if (finder.getAttribute('data-activated')) {
return false;
}
var brandSelect = finder.querySelector('.select-brand');
var familySelect = finder.querySelector('.select-family');
var modelSelect = finder.querySelector('.select-model');
var selectedBrand, selectedFamily, selectedModel;
function resetFamily() {
var fancyLabel = familySelect.parentElement.querySelector('.fancy-label');
if (fancyLabel) {
if (fancyLabel.getAttribute('data-html')) {
fancyLabel.querySelector('span').innerHTML = fancyLabel.getAttribute('data-html');
}
}
familySelect.innerHTML = "<option value=''>" + finder.getAttribute('data-family-label') + "</option>";
familySelect.parentElement.classList.remove('has-options');
familySelect.parentElement.classList.remove('loading');
familySelect.disabled = true;
}
function resetModel() {
var fancyLabel = modelSelect.parentElement.querySelector('.fancy-label');
if (fancyLabel) {
if (fancyLabel.getAttribute('data-html')) {
fancyLabel.querySelector('span').innerHTML = fancyLabel.getAttribute('data-html');
}
}
modelSelect.innerHTML = "<option value=''>" + finder.getAttribute('data-model-label') + "</option>";
modelSelect.parentElement.classList.remove('has-options');
modelSelect.parentElement.classList.remove('loading');
modelSelect.disabled = true;
}
function setLoading(select, complete) {
if (complete) {
select.parentElement.classList.remove('loading');
select.parentElement.classList.add('has-options');
select.disabled = false;
} else {
select.parentElement.classList.add('loading');
}
}
brandSelect.addEventListener('change', function() {
familySelect.classList.remove('has-options');
var selectedCategory = this.querySelector('option:checked').value;
var selectedCategoryLabel = this.querySelector('option:checked').innerHTML;
var fancyLabel = brandSelect.parentElement.querySelector('.fancy-label');
if (fancyLabel) {
if (!fancyLabel.getAttribute('data-html')) {
fancyLabel.setAttribute('data-html', fancyLabel.innerHTML);
}
fancyLabel.querySelector('span').innerHTML = selectedCategoryLabel;
}
if (selectedCategory) {
selectedBrand = selectedCategoryLabel;
resetFamily();
resetModel();
setLoading(familySelect);
storage.get(
'/rest/V1/printerfinder/families/' + selectedCategory
).done(function(data) {
var families = JSON.parse(data), option;
for (var i = 0; i < families.length; i++) {
option = document.createElement('option');
option.innerHTML = families[i].name;
option.value = families[i].id;
familySelect.appendChild(option);
}
setLoading(familySelect, true);
});
}
});
familySelect.addEventListener('change', function() {
modelSelect.parentElement.classList.remove('has-options');
var selectedCategory = this.querySelector('option:checked').value;
var selectedCategoryLabel = this.querySelector('option:checked').innerHTML;
var fancyLabel = familySelect.parentElement.querySelector('.fancy-label');
if (fancyLabel) {
if (!fancyLabel.getAttribute('data-html')) {
fancyLabel.setAttribute('data-html', fancyLabel.innerHTML);
}
fancyLabel.querySelector('span').innerHTML = selectedCategoryLabel;
}
if (selectedCategory) {
selectedFamily = selectedCategoryLabel;
resetModel();
setLoading(modelSelect);
storage.get(
'/rest/V1/printerfinder/models/' + selectedCategory
).done(function(data) {
var models = JSON.parse(data), option;
modelSelect.parentElement.classList.remove('loading');
modelSelect.innerHTML = "<option value=''>" + finder.getAttribute('data-model-label') + "</option>";
for (var i = 0; i < models.length; i++) {
option = document.createElement('option');
option.innerHTML = models[i].name;
option.setAttribute('data-url', models[i].url);
modelSelect.appendChild(option);
}
setLoading(modelSelect, true);
});
}
});
modelSelect.addEventListener('change', function() {
var selectedCategory = this.querySelector('option:checked');
var selectedCategoryLabel = this.querySelector('option:checked').innerHTML;
var fancyLabel = modelSelect.parentElement.querySelector('.fancy-label');
if (fancyLabel) {
if (!fancyLabel.getAttribute('data-html')) {
fancyLabel.setAttribute('data-html', fancyLabel.innerHTML);
}
fancyLabel.querySelector('span').innerHTML = selectedCategoryLabel;
}
if (selectedCategory.getAttribute('data-url')) {
selectedModel = selectedCategoryLabel;
try {
window.sessionStorage.setItem("lastFinderConfig", JSON.stringify({
brand: selectedBrand,
family: selectedFamily,
model: selectedModel
}));
} catch (e) {
// private browsing
}
window.location = selectedCategory.getAttribute('data-url');
}
});
finder.setAttribute('data-activated', true);
});
});
</script>
</div>
Related
I have to make sure the second dropdown menu only starts showing when an option ("Tijd" or "Woorden") is selected in the first one. When no option is selected afterwards, the second dropdown has to hide again.
HTML
<div class="dropdown">
<p>Spelmodus:</p>
<select id="spelmodus" name="spelmodus" onchange="changeSpelmodus(this.value);">
<option></option>
</select>
</div>
<div id="optieDiv">
<p id="tijdWoorden"></p>
<select id="opties" name="opties" onchange="changeOptie(this.value);">
</select>
</div>
JavaScript
var spelmodusOpties = {
"Tijd": [{"Optie": "1 minuut"}, {"Optie": "2 minuten"}, {"Optie": "5 minuten"}],
"Woorden": [{"Optie": "50 woorden"}, {"Optie": "100 woorden"}, {"Optie": "150 woorden"}],
};
function PrepopulateSpelmodus() {
var spelmodusSelect = document.getElementById('spelmodus');
var i = 1;
for (var spelmodus in spelmodusOpties) {
spelmodusSelect.options[i++] = new Option(spelmodus)
}
}
function changeSpelmodus(productNameID) {
var optieSelect = document.getElementById('opties');
optieSelect.innerHTML = '<option></option>'; // Remove previous options
var versions = spelmodusOpties[productNameID];
for (var i = 0; i < versions.length; i++) {
optieSelect.appendChild(new Option(versions[i].Optie));
}
var selectie = document.getElementById('spelmodus').value;
document.getElementById('tijdWoorden').innerHTML = selectie
}
function changeOptie() {
var productNameID = document.getElementById('spelmodus').value;
var versions = spelmodusOpties[productNameID];
for (var i = 0; i < versions.length; i++) {
}
}
PrepopulateSpelmodus();
You just need to validate and hide on change of select
if(!productNameID){
document.getElementById('optieDiv').style.display = "none"
return;
}else{
document.getElementById('optieDiv').style.display = ""
}
var spelmodusOpties = {
"Tijd": [{"Optie": "1 minuut"}, {"Optie": "2 minuten"}, {"Optie": "5 minuten"}],
"Woorden": [{"Optie": "50 woorden"}, {"Optie": "100 woorden"}, {"Optie": "150 woorden"}],
};
function PrepopulateSpelmodus() {
var spelmodusSelect = document.getElementById('spelmodus');
var i = 1;
for (var spelmodus in spelmodusOpties) {
spelmodusSelect.options[i++] = new Option(spelmodus)
}
}
function changeSpelmodus(productNameID) {
if(!productNameID){
document.getElementById('optieDiv').style.display = "none"
return;
}else{
document.getElementById('optieDiv').style.display = ""
}
var optieSelect = document.getElementById('opties');
optieSelect.innerHTML = '<option></option>'; // Remove previous options
var versions = spelmodusOpties[productNameID];
for (var i = 0; i < versions.length; i++) {
optieSelect.appendChild(new Option(versions[i].Optie));
}
var selectie = document.getElementById('spelmodus').value;
document.getElementById('tijdWoorden').innerHTML = selectie
}
function changeOptie() {
var productNameID = document.getElementById('spelmodus').value;
var versions = spelmodusOpties[productNameID];
for (var i = 0; i < versions.length; i++) {
}
}
PrepopulateSpelmodus();
<div class="dropdown">
<p>Spelmodus:</p>
<select id="spelmodus" name="spelmodus" onchange="changeSpelmodus(this.value);">
<option></option>
</select>
</div>
<div id="optieDiv" style="display: none">
<p id="tijdWoorden"></p>
<select id="opties" name="opties" onchange="changeOptie(this.value);">
</select>
</div>
const optieDivEl = document.querySelector('#optieDiv');
function toggleOptieDiv(event) {
// Check if the event.target (select) is one of the specified values
if (['tijd', 'woorden'].includes(event.target.value)) {
// Do no render `div.optieDiv`
optieDivEl.style.display = 'none';
} else {
// Render `div.optieDiv`
optieDivEl.style.display = 'block';
}
}
document.onload = toggleOptieDiv;
document.querySelector('#spelmodus').addEventListener('change', toggleOptieDiv);
<div class="dropdown">
<p>Spelmodus:</p>
<select id="spelmodus" name="spelmodus">
<option value="">--Please choose an option--</option>
<option value="tijd">Tijd</option>
<option value="woorden">Woorden</option>
<option value="other">Other</option>
</select>
</div>
<div id="optieDiv">
<p id="tijdWoorden"></p>
<select id="opties" name="opties" onchange="changeOptie(this.value);">
</select>
</div>
I have an ecommerce site that has products with multiple attributes (e.g. size, colour, etc,.)
On each product page there is a dropdown for each attribute with a class of 'attribute_price'.
I have also preloaded hidden inputs onto the page from my database with the pricing for each product with a class of 'hidden_attribute_value'.
So not every combination of size and colour is an option. For example, we might have 'small_red' or 'medium_red' but no 'large_red'
So if they select 'large' from the size dropdown menu 'red' should not be an option for the colour.
What I have so far is:
$("select.attribute_price").on("change", function(){
var id = event.target.id;
// determine which dropdown was changed (size or colour)
var attribute_value = document.getElementById(id).value+'_';
// get the value of the dropdown that they selected
var other_attribute_ids = []
var i;
var other_attributes = document.getElementsByClassName("attribute_price");
for(i=0; i<other_attributes.length; i++){
if(other_attributes[i].id != id){
var other_attribute_id = document.getElementById(other_attributes[i].id).id;
other_attribute_ids.push(other_attribute_id);
}
}
// create an array of all of the other dropdown ids excluding the one they changed
var all_attribute_ids = []
var i;
var all_attributes = document.getElementsByClassName("hidden_attribute_value");
for(i=0; i<all_attributes.length; i++){
all_attribute_ids.push(all_attributes[i].id);
}
// create an array of all of the possible values that it can be
});
So I have a variable 'attribute_value' which would be something like 'red_' or 'blue_'.
I have an array called 'all_attribute_values' which has the ids of hidden inputs for all possible combinations. These would have values like 'small_red_' or 'small_blue'.
And I have an array called 'other_attribute_ids' which has the id of the other dropdown menus that haven't been selected.
So if an item in 'all_attribute_values' does not contain 'attribute_value' remove that option from 'other_attribute_ids'.
I have created a sample html based on your usecase. Solution is likewise, but you should get inspiration for solving yours.
I have considered independent attributes, so the solution will scale to new attributes with different values. I have also considered that server response is not editable.
I have a quick link in jsfiddle to checkout the solution
https://jsfiddle.net/nfLx6aok/1/
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<select id="size" class="attribute_price">
<option value="small">Small</option>
<option value="large">Large</option>
</select>
<select id="color" class="attribute_price">
<option value="red">Red</option>
<option value="green">Green</option>
<option value="black">Black</option>
</select>
<select id="pattern" class="attribute_price">
<option value="solids">Solids</option>
<option value="checked">Checked</option>
<option value="dots">Dots</option>
</select>
<input type="hidden" id="small_red_solids" class="hidden_attribute_value">
<input type="hidden" id="small_black_dots" class="hidden_attribute_value">
<input type="hidden" id="large_green_checked" class="hidden_attribute_value">
<script>
// on page load
$( document ).ready(function() {
renderOptions();
});
$("select.attribute_price").on("change", function () {
renderOptions();
});
function renderOptions() {
// create an array of all of the possible values that it can be
// allowed_attribute_values = ['small_red', 'large_blue']
var allowed_attribute_values = [];
var all_attributes = document.getElementsByClassName("hidden_attribute_value");
for (var i = 0; i < all_attributes.length; i++) {
allowed_attribute_values.push(all_attributes[i].id);
}
function getAllPossibleValues(current_level, all_attributes) {
var depth_index = all_attributes.length;
var selected_combination = '';
for (var i = 0; i < depth_index; i++) {
if (i <= current_level) {
selected_combination += all_attributes[i].value;
if (i != all_attributes.length - 1) {
selected_combination += '_';
}
}
}
// hide all lower options
for (var i = current_level + 1; i < depth_index; i++) {
var selectedIdOptions = all_attributes[i].options;
all_attributes[i].value = null
for (var j = 0; j < selectedIdOptions.length; j++) {
// hide all lower options
selectedIdOptions[j].hidden = true;
var el = allowed_attribute_values.find(a => a.includes(selected_combination + selectedIdOptions[j].value));
if (el) {
selectedIdOptions[j].hidden = false;
}
}
}
}
if (event) {
var id = event.target.id;
} else {
var id = document.getElementsByClassName("attribute_price")[0].id;
}
var other_attributes = document.getElementsByClassName("attribute_price");
for (var i = 0; i < other_attributes.length; i++) {
if (other_attributes[i].id == id) {
allPossibleValues = getAllPossibleValues(i, other_attributes);
// we dont want to go deeper as of now
break;
}
}
}
</script>
this would work with any number of dropdown.
you can generate random attributes to test.
$(document).ready(function () {
/* generates random attributes */
var div_attributes = $('#div_attributes');
var select_colors = $('#select_colors');
var select_sizes = $('#select_sizes');
var select_attr0 = $('#select_attr0');
var select_attr1 = $('#select_attr1');
$('#btnGenerate').on('click', function () {
var result = "";
//
var index = getRandomArbitrary(1, select_sizes.find('option').get().length);
var random_attribute = select_sizes.find('option').eq(index).attr('value');
result += random_attribute;
//
index = getRandomArbitrary(1, select_colors.find('option').get().length);
random_attribute = select_colors.find('option').eq(index).attr('value');
result += '_' + random_attribute;
//
index = getRandomArbitrary(1, select_attr0.find('option').get().length);
random_attribute = select_attr0.find('option').eq(index).attr('value');
result += '_' + random_attribute;
//
index = getRandomArbitrary(1, select_attr1.find('option').get().length);
random_attribute = select_attr1.find('option').eq(index).attr('value');
result += '_' + random_attribute;
$('<div>' + result + '</div>').appendTo(div_attributes);
div_attributes.find('div').each(function () {
var item = $(this);
attributes.push(item.text());
});
SetFirstSelect();
});
var attributes = [];
//sets first select
SetFirstSelect();
function SetFirstSelect() {
$.each(attributes, function (i, val) {
var attribute = val.split('_')[0];
$('.attribute_price').eq(0).find('option[value="' + attribute + '"]').show();
});
}
//control attributes array
var selected_val = [];
$('.attribute_price').on('change', function () {
var item = $(this);
var index = item.index('.attribute_price');
selected_val[index] = item.val();
var select = $('.attribute_price').eq(index + 1);
var selected_attribute = item.val();
for (var i = index + 1; i < $('.attribute_price').get().length; i++) {
$('.attribute_price').eq(i).find('option').hide();
$('.attribute_price').eq(i).prop('selectedIndex', 0)
}
var selected_val_str = selected_val[0];
for (var i = 1; i <= index; i++) {
selected_val_str += '_' + selected_val[i];
}
$.each(attributes, function (j, val) {
if (val.indexOf(selected_val_str) >= 0) {
var attribute1 = val.split('_')[index + 1];
select.find('option[value="' + attribute1 + '"]').show();
}
});
});
function getRandomArbitrary(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
});
.attribute_price option {
display: none;
}
.container {
margin:30px;
}
.row > div {
padding:10px;
}
.btn {
margin-top:20px;
}
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<div class="container">
<div class="row">
<div style="width:50%; float:left">
<input type="button" class="btn btn-primary" id="btnGenerate" value="generate random attributes" />
<div id="div_attributes"></div>
</div>
<div style="width:50%; float:left">
<div class="form-group">
<label>Sizes</label>
<select class="form-control attribute_price" id="select_sizes">
<option value="">select size</option>
<option value="small">small</option>
<option value="large">large</option>
<option value="medium">medium</option>
</select>
</div>
<div class="form-group">
<label>color</label>
<select id="select_colors" class="form-control attribute_price">
<option value="">select color</option>
<option value="black">black</option>
<option value="yellow">yellow</option>
<option value="red">red</option>
</select>
</div>
<div class="form-group">
<label>attrType0</label>
<select id="select_attr0" class="form-control attribute_price">
<option value="">select attr0</option>
<option value="attr00">attr00</option>
<option value="attr01">attr01</option>
<option value="attr02">attr02</option>
</select>
</div>
<div class="form-group">
<label>attrType1</label>
<select id="select_attr1" class="form-control attribute_price">
<option value="">select attr1</option>
<option value="attr10">attr10</option>
<option value="attr11">attr11</option>
<option value="attr12">attr12</option>
</select>
</div>
</div>
</div>
</div>
I don't know if I have understood exactly what you are trying to explain or not but here's what I understood
you have a website with suppose dropdowns for say clothes having attributes size, price, color, brand and you have an array of objects containing all of these attributes for each object.
I will be explaining this in reactjs since i am more familiar with it than php
so for each dropdown you can have an onchange handler which invokes a function where you check the values of the other dropdowns. If You select size M then enable and populate the dropdown list after filtering clothes with size M. when that is done invoke a similar function for checking the other attributes.
at this time all of your dropdowns will be active, now if the user makes any changes to the first dropdown i.e. size you can either reset the other dropdowns to be reselected or just pass the new list depending on how you are handling
Here is a similar thing i had done for setting date
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July','August', 'September', 'October', 'November', 'December']
const Month30 = ['4', '6', '9', '11']
const Month31 = ['1', '3', '5', '7', '8', '10', '12']
class Dropdown extends React.Component {
constructor(props) {
super(props)
this.state = {
birthDay: '',
birthMonth: '',
birthYear: ''
}
}
componentDidMount() {
}
getMonthTotalDays = (birthMonth, birthYear) => {
if (birthMonth === '02') {
if (birthYear !== '' && birthYear % 4 === 0) {
return 29
} else {
return 28
}
} else if (Month30.includes(birthMonth)) {
return 30
} else {
return 31
}
}
handleChange = e => {
this.setState({
[e.target.name]: e.target.value
}, () => {
const { birthMonth, birthYear, birthDay } = this.state
const days = this.getMonthTotalDays(birthMonth, birthYear)
if (birthDay > days) {
this.setState({ birthDay: '' })
}
})
}
renderMonths = () => {
return months.map((month, i) => {
if(i < 9){
return (<option key={`${month}-${i}`} value={'0' + (i + 1)}>{month}</option>)
}
else
return (<option key={`${month}-${i}`} value={i + 1}>{month}</option>)
})
}
renderDay = () => {
const { birthMonth, birthDay, birthYear } = this.state
const daysOptions = []
let days = this.getMonthTotalDays(birthMonth, birthYear)
for (let day=1; day<=days; day++) {
daysOptions.push(<option key={`'date-'${day}`} value={day}> { day } </option>)
}
return daysOptions
}
renderYears = () => {
const toYear = (new Date()).getFullYear() - 16
const yearOptions = []
for (let year = 1960; year <= toYear; year++) {
yearOptions.push(<option key={`year-${year}`} value={year}> { year } </option>)
}
return yearOptions
}
render() {
const { birthDay, birthMonth, birthYear } = this.state
return (
<div>
<label>Month</label>
<select
name="birthMonth"
value={ birthMonth }
onChange={this.handleChange}
>
<option disabled selected value=''>Month</option>
{ this.renderMonths() }
</select>
<label>Day</label>
<select
name='birthDay'
value={ birthDay }
onChange={this.handleChange}
>
<option disabled selected value=''>Day</option>
{ this.renderDay() }
</select>
<label>Year</label>
<select
name='birthYear'
value={ birthYear }
onChange={this.handleChange}
>
<option disabled selected value=''>Year</option>
{ this.renderYears() }
</select>
</div>
)
}
}
ReactDOM.render(
<Dropdown />,
document.getElementById('drop')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="drop"></div>
Here is a solution that takes a skus array as input and create a dropdown for each attribute. When any dropdown value changes, the options in all other dropdowns are updated to show only options consistent with picked options.
https://codepen.io/rockysims/pen/PyJbbv
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script type="text/javascript">
skus = [{
id: 1,
attributes: {
color: "red",
size: "small",
shape: "circle"
}
}, {
id: 2,
attributes: {
color: "red",
size: "medium",
shape: "square"
}
}, {
id: 3,
attributes: {
color: "yellow",
size: "small",
shape: "circle"
}
}, {
id: 4,
attributes: {
color: "yellow",
size: "medium",
shape: "square"
}
}, {
id: 5,
attributes: {
color: "yellow",
size: "large",
shape: "square"
}
}, {
id: 6,
attributes: {
color: "green",
size: "medium",
shape: "square"
}
}, {
id: 7,
attributes: {
color: "green",
size: "large",
shape: "square"
}
}];
$(function() {
const allOptionsByAttrName = buildAllOptionsByAttrName();
//create dropdowns
for (let attrName in allOptionsByAttrName) {
const dropdownId = attrName + "Dropdown";
const options = allOptionsByAttrName[attrName];
let html = "";
html += attrName + ": ";
html += buildDropdownHtml(dropdownId, options);
html += "<br/>";
$("#dropdowns").append(html);
}
//on dropdown changes, update options of all dropdowns
for (let changedAttrName in allOptionsByAttrName) {
$("#" + changedAttrName + "Dropdown").on('change', function() {
//build pickedOptionByAttrName
const pickedOptionByAttrName = {};
for (let attrName in allOptionsByAttrName) {
const dropdown = $("#" + attrName + "Dropdown");
pickedOptionByAttrName[attrName] = dropdown.val();
}
refreshAvailableOptions(pickedOptionByAttrName);
});
}
});
function buildAllOptionsByAttrName() {
const allOptionsByAttrName = {};
for (let sku of skus) {
for (let attrName in sku.attributes) {
allOptionsByAttrName[attrName] = allOptionsByAttrName[attrName] || [];
if (allOptionsByAttrName[attrName].indexOf(sku.attributes[attrName]) == -1) {
allOptionsByAttrName[attrName].push(sku.attributes[attrName]);
}
}
}
return allOptionsByAttrName;
}
function buildDropdownHtml(dropdownId, options) {
let html = "";
html += "<select id='" + dropdownId + "'>";
html += "<option value=''>";
html += "";
html += "</option>";
for (let option of options) {
html += "<option value='" + option + "'>";
html += option;
html += "</option>";
}
html += "</select>";
return html;
}
function refreshAvailableOptions(pickedOptionByAttrName) {
for (let attrName in pickedOptionByAttrName) {
//build availableOptions
const dropdown = $("#" + attrName + "Dropdown");
const options = $("#" + attrName + "Dropdown option");
const availableOptions = buildAvailableOptions(pickedOptionByAttrName, attrName);
availableOptions.push(""); //nothing picked option
//show available options and hide others
options.each(function() {
const option = $(this);
const optionIsAvailable = availableOptions.indexOf(option.val()) != -1;
if (optionIsAvailable) {
option.show();
} else {
option.hide();
}
});
}
}
function buildAvailableOptions(pickedOptionByAttrName, attrNameToBuildFor) {
//build availableSkus
const availableSkus = skus.filter(function(sku) {
let available = true;
for (let attrName in pickedOptionByAttrName) {
if (attrName != attrNameToBuildFor) {
const pickedOption = pickedOptionByAttrName[attrName];
if (pickedOption) {
available = available && sku.attributes[attrName] == pickedOption;
}
}
}
return available;
});
//build availableOptions
const availableOptions = [];
for (let sku of availableSkus) {
if (availableOptions.indexOf(sku.attributes[attrNameToBuildFor]) == -1) {
availableOptions.push(sku.attributes[attrNameToBuildFor]);
}
}
return availableOptions;
}
</script>
<div id="dropdowns">
</div>
If you prefer not to dynamically create the dropdowns, comment out the for loop under //create dropdowns and replace <div id="dropdowns"></div> with the following:
<div id="dropdowns">
color:
<select id="colorDropdown">
<option value=""></option>
<option value="red">red</option>
<option value="yellow">yellow</option>
<option value="green">green</option>
</select><br/>
size:
<select id="sizeDropdown">
<option value=""></option>
<option value="small">small</option>
<option value="medium">medium</option>
<option value="large">large</option>
</select><br/>
shape:
<select id="shapeDropdown">
<option value=""></option>
<option value="circle">circle</option>
<option value="square">square</option>
</select><br>
</div>
If you can identify in PHP which options for other categories are available for certain drop-down category-value selection. You can incrementally flag each option as excluded for each selected value to keep it disabled:
JS:
$(document).ready(function () {
$(".dropdown").change(function(){
var val = $(this).val();
var id = $(this).attr('id');
$.get('get_options.php', {category: id, value:val}, function(data) {
$(".dropdown:not(#"+id+")").each(function() {
var cat = $(this).attr('id');
$(this).find('option').each(function() {
var cat_val = $(this).val();
var options = data[cat];
var exluded = $(this).attr('exlude');
if ($.inArray(cat_val, options) !== -1) {
$(this).attr('exlude', exluded-1);
if(exluded == 1) {
$(this).prop('disabled', false);
}
} else {
$(this).attr('exlude', exluded+1);
$(this).prop('disabled', true);
}
});
});
}, 'json');
});
});
HTML:
<div id="dropdowns">
color:
<select id="color" class="dropdown">
<option value=""></option>
<option value="red">red</option>
<option value="yellow">yellow</option>
<option value="green">green</option>
</select><br/>
size:
<select id="size" class="dropdown">
<option value=""></option>
<option value="small">small</option>
<option value="medium">medium</option>
<option value="large">large</option>
</select><br/>
shape:
<select id="shape" class="dropdown">
<option value=""></option>
<option value="circle">circle</option>
<option value="square">square</option>
<option value="triangle">triangle</option>
</select><br>
**SAMPLE DATA: ** example if user selects color first, return all available options for other drop-down categories.
{"size": ["small","large"],"shape":["circle"]}
or in php:
$data = array(
'size' => array(
'small', 'large'
),
'shape' => array(
'circle'
),
);
echo json_encode($data);
I am trying to disable/remove options in a dropdown, based on the selection of other dropdown options.
But the dropdown/selector we have to choose from, has a sub-dropdown list and both main and sub dropdowns are
sharing the same classes and ids but since both are wrapped in different divs with different ids, I have been
trying to access the second selector but couldn't .
Below is the js code that I used for this;
<script type="text/javascript">
document.getElementById("lvl1").querySelector("select").onchange = function()
{
if(this.value=="8"){
var bikeSizes = document.getElementById("pa_size[]");
for ( var i = 1; i <8; i++) {
bikeSizes.options[i].removeAttribute("disabled", "disabled");
}
for ( var i = 8; i < 12; i++) {
bikeSizes.options[i].setAttribute("disabled", "disabled");
}
} else {
var bikeSizes = document.getElementById("pa_size[]");
for ( var i = 1; i < 8; i++) {
bikeSizes.options[i].setAttribute("disabled", "disabled");
}
for ( var i = 8; i < 12; i++) {
bikeSizes.options[i].removeAttribute("disabled", "disabled");
}
}
return false;
};
</script>
The html code of the selector/dropdowns are;
— Select —
Camping
Road Sports
Snow Sports
Water Sports
<div id="lvl1" level="1" style="">
<select data-required="yes" data-type="select" name="product_cat" id="product_cat" class="cat-ajax product_cat wpuf_product_cat_">
<option value="-1">— Select —</option>
<option class="level-0" value="8">Bikes</option>
</select>
<span data-taxonomy="{"required":"yes","name":"product_cat","exclude_type":"child_of","exclude":"camping,road-sports,water-sports","orderby":"name","order":"ASC"}"></span>
</div>
I fixed the quote then put it in an onload function. Also, there is no second argument on a removeAttribute. This worked for me.
<script>
window.onload = function () {
document.getElementById("product_cat").onchange = function () {
if (this.value == "8") {
var bikeSizes = document.getElementById("pa_size[]");
for (var i = 1; i < 8; i++) {
bikeSizes.options[i].removeAttribute("disabled");
}
for (var i = 8; i < 12; i++) {
bikeSizes.options[i].setAttribute("disabled", "disabled");
}
} else {
var bikeSizes = document.getElementById("pa_size[]");
for (var i = 1; i < 8; i++) {
bikeSizes.options[i].setAttribute("disabled", "disabled");
}
for (var i = 8; i < 12; i++) {
bikeSizes.options[i].removeAttribute("disabled");
}
}
return false;
};
}
</script>
<!-- my test html -->
<div id="lvl1" level="1" style="">
<select data-required="yes" data-type="select" name="product_cat" id="product_cat" class="cat-ajax product_cat wpuf_product_cat_">
<option value="-1">— Select —</option>
<option class="level-0" value="8">Bikes</option>
</select>
<span data-taxonomy="{"required":"yes","name":"product_cat","exclude_type":"child_of","exclude":"camping,road-sports,water-sports","orderby":"name","order":"ASC"}"></span>
<select id="pa_size[]">
<option value="-1">--Select--</option>
<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>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
</select>
</div>
Based on what I saw on your website, here is an alternative solution:
<script>
var group1 = [ { value:"33", text:"Small Unisex"},
{ value:"34", text:"Large Unisex"},
{ value:"35", text:"XL Unisex"},
{ value:"36", text:"Small Womens"},
{ value:"37", text:"Medium Womens"},
{ value:"38", text:"Large Womens"},
{ value:"39", text:"XL Womens"}];
var group2 = [{value:"40", text:"Medium"},
{value:"41", text:"Small"},
{ value:"43", text:"XL"},
{ value:"42", text:"Large"}];
window.onload = function() {
document.getElementById("product_cat").onchange = function () {
var bikeSizes = document.getElementById("pa_size[]");
bikeSizes.innerHTML = "";
bikeSizes.appendChild(new Option("--Select--", "-1"));
bikeSizes.disabled = false;
if (this.value == "-1") {
bikeSizes.disabled = true;
}
else if (this.value == "8") {
for (var i = 0; i < group1.length; ++i){
var opt = new Option(group1[i].text, group1[i].value);
bikeSizes.appendChild(opt);
}
} else {
for (var i = 0; i < group2.length; ++i) {
var opt = new Option(group2[i].text, group2[i].value);
bikeSizes.appendChild(opt);
}
}
return false;
};
}
</script>
so is this closer to what you need? This is 3 select boxes where you can only see the second one after the first one has a valid selection. Then you can only see the third one when the second one has a valid choice.
The options available is dependent on its master select box.
you can see it work here http://jsbin.com/nijahoh/edit?html,js,output
<script>
var fakeData = {
group1: [{ value: "group3", text: "3" }, { value: "group4", text: "4" }],
group2: [{ value: "group5", text: "5" }, { value: "group6", text: "6" }],
group3: [{ value: "group7", text: "7" }, { value: "group8", text: "8" }],
group4: [{ value: "group9", text: "9" }, { value: "group10", text: "10" }]
};
$(document).ready(function(){
// first select box change handler
$("#product_cat").on("change", function () {
var val = this.value;
$("#d").val("-1");
setUpSel($("#d"), val);
$("#d").trigger("change");
$("#d").css("display", val=="-1"?"none":"");
});
$("#d").on("change", function () {
var val = this.value;
$("#c").val("-1");
setUpSel($("#c"), val);
$("#c").trigger("change");
$("#c").css("display", val == "-1" ? "none" : "");
});
});
function setUpSel($sel, group) {
$sel.html("<option value='-1'>--Select--</option>");
var selData = fakeData[group];
$.each(selData, function (i, opt) {
$sel.append(new Option(opt.text, opt.value));
});
}
</script>
I trying to do 2 combo box on web page
Let said Country option person choose "China" the second combobox will list all the provinces, after which if the user choose "JiangSu" for example will open a dedicate iframe underneath the 2nd combobox
Any idea how to do it?
<script type="text/javascript">
/*
Triple Combo Script Credit
By Philip M: http://www.codingforums.com/member.php?u=186
Visit http://javascriptkit.com for this and over 400+ other scripts
*/
var categories = [];
categories["startList"] = ["China","US"]
categories["China"] = ["ANHUI","JIANGSU"];
categories["US"] = ["Alabama","New york"];
var nLists = 2; // number of select lists in the set
function fillSelect(currCat,currList){
var step = Number(currList.name.replace(/\D/g,""));
for (i=step; i<nLists+1; i++) {
document.forms['tripleplay']['List'+i].length = 1;
document.forms['tripleplay']['List'+i].selectedIndex = 0;
}
var nCat = categories[currCat];
for (each in nCat) {
var nOption = document.createElement('option');
var nData = document.createTextNode(nCat[each]);
nOption.setAttribute('value',nCat[each]);
nOption.appendChild(nData);
currList.appendChild(nOption);
}
}
function getValue(L2, L1) {
<!-- alert("Your selection was:- \n" + L1 + "\n" + L2);-->
document.getElementById("lname").value= L1 + "\n" + L2;
}
function init() {
fillSelect('startList',document.forms['tripleplay']['List1'])
}
navigator.appName == "Microsoft Internet Explorer" ? attachEvent('onload', init, false) : addEventListener('load', init, false);
</script>
html
<span class="favorBOfont">Country Selection</span><p> </p>
<form name="tripleplay" action="">
Category:
<select name='List1' onchange="fillSelect(this.value,this.form['List2'])">
<option selected>Make a selection</option>
</select>
<p> </p>
<p>
Content:
<select name='List2' onchange="getValue(this.value, this.form['List1'].value)">
<option selected>Make a selection</option>
</select>
<!-- onchange="fillSelect(this.value,this.form['List3'])" -->
</p>
</form>
<p> </p>
<p>
<textarea rows="8" cols="88" id="lname" name="lname" size="30" height="30" readonly></textarea>
</p>
<div></div>
I would need an iframe statement instead of textarea property
Here is a basic example.
var nList1 = document.querySelector('select[name="List1"]'),
nList2 = document.querySelector('select[name="List2"]'),
myFrame = document.getElementById('myFrame'),
categories = ["China", "US"],
contents = {
China: ["ANHUI", "JIANGSU"],
US: ["Alabama", "New york"]
}
categories.forEach(function (category) {
var option = document.createElement('option');
option.value = option.textContent = category;
nList1.appendChild(option);
});
nList1.addEventListener('change', function (evt) {
var target = evt.target,
value = target.value,
options = nList2.options,
content = contents[value];
myFrame.src = '';
nList2.selectedIndex = 0;
while (options.length > 1) {
nList2.removeChild(options[1]);
}
if (content) {
content.forEach(function (element) {
var option = document.createElement('option');
option.value = option.textContent = element;
nList2.appendChild(option);
});
}
}, false);
nList2.addEventListener('change', function (evt) {
if (evt.target.selectedIndex) {
myFrame.src = '/';
} else {
myFrame.src = '';
}
}, false);
.dropDown {
display:block;
}
#myFrame {
margin-top:1em;
width:100%
}
<span class="favorBOfont">Country Selection</span>
<label class="dropDown">Category:
<select name="List1">
<option>Make a selection</option>
</select>
</label>
<label>Content:
<select name="List2">
<option>Make a selection</option>
</select>
</label>
<iframe id="myFrame"></iframe>
I have an element which is text box but its value is populated from another hidden select element.
<input type="text" id="autocompleteu_17605833" style="box-shadow: none; width: 119px;" class="mobileLookupInput ui-autocomplete-input" autocomplete="off" role="textbox" aria-autocomplete="list" aria-haspopup="true">
<select id="u_17605833" name="u_17605833" style="visibility: hidden">
<option value="127468">Virginia</option>
<option value="127469">Washington</option>
<option value="127470">West Virginia</option>
<option value="127471">Wisconsin</option>
<option value="127472">Wyoming</option>
</select>
var mySelObju_17605833 = document.getElementById("u_17605833");
$(function () {
var availableTagsu_17605833 = new Array();
for (var i = 0; i < mySelObju_17605833.options.length; i++) {
if (mySelObju_17605833.options[i].text != 'Other') {
availableTagsu_17605833[i] = mySelObju_17605833.options[i].text;
}
}
$("#autocompleteu_17605833").width($(mySelObju_17605833).width() + 5);
availableTagsu_17605833 = $.map(availableTagsu_17605833, function (v) {
return v === "" ? null : v;
});
$("#autocompleteu_17605833").autocomplete({
minLength: 0,
source: function (request, response) {
var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term), "i");
var a = $.grep(availableTagsu_17605833, function (item, index) {
var items = item.split(" ");
for (i = 0; i < items.length; i++) {
if (matcher.test(items[i])) return matcher.test(items[i]);
}
return matcher.test(item);
});
response(a);
},
close: function (event, ui) {
for (var i = 0, sL = mySelObju_17605833.length; i < sL; i++) {
if (mySelObju_17605833.options[i].text.toLowerCase() == $("#autocompleteu_17605833").val().toLowerCase()) {
mySelObju_17605833.selectedIndex = i;
$("#errorTDu_17605833").html("");
break;
}
mySelObju_17605833.selectedIndex = 0;
$("#errorTDu_17605833").html("Error: Invalid Input");
}
$("#autocompleteu_17605833").trigger("onchange")
}
});
});
$("#autocompleteArrowu_17605833").click(function () {
$("#autocompleteu_17605833").autocomplete("search");
$("#autocompleteu_17605833").focus();
});
$("#autocompleteu_17605833").focusout(function () {
for (var i = 0, sL = mySelObju_17605833.length; i < sL; i++) {
if (mySelObju_17605833.options[i].text.toLowerCase() == $("#autocompleteu_17605833").val().toLowerCase()) {
mySelObju_17605833.selectedIndex = i;
$("#errorTDu_17605833").html("");
break;
}
mySelObju_17605833.selectedIndex = 0;
$("#errorTDu_17605833").html("Error: Invalid Input");
}
$("#autocompleteu_17605833").trigger("onchange")
//$(this).autocomplete("close");
});
I want to find value selected in the hidden select box!
I tried to do the following
$("#autocompleteu_17605833").on("click", function (event) {
$((this.id).substring((this.id).indexOf("_") - 1)).attr("onchange", function (event) {
var selece = this.value;
alert(selece);
});
});
$("#autocompleteu_17605833").next().on("click", function (event) {
var selectedValue = document.getElementById((this.id).substring((this.id).indexOf("_") - 1)).value;
alert("Click on Arrow" + selectedValue);
});
$("#autocompleteu_17605833").on("change", function (event) {
var selectedValue = document.getElementById((this.id).substring((this.id).indexOf("_") - 1)).value;
alert("Changing the value" + selectedValue);
});
what I'm getting is older value where as I need the current assigned value.
How to achieve this??
WORKING DEMO
If am not wrong you want the selected value for this you can use select method
select:function(event,ui) {
alert("You have selected "+ui.item.label);
alert("You have selected "+ui.item.value);
}
This is a simple piece of code that will work as you required.
function result(){
document.getElementById("result").innerHTML= document.getElementById("u_17605833").value;
}
<html>
<head>
</head>
<body>
<div>
<select id="u_17605833" name="u_17605833" >
<option value="127468">Virginia</option>
<option value="127469">Washington</option>
<option value="127470">West Virginia</option>
<option value="127471">Wisconsin</option>
<option value="127472">Wyoming</option>
</select>
<input type="button" value="Show the result" onclick="result()"/>
</div>
<div id="result"></div>
</body>
</html>