Abdul
Abdul

Reputation: 51

how to change options in a selection based on the chosen option in another selection

I have tried to use javascript/j-query to change options in the 2nd selection depending on the choice in the 1st selection.

I think the reason the javascript isn't working is because of other javascript that is used to style the dropdown.

If you have extra time, I would be grateful if you also show me how to link it to another dropdown called subjects (topic dropdown's choices depend on the subject and the qualification).

Finally, if you find a better solution that uses another language like php, I would accept that too.

Edit: A lot of people were stripping down the styling and the other js function.

The answers you give me are correct, but they won't work for me, probably because the problem lies in the other javascript function (the one that allows me to style the dropdown).

If you answer my question; it would be more helpful to include the problematic js function, since an answer that includes that will work for me.

Thanks

$(document).ready(function () {
    $("#level").change(function () {
        var val = $("#level").val();
        if (val === "GCSE") {
            $("#topic").html("<option value='test'>item1: test 1</option><option value='test2'>item1: test 2</option>");
        }
		else if (val === "asLevel") {
            $("#topic").html("<option value='test'>item2: test 1</option><option value='test2'>item2: test 2</option>");
        }
		else if (val === "aLevel") {
            $("#topic").html("<option value='test'>item3: test 1</option><option value='test2'>item3: test 2</option>");
        }
    });
});

var x, i, j, selElmnt, a, b, c;
/*look for any elements with the class "custom-select":*/
x = document.getElementsByClassName("custom-select");
for (i = 0; i < x.length; i++) {
	selElmnt = x[i].getElementsByTagName("select")[0];
	/*for each element, create a new DIV that will act as the selected item:*/
	a = document.createElement("DIV");
	a.setAttribute("class", "select-selected");
	a.innerHTML = selElmnt.options[selElmnt.selectedIndex].innerHTML;
	x[i].appendChild(a);
	/*for each element, create a new DIV that will contain the option list:*/
	b = document.createElement("DIV");
	b.setAttribute("class", "select-items select-hide");
	for (j = 0; j < selElmnt.length; j++) {
		/*for each option in the original select element,
		create a new DIV that will act as an option item:*/
		c = document.createElement("DIV");
		c.innerHTML = selElmnt.options[j].innerHTML;
		c.addEventListener("click", function(e) {
			/*when an item is clicked, update the original select box,
			and the selected item:*/
			var y, i, k, s, h;
			s = this.parentNode.parentNode.getElementsByTagName("select")[0];
			h = this.parentNode.previousSibling;
			for (i = 0; i < s.length; i++) {
				if (s.options[i].innerHTML == this.innerHTML) {
					s.selectedIndex = i;
					h.innerHTML = this.innerHTML;
					y = this.parentNode.getElementsByClassName("same-as-selected");
					for (k = 0; k < y.length; k++) {
						y[k].removeAttribute("class");
					}
					this.setAttribute("class", "same-as-selected");
					break;
				}
			}
			h.click();
		});
		b.appendChild(c);
	}
	x[i].appendChild(b);
	a.addEventListener("click", function(e) {
		/*when the select box is clicked, close any other select boxes,
		and open/close the current select box:*/
		e.stopPropagation();
		closeAllSelect(this);
		this.nextSibling.classList.toggle("select-hide");
		this.classList.toggle("select-arrow-active");
	});
}

function closeAllSelect(elmnt) {
	/*a function that will close all select boxes in the document,
	except the current select box:*/
	var x, y, i, arrNo = [];
	x = document.getElementsByClassName("select-items");
	y = document.getElementsByClassName("select-selected");
	for (i = 0; i < y.length; i++) {
		if (elmnt == y[i]) {
			arrNo.push(i)
		}
		else {
			y[i].classList.remove("select-arrow-active");
		}
	}
	for (i = 0; i < x.length; i++) {
		if (arrNo.indexOf(i)) {
			x[i].classList.add("select-hide");
		}
	}
}

/*if the user clicks anywhere outside the select box,
then close all select boxes:*/
document.addEventListener("click", closeAllSelect);
.custom-select {
	width: 100%;
	position: relative;
	font-family: 'Quicksand', sans-serif;
	font-size: 1.2em;
}

.custom-select select {
	display: none;
}

.select-selected {
	border-radius: 13px;
	float: center;
	background: linear-gradient(to left, rgb(0,176,240), rgb(0,112,192));
	-webkit-user-select: none;      
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
}

.select-selected:before {
	background: white;
}

.select-selected:after {
	border-radius: 3px;
	float: right;
	position: relative;
	content: "";
	top: 10px;
	width: 0;
	height: 0;
	border: 6px solid transparent;
	border-color: #fff transparent transparent transparent;
}

.select-selected.select-arrow-active:after {
	border-color: transparent transparent #fff transparent;
	top: 2px;
}

.select-items div,.select-selected {
	transition: 0.2s;
	color: #ffffff;
	padding: 10px;
	cursor: pointer;
	user-select: none;
}

.select-items {
	margin-top: 3px;
	position: relative;
	background: rgb(13,13,13);
	top: 100%;
	left: 0;
	right: 0;
	z-index: 3;
	border-radius: 13px;
	overflow: hidden;
}

.select-hide {
	display: none;
}
.select-items div:hover, .same-as-selected {
	background: linear-gradient(to left, rgb(0,176,240), rgb(0,112,192));
	box-shadow: inset 0 0 16px rgba(0,0,0,0.4);
	-webkit-user-select: none;      
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
}

.border {
	box-shadow: 0 3px 8px rgba(0,0,0,0.3);
	width: auto;
	border-radius: 13px;
	background: linear-gradient(to left, rgb(0,176,240), rgb(0,112,192));
	padding: 3px;
	margin-bottom: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="border">
	<div class="custom-select">
		<select id="subject">
			<option value="0">Select a subject</option>
			<option value="biology">Biology</option>
			<option value="chemistry">Chemistry</option>
			<option value="physics">Physics</option>
			<option value="math">Maths</option>
			<option value="english">English</option>
			<option value="art">Art</option>
			<option value="re">RE</option>
			<option value="computing">Computing</option>
		</select>
	</div>
</div>

<div class="border">
<div class="custom-select">
  <select id="level">
    <option value="0">Select the qualification</option>
     <option value="GCSE">GCSE</option>
      <option value="asLevel">AS Level</option>
      <option value="aLevel">A Level</option>
  </select>
</div>
</div>

<div class="border">
<div class="custom-select">
	<select id="topic">
	  <option value="0">Select the topic</option>
	</select>
</div>
</div>

Dominique Fortin, here is your previous script with the closeAllSelect function 'activated' (not comment)

$(document).ready(function () {

	var mySubject = new myNameSpace.myDropDown('subject');
	var myLevel = new myNameSpace.myDropDown('level');
	var myTopic = new myNameSpace.myDropDown('topic');

	$("#level").change(function () {

		var val = $("#level").val();

		if (val === "GCSE") {

			myTopic.changeList([{"value":"0", "label":"Select the topic"}
			                   ,{"value":"test", "label":"item1: test 1"}
			                   ,{"value":"test2","label":"item1: test 2"}]);
		} else if (val === "asLevel") {

			myTopic.changeList([{"value":"0", "label":"Select the topic"}
			                   ,{"value":"test", "label":"item2: test 1"}
			                   ,{"value":"test2","label":"item2: test 2"}]);
		} else if (val === "aLevel") {

			myTopic.changeList([{"value":"0", "label":"Select the topic"}
			                   ,{"value":"test", "label":"item3: test 1"}
			                   ,{"value":"test2","label":"item3: test 2"}]);
		}
	});
  
});


(function module (global) {

global.myNameSpace = global.myNameSpace || {};
global.myNameSpace.myDropDown = myDropDown;

function myDropDown (id) {
	var formSelectJQ, lov, selectedLOVIndex;

	ctor();
	this.getValue = getValue;
	this.setValue = setValue;
	this.changeList = changeList;

	function ctor() {
		formSelectJQ= $('#'+id);
		$(formSelectJQ).css('display','none');

		$('<div id="'+id+'_myDropDown" class="border" style="display: none;">'
		   +'<div class="custom-select">'
		     +'<div class="select-selected"></div>'
		     +'<div class="select-items select-hide"></div>'
		   +'<div></div>').insertAfter(formSelectJQ);

		renderList();

		$('#'+id+'_myDropDown')
		  .on('click', selectOnClick)
		  .css('display','block');
	}

	function renderList () {
		readLOV();
 		var val = getValue();
		var list = lov.map((e) => {
			return '<div value="'+e.value+'" '
			  +(e.value === val ? 'class="same-as-selected"' : '')
			  +'>'+e.label+'</div>';
		});
		$('#'+id+'_myDropDown .select-items')
		  .empty()
		  .append(list.join(''));

		$('#'+id+'_myDropDown .select-items div')
		  .on('click', optionOnClick);

		setValue(val);
	}

	function readLOV () {
		lov = [];
		selectedLOVIndex = -1;
		$('#'+id+' option').each((i,e) => {
			lov.push({"value":e.value,"label":e.innerHTML});
			if (e.selected) {
				selectedLOVIndex = lov.length-1;
			}
		});
		selectedLOVIndex = (selectedLOVIndex < 0 ? 0 : selectedLOVIndex);
		if (lov.length <= 0) {
			lov = [{"value":'',"label":' '}];
		}
	}

	function writeLOV () {

		var list = lov.map((e) => {
			return '<option value="'+e.value+'">'+e.label+'</option>';
		});

		$('#'+id).empty().append(list.join(''));
	}

	function getValue () {
		readLOV();
		return lov[selectedLOVIndex].value;
	}

	function setValue (val) {
		$('#'+id+'_myDropDown .select-items .same-as-selected')
		  .removeClass("same-as-selected");
		formSelectJQ.prop('value', val);
		readLOV();
		if (lov.length > 0) {
			$('#'+id+'_myDropDown .select-selected').html(lov[selectedLOVIndex].label);
		} else {
			$('#'+id+'_myDropDown .select-selected').html(" ");
		}
		$('#'+id+'_myDropDown .select-items div[value="'+getValue()+'"]')
		  .addClass("same-as-selected");

		formSelectJQ.trigger('change');
	}

	function selectOnClick (event) {
		/*when the select box is clicked, close any other select boxes,
		and open/close the current select box:*/
		event.stopPropagation();
		$('#'+id+'_myDropDown .select-items').toggleClass("select-hide");
		$('#'+id+'_myDropDown .select-selected').toggleClass("select-arrow-active");
	}

	function optionOnClick (event) {
		/*when an item is clicked, update the original select box,
		and the selected item:*/
		setValue( $(event.target).attr('value') );
	}

	function changeList (listOfValues, defaultValue) {
		var val = getValue();
		lov = listOfValues;
		writeLOV();
		setValue(defaultValue || val);
		renderList();
	}
}

})(window);


function closeAllSelect(elmnt) {
	//a function that will close all select boxes in the document,
	//except the current select box:
	var x, y, i, arrNo = [];
	x = document.getElementsByClassName("select-items");
	y = document.getElementsByClassName("select-selected");
	for (i = 0; i < y.length; i++) {
		if (elmnt == y[i]) {
			arrNo.push(i)
		}
		else {
			y[i].classList.remove("select-arrow-active");
		}
	}
	for (i = 0; i < x.length; i++) {
		if (arrNo.indexOf(i)) {
			x[i].classList.add("select-hide");
		}
	}
}

//if the user clicks anywhere outside the select box,
//then close all select boxes:
document.addEventListener("click", closeAllSelect);

Upvotes: 0

Views: 662

Answers (3)

Abdul
Abdul

Reputation: 51

I figured out how to fix my problem. I used @Dominique Fortin's answer and edited it a little to factor in the selection of the first dropdown (subject). Everything else the same as Dominique's answer except the closeAllSelect function, the one in this solution works better than Dominique's current one because it still allows you to close the dropdown by clicking the blue title bar. It also allows you to open more than one dropwdown at the same time.

Here is the code:

$(document).ready(function () {

	var mySubject = new myNameSpace.myDropDown('subject');
	var myLevel = new myNameSpace.myDropDown('level');
	var myTopic = new myNameSpace.myDropDown('topic');

	$("#level").change(function () {

		var val = $("#level").val();
		var subVal = $("#subject").val();
		
		if (val === "0" || subVal === "0") {
			
			myTopic.changeList([{"value":"0", "label":"Select the topic"}]);
			
		}
		
		if (subVal === "biology") {
			if (val === "GCSE") {

				myTopic.changeList([{"value":"0", "label":"Select the topic"}
								   ,{"value":"1", "label":"Unit: B1"}
								   ,{"value":"2","label":"Unit: B2"}
								   ,{"value":"3","label":"Unit: B3"}
								   ,{"value":"4","label":"Unit: B4"}
								   ,{"value":"5","label":"Unit: B5"}
								   ,{"value":"6","label":"Unit: B6"}
								   ,{"value":"7","label":"Unit: B7"}
								   ,{"value":"8","label":"Unit: B8"}
								   ,{"value":"9","label":"Unit: B9"}]);
							   
			} else if (val === "asLevel") {

				myTopic.changeList([{"value":"0", "label":"Select the topic"}
								   ,{"value":"1", "label":"Biological molecules"}
								   ,{"value":"2","label":"Cells"}
								   ,{"value":"3","label":"Organisms and their environment"}
								   ,{"value":"4","label":"Genetics"}]);

			} else if (val === "aLevel") {

				myTopic.changeList([{"value":"0", "label":"Select the topic"}
								   ,{"value":"1", "label":"Energy transfers in and between organisms"}
								   ,{"value":"2","label":"Organisms: Internal and external environments"}
								   ,{"value":"3","label":"Genetics, populations, evolution and ecosystems"}
								   ,{"value":"4","label":"The control of gene expression"}]);
			}
		}
		
		if (subVal === "chemistry") {
			if (val === "GCSE") {

				myTopic.changeList([{"value":"0", "label":"Select the topic"}
								   ,{"value":"1", "label":"Unit: C1"}
								   ,{"value":"2","label":"Unit: C2"}
								   ,{"value":"3","label":"Unit: C3"}
								   ,{"value":"4","label":"Unit: C4"}
								   ,{"value":"5","label":"Unit: C5"}
								   ,{"value":"6","label":"Unit: C6"}
								   ,{"value":"7","label":"Unit: C7"}
								   ,{"value":"8","label":"Unit: C8"}
								   ,{"value":"9","label":"Unit: C9"}]);
							   
			} else if (val === "asLevel") {

				myTopic.changeList([{"value":"0", "label":"Select the topic"}]);

			} else if (val === "aLevel") {

				myTopic.changeList([{"value":"0", "label":"Select the topic"}]);

			}
		}
		
		if (subVal === "physics") {
			if (val === "GCSE") {

				myTopic.changeList([{"value":"0", "label":"Select the topic"}
								   ,{"value":"1", "label":"Unit: P1"}
								   ,{"value":"2","label":"Unit: P2"}
								   ,{"value":"3","label":"Unit: P3"}
								   ,{"value":"4","label":"Unit: P4"}
								   ,{"value":"5","label":"Unit: P5"}
								   ,{"value":"6","label":"Unit: P6"}
								   ,{"value":"7","label":"Unit: P7"}
								   ,{"value":"8","label":"Unit: P8"}
								   ,{"value":"9","label":"Unit: P9"}]);
							   
			} else if (val === "asLevel") {

				myTopic.changeList([{"value":"0", "label":"Select the topic"}]);

			} else if (val === "aLevel") {

				myTopic.changeList([{"value":"0", "label":"Select the topic"}]);

			}
		}
		
		if (subVal === "math") {
			if (val === "GCSE") {

				myTopic.changeList([{"value":"0", "label":"Select the topic"}]);
							   
			} else if (val === "asLevel") {

				myTopic.changeList([{"value":"0", "label":"Select the topic"}]);

			} else if (val === "aLevel") {

				myTopic.changeList([{"value":"0", "label":"Select the topic"}]);

			}
		}
	});
  
});


(function module (global) {

global.myNameSpace = global.myNameSpace || {};
global.myNameSpace.myDropDown = myDropDown;

function myDropDown (id) {
	var formSelectJQ, lov, selectedLOVIndex;

	ctor();
	this.getValue = getValue;
	this.setValue = setValue;
	this.changeList = changeList;

	function ctor() {
		formSelectJQ= $('#'+id);
		$(formSelectJQ).css('display','none');

		$('<div id="'+id+'_myDropDown" class="border" style="display: none;">'
		   +'<div class="custom-select">'
		     +'<div class="select-selected"></div>'
		     +'<div class="select-items select-hide"></div>'
		   +'<div></div>').insertAfter(formSelectJQ);

		renderList();

		$('#'+id+'_myDropDown')
		  .on('click', selectOnClick)
		  .css('display','block');
	}

	function renderList () {
		readLOV();
 		var val = getValue();
		var list = lov.map((e) => {
			return '<div value="'+e.value+'" '
			  +(e.value === val ? 'class="same-as-selected"' : '')
			  +'>'+e.label+'</div>';
		});
		$('#'+id+'_myDropDown .select-items')
		  .empty()
		  .append(list.join(''));

		$('#'+id+'_myDropDown .select-items div')
		  .on('click', optionOnClick);

		setValue(val);
	}

	function readLOV () {
		lov = [];
		selectedLOVIndex = -1;
		$('#'+id+' option').each((i,e) => {
			lov.push({"value":e.value,"label":e.innerHTML});
			if (e.selected) {
				selectedLOVIndex = lov.length-1;
			}
		});
		selectedLOVIndex = (selectedLOVIndex < 0 ? 0 : selectedLOVIndex);
		if (lov.length <= 0) {
			lov = [{"value":'',"label":' '}];
		}
	}

	function writeLOV () {

		var list = lov.map((e) => {
			return '<option value="'+e.value+'">'+e.label+'</option>';
		});

		$('#'+id).empty().append(list.join(''));
	}

	function getValue () {
		readLOV();
		return lov[selectedLOVIndex].value;
	}

	function setValue (val) {
		$('#'+id+'_myDropDown .select-items .same-as-selected')
		  .removeClass("same-as-selected");
		formSelectJQ.prop('value', val);
		readLOV();
		if (lov.length > 0) {
			$('#'+id+'_myDropDown .select-selected').html(lov[selectedLOVIndex].label);
		} else {
			$('#'+id+'_myDropDown .select-selected').html(" ");
		}
		$('#'+id+'_myDropDown .select-items div[value="'+getValue()+'"]')
		  .addClass("same-as-selected");

		formSelectJQ.trigger('change');
	}

	function selectOnClick (event) {
		/*when the select box is clicked, close any other select boxes,
		and open/close the current select box:*/
		event.stopPropagation();
		$('#'+id+'_myDropDown .select-items').toggleClass("select-hide");
		$('#'+id+'_myDropDown .select-selected').toggleClass("select-arrow-active");
	}

	function optionOnClick (event) {
		/*when an item is clicked, update the original select box,
		and the selected item:*/
		setValue( $(event.target).attr('value') );
	}

	function changeList (listOfValues, defaultValue) {
		var val = getValue();
		lov = listOfValues;
		writeLOV();
		setValue(defaultValue || val);
		renderList();
	}
}

})(window);


function closeAllSelect(elmnt) {
	//a function that will close all select boxes in the document,
	//except the current select box:
	var x, y, i, arrNo = [];
	x = document.getElementsByClassName("select-items");
	y = document.getElementsByClassName("select-selected");
	for (i = 0; i < y.length; i++) {
		if (elmnt == y[i]) {
			arrNo.push(i)
		}
		else {
			y[i].classList.remove("select-arrow-active");
		}
	}
	for (i = 0; i < x.length; i++) {
		if (arrNo.indexOf(i)) {
			x[i].classList.add("select-hide");
		}
	}
}

//if the user clicks anywhere outside the select box,
//then close all select boxes:
document.addEventListener("click", closeAllSelect);
.custom-select {
	width: 100%;
	position: relative;
	font-family: 'Quicksand', sans-serif;
	font-size: 1.1em;
}

.custom-select select {
	display: none;
}

.select-selected {
	border-radius: 13px;
	float: center;
	background: linear-gradient(to left, rgb(0,176,240), rgb(0,112,192));
	-webkit-user-select: none;      
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
}

.select-selected:before {
	background: white;
}

.select-selected:after {
	border-radius: 3px;
	float: right;
	position: relative;
	content: "";
	top: 10px;
	width: 0;
	height: 0;
	border: 6px solid transparent;
	border-color: #fff transparent transparent transparent;
}

.select-selected.select-arrow-active:after {
	border-color: transparent transparent #fff transparent;
	top: 2px;
}

.select-items div,.select-selected {
	transition: 0.2s;
	color: #ffffff;
	padding: 10px;
	cursor: pointer;
	user-select: none;
}

.select-items {
	margin-top: 3px;
	position: relative;
	background: rgb(13,13,13);
	top: 100%;
	left: 0;
	right: 0;
	z-index: 3;
	border-radius: 13px;
	overflow: hidden;
}

.select-hide {
	display: none;
}

.select-items div:hover, .same-as-selected {
	background: linear-gradient(to left, rgb(0,176,240), rgb(0,112,192));
	box-shadow: inset 0 0 16px rgba(0,0,0,0.4);
	-webkit-user-select: none;      
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="border">
	<div class="custom-select">
		<select id="subject">
			<option value="0">Select a subject</option>
			<option value="biology">Biology</option>
			<option value="chemistry">Chemistry</option>
			<option value="physics">Physics</option>
			<option value="math">Maths</option>
			<option value="english">English</option>
			<option value="art">Art</option>
			<option value="re">RE</option>
			<option value="computing">Computing</option>
		</select>
	</div>
</div>
<br/>
<br/>
<div class="border">
<div class="custom-select">
  <select id="level">
    <option value="0">Select the qualification</option>
     <option value="GCSE">GCSE</option>
      <option value="asLevel">AS Level</option>
      <option value="aLevel">A Level</option>
  </select>
</div>
</div>
<br/>
<br/>
<div class="border">
<div class="custom-select">
	<select id="topic">
	  <option value="0">Select the topic</option>
	</select>
</div>
</div>

I found a logical problem with this solution, if I select the qualification before the subject, the topics displayed will not update until I reselect the qualification. If anyone can point out the problem and/or give tips to make it more efficient, that would be helpful.

Thanks.

Upvotes: 0

Dominique Fortin
Dominique Fortin

Reputation: 2238

This is what meant by wrapring the logic into an object.

$(document).ready(function () {

	var mySubject = new myNameSpace.myDropDown('subject');
	var myLevel = new myNameSpace.myDropDown('level');
	var myTopic = new myNameSpace.myDropDown('topic');

	$("#level").change(function () {

		var val = $("#level").val();

		if (val === "GCSE") {

			myTopic.changeList([{"value":"0", "label":"Select the topic"}
			                   ,{"value":"test", "label":"item1: test 1"}
			                   ,{"value":"test2","label":"item1: test 2"}]);
		} else if (val === "asLevel") {

			myTopic.changeList([{"value":"0", "label":"Select the topic"}
			                   ,{"value":"test", "label":"item2: test 1"}
			                   ,{"value":"test2","label":"item2: test 2"}]);
		} else if (val === "aLevel") {

			myTopic.changeList([{"value":"0", "label":"Select the topic"}
			                   ,{"value":"test", "label":"item3: test 1"}
			                   ,{"value":"test2","label":"item3: test 2"}]);
		}
	});
  
});


(function module (global) {

global.myNameSpace = global.myNameSpace || {};
global.myNameSpace.myDropDown = myDropDown;

var listDropDown = [];

//if the user clicks anywhere outside the select box,
//then close all select boxes:
$(global.document).on("click", function () {closeAllSelect();});

function myDropDown (id) {
	var formSelectJQ, lov, selectedLOVIndex;
  var self = this;
	ctor();
	self.getValue = getValue;
	self.setValue = setValue;
	self.changeList = changeList;
	self.hideOptions = hideOptions;

	function ctor() {
		formSelectJQ= $('#'+id);
		$(formSelectJQ).css('display','none');

		$('<div id="'+id+'_myDropDown" class="border" style="display: none;">'
		   +'<div class="custom-select">'
		     +'<div class="select-selected"></div>'
		     +'<div class="select-items select-hide"></div>'
		   +'<div></div>').insertAfter(formSelectJQ);

		renderList();

		$('#'+id+'_myDropDown')
		  .on('click', selectOnClick)
		  .css('display','block');

		listDropDown.push(self);
	}

	function renderList () {
		readLOV();
 		var val = getValue();
		var list = lov.map((e) => {
			return '<div value="'+e.value+'" '
			  +(e.value === val ? 'class="same-as-selected"' : '')
			  +'>'+e.label+'</div>';
		});
		$('#'+id+'_myDropDown .select-items')
		  .empty()
		  .append(list.join(''));

		$('#'+id+'_myDropDown .select-items div')
		  .on('click', optionOnClick);

		setValue(val);
	}

	function readLOV () {
		lov = [];
		selectedLOVIndex = -1;
		$('#'+id+' option').each((i,e) => {
			lov.push({"value":e.value,"label":e.innerHTML});
			if (e.selected) {
				selectedLOVIndex = lov.length-1;
			}
		});
		selectedLOVIndex = (selectedLOVIndex < 0 ? 0 : selectedLOVIndex);
		if (lov.length <= 0) {
			lov = [{"value":'',"label":' '}];
		}
	}

	function writeLOV () {

		var list = lov.map((e) => {
			return '<option value="'+e.value+'">'+e.label+'</option>';
		});

		$('#'+id).empty().append(list.join(''));
	}

	function getValue () {
		readLOV();
		return lov[selectedLOVIndex].value;
	}

	function setValue (val) {
		$('#'+id+'_myDropDown .select-items .same-as-selected')
		  .removeClass("same-as-selected");
		formSelectJQ.prop('value', val);
		readLOV();
		if (lov.length > 0) {
			$('#'+id+'_myDropDown .select-selected').html(lov[selectedLOVIndex].label);
		} else {
			$('#'+id+'_myDropDown .select-selected').html(" ");
		}
		$('#'+id+'_myDropDown .select-items div[value="'+getValue()+'"]')
		  .addClass("same-as-selected");

		formSelectJQ.trigger('change');
	}

	function selectOnClick (event) {
		/*when the select box is clicked, close any other select boxes,
		and open/close the current select box:*/
		event.stopPropagation();
		closeAllSelect();
		$('#'+id+'_myDropDown .select-items').toggleClass("select-hide");
		$('#'+id+'_myDropDown .select-selected').toggleClass("select-arrow-active");
	}

	function optionOnClick (event) {
		/*when an item is clicked, update the original select box,
		and the selected item:*/
		event.stopPropagation();
		setValue( $(event.target).attr('value') );
		hideOptions();
	}

	function changeList (listOfValues, defaultValue) {
		var val = getValue();
		lov = listOfValues;
		writeLOV();
		setValue(defaultValue || val);
		renderList();
	}
  
	function hideOptions () {

		var itemList = $('#'+id+'_myDropDown .select-items');
		
		if ( ! itemList.hasClass("select-hide")) {
			itemList.addClass("select-hide");
		}
	}
}

function closeAllSelect() {
	//a function that will close all select boxes in the document,
	//except the current select box:
	listDropDown.forEach((d) => {
		d.hideOptions();
	});
}

})(window);
.custom-select {
	width: 100%;
	position: relative;
	font-family: 'Quicksand', sans-serif;
	font-size: 1.2em;
}

.custom-select select {
	display: none;
}

.select-selected {
	border-radius: 13px;
	float: center;
	background: linear-gradient(to left, rgb(0,176,240), rgb(0,112,192));
	-webkit-user-select: none;      
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
}

.select-selected:before {
	background: white;
}

.select-selected:after {
	border-radius: 3px;
	float: right;
	position: relative;
	content: "";
	top: 10px;
	width: 0;
	height: 0;
	border: 6px solid transparent;
	border-color: #fff transparent transparent transparent;
}

.select-selected.select-arrow-active:after {
	border-color: transparent transparent #fff transparent;
	top: 2px;
}

.select-items div,.select-selected {
	transition: 0.2s;
	color: #ffffff;
	padding: 10px;
	cursor: pointer;
	user-select: none;
}

.select-items {
	margin-top: 3px;
	position: relative;
	background: rgb(13,13,13);
	top: 100%;
	left: 0;
	right: 0;
	z-index: 3;
	border-radius: 13px;
	overflow: hidden;
}

.select-hide {
	display: none;
}
.select-items div:hover, .same-as-selected {
	background: linear-gradient(to left, rgb(0,176,240), rgb(0,112,192));
	box-shadow: inset 0 0 16px rgba(0,0,0,0.4);
	-webkit-user-select: none;      
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
}

.border {
	box-shadow: 0 3px 8px rgba(0,0,0,0.3);
	width: auto;
	border-radius: 13px;
	background: linear-gradient(to left, rgb(0,176,240), rgb(0,112,192));
	padding: 3px;
	margin-bottom: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<select id="subject">
	<option value="0">Select a subject</option>
	<option value="biology">Biology</option>
	<option value="chemistry">Chemistry</option>
	<option value="physics">Physics</option>
	<option value="math">Maths</option>
	<option value="english">English</option>
	<option value="art">Art</option>
	<option value="re">RE</option>
	<option value="computing">Computing</option>
</select>

<select id="level">
	<option value="0">Select the qualification</option>
	<option value="GCSE">GCSE</option>
	<option value="asLevel">AS Level</option>
	<option value="aLevel">A Level</option>
</select>

<select id="topic">
	<option value="0">Select the topic</option>
</select>

Upvotes: 2

ecg8
ecg8

Reputation: 1392

Here is how I would do it. I'd put the objects into a separate .js file and call it with the tag. I stripped out your styling and half of your options just to keep my answer concise, but the principle is scalable.

Store each set of possibilities as an array and use an event listener to empty out and then refill your dropdowns each time the previous dropdown has been selected.

var levelOpts = {
	"1": [
		["1","Bio specific option #1"],["2","Bio specific option #2"],["3","Bio specific option #3"]
	],
	"2": [
		["4","Chem specific option #1"],["5","Chem specific option #2"],["6","Chem specific option #3"]
	],
  "3": [
		["7","Phys specific option #1"],["8","Phys specific option #2"],["9","Phys specific option #3"]
	],
	"4": [
		["10","Math specific option #1"],["11","Math specific option #2"],["12","Math specific option #3"]
	]
};
var topicOpts = {
	"1": [
		["0","Choose one"],["1","Bio specific suboption #1a"],["2","Bio specific suboption #1b"],["3","Bio specific suboption #1c"]
	],
	"2": [
		["0","Choose one"],["1","Bio specific suboption #2a"],["2","Bio specific suboption #2b"],["3","Bio specific suboption #2c"]
	],
  "3": [
		["0","Choose one"],["1","Bio specific suboption #3a"],["2","Bio specific suboption #3b"],["3","Bio specific suboption #3c"]
	],
	"4": [
		["0","Choose one"],["1","Chem specific suboption #1a"],["2","Chem specific suboption #1b"],["3","Chem specific suboption #1c"]
	],
	"5": [
		["0","Choose one"],["1","Chem specific suboption #2a"],["2","Chem specific suboption #2b"],["3","Chem specific suboption #2c"]
	],
  "6": [
		["0","Choose one"],["1","Chem specific suboption #3a"],["2","Chem specific suboption #3b"],["3","Chem specific suboption #3c"]
	],
  "7": [
		["0","Choose one"],["1","Phys specific suboption #1a"],["2","Phys specific suboption #1b"],["3","Phys specific suboption #1c"]
	],
	"8": [
		["0","Choose one"],["1","Phys specific suboption #2a"],["2","Phys specific suboption #2b"],["3","Phys specific suboption #2c"]
	],
  "9": [
		["0","Choose one"],["1","Phys specific suboption #3a"],["2","Phys specific suboption #3b"],["3","Phys specific suboption #3c"]
	],
	"10": [
		["0","Choose one"],["1","Math specific suboption #1a"],["2","Math specific suboption #1b"],["3","Math specific suboption #1c"]
	],
	"11": [
		["0","Choose one"],["1","Math specific suboption #2a"],["2","Math specific suboption #2b"],["3","Math specific suboption #2c"]
	],
  "12": [
		["0","Choose one"],["1","Math specific suboption #3a"],["2","Math specific suboption #3b"],["3","Math specific suboption #3c"]
	],
};
var subject = document.getElementById("subject");
var level = document.getElementById("level");
var topic = document.getElementById("topic");
subject.addEventListener("change", LevelFill);
level.addEventListener("change", TopicFill);
function LevelFill() {
	var opts = [];
  while (level.firstChild) {
  	level.firstChild.remove();
  }
  switch(subject.value) {
  	case "1":
    	opts = levelOpts["1"];
			level.style.display = "block";
      break;
    case "2":
    	opts = levelOpts["2"];
			level.style.display = "block";
			break;
		case "3":
			opts = levelOpts["3"];
			level.style.display = "block";
			break;
		case "4":
			opts = levelOpts["4"];
			level.style.display = "block";
			break;
		default:
			opts = [];
			level.style.display = "none";
	}
	for (var i = 0; i < opts.length; i++) {
		var option = document.createElement("option");
		option.text = opts[i][1];
		option.value = opts[i][0];
		level.appendChild(option);
	}
	topic.style.display = "none";
}
function TopicFill() {
	var opts = [];
	while (topic.firstChild) {
		topic.firstChild.remove();
	}
	switch(level.value) {
		case "1":
			opts = topicOpts["1"];
			topic.style.display = "block";
			break;
		case "2":
			opts = topicOpts["2"];
			topic.style.display = "block";
			break;
		case "3":
			opts = topicOpts["3"];
			topic.style.display = "block";
			break;
    case "4":
			opts = topicOpts["4"];
			topic.style.display = "block";
			break;
		case "5":
			opts = topicOpts["5"];
			topic.style.display = "block";
			break;
		case "6":
			opts = topicOpts["6"];
			topic.style.display = "block";
			break;
    case "7":
			opts = topicOpts["7"];
			topic.style.display = "block";
			break;
		case "8":
			opts = topicOpts["8"];
			topic.style.display = "block";
			break;
		case "9":
			opts = topicOpts["9"];
			topic.style.display = "block";
			break;
    case "10":
			opts = topicOpts["10"];
			topic.style.display = "block";
			break;
		case "11":
			opts = topicOpts["11"];
			topic.style.display = "block";
			break;
		case "12":
			opts = topicOpts["12"];
			topic.style.display = "block";
			break;
		default:
			opts = [];
			level.style.display = "none";
			topic.style.display = "none";
	}
	for (var i = 0; i < opts.length; i++) {
		var option = document.createElement("option");
		option.text = opts[i][1];
		option.value = opts[i][0];
		topic.appendChild(option);
	}
	topic.style.display = "block";
}
#level, #topic {
  display: none
}
<div class="border">
	<div class="custom-select">
		<select id="subject">
			<option value="0">Select a subject</option>
			<option value="1">Biology</option>
			<option value="2">Chemistry</option>
			<option value="3">Physics</option>
			<option value="4">Maths</option>
		</select>
	</div>
</div>
<div class="border">
  <div class="custom-select">
    <select id="level"></select>
  </div>
</div>
<div class="border">
  <div class="custom-select">
	  <select id="topic"></select>
  </div>
</div>

Upvotes: 1

Related Questions