My goal is to remove options from a select input ("class") based on their classList depending on the selection made in a previous select input ("class-type"). Strangely enough, some options ARE removed (as they should be) when enableClassSelect is called, but not all options which don't have the necessary class are moved at once. Currently the "class-list" needs to be changed ~7 times before ALL options are removed (this should not happen!).
See code below - I've reviewed it several times and attempted some debugging to no avail. console.log(classSelect.length); prints "46", which is correct, so each option element should be checked in the iteration.
function enableClassSelect(classType) {
let classSelect = document.getElementById("class");
console.log("Length: " + classSelect.length);
for (i = 0; i < classSelect.length; i++) {
if (!classSelect.options[i].classList.contains(classType)) {
classSelect.remove(i);
}
}
classSelect.disabled = false;
classSelect.classList.remove("disabled-select");
let classDefaultOption = document.getElementById("class-default-option");
classDefaultOption.innerHTML = " -- select a class -- ";
return;
}
<select onchange="javascript:enableClassSelect(this.options[this.selectedIndex].value);" class="reg" id="class-type" name="class-type" required>
<option disabled selected value> -- select a class type -- </option>
<option value="Magician">Magician</option>
<option value="Thief">Thief</option>
<option value="Warrior">Warrior</option>
<option value="Bowman">Bowman</option>
<option value="Pirate">Pirate</option>
</select>
<select class="disabled-select reg" id="class" name="class" disabled required>
<option class="Magician Thief Warrior Bowman Pirate" id="class-default-option" disabled selected value></option>
<!-- Magicians -->
<option class="Magician" value="Battle Mage">Battle Mage</option>
<option class="Magician" value="Beast Tamer">Beast Tamer</option>
<option class="Magician" value="Blaze Wizard">Blaze Wizard</option>
<option class="Magician" value="Evan">Evan</option>
<option class="Magician" value="Kanna">Kanna</option>
<option class="Magician" value="Luminous">Luminous</option>
<option class="Magician" value="Bishop">Bishop</option>
<option class="Magician" value="Ice/Lightning Mage">Ice/Lightning Mage</option>
<option class="Magician" value="Fire/Poison Mage">Fire/Poison Mage</option>
<option class="Magician" value="Kinesis">Kinesis</option>
<option class="Magician" value="Illium">Illium</option>
<!-- Thieves -->
<option class="Thief" value="Dual Blade">Dual Blade</option>
<option class="Thief" value="Night Walker">Night Walker</option>
<option class="Thief" value="Phantom">Phantom</option>
<option class="Thief" value="Shadower">Shadower</option>
<option class="Thief" value="Night Lord">Night Lord</option>
<option class="Thief" value="Xenon">Xenon</option>
<option class="Thief" value="Cadena">Cadena</option>
<!-- Warriors -->
<option class="Warrior" value="Aran">Aran</option>
<option class="Warrior" value="Dawn Warrior">Dawn Warrior</option>
<option class="Warrior" value="Demon Avenger">Demon Avenger</option>
<option class="Warrior" value="Demon Slayer">Demon Slayer</option>
<option class="Warrior" value="Hayato">Hayato</option>
<option class="Warrior" value="Kaiser">Kaiser</option>
<option class="Warrior" value="Mihile">Mihile</option>
<option class="Warrior" value="Dark Knight">Dark Knight</option>
<option class="Warrior" value="Hero">Hero</option>
<option class="Warrior" value="Paladin">Paladin</option>
<option class="Warrior" value="Zero">Zero</option>
<option class="Warrior" value="Blaster">Blaster</option>
<!-- Bowmen -->
<option class="Bowman" value="Marksman">Marksman</option>
<option class="Bowman" value="Bowmaster">Bowmaster</option>
<option class="Bowman" value="Wild Hunter">Wild Hunter</option>
<option class="Bowman" value="Wind Archer">Wind Archer</option>
<option class="Bowman" value="Mercedes">Mercedes</option>
<option class="Bowman" value="Pathfinder">Pathfinder</option>
<!-- Pirates -->
<option class="Pirate" value="Angelic Buster">Angelic Buster</option>
<option class="Pirate" value="Cannoneer">Cannoneer</option>
<option class="Pirate" value="Jett">Jett</option>
<option class="Pirate" value="Mechanic">Mechanic</option>
<option class="Pirate" value="Buccaneer">Buccaneer</option>
<option class="Pirate" value="Corsair">Corsair</option>
<option class="Pirate" value="Shade">Shade</option>
<option class="Pirate" value="Thunder Breaker">Thunder Breaker</option>
<option class="Pirate" value="Ark">Ark</option>
</select>
Expected: select a class type (e.g. "Warrior" and the "class" element becomes enabled and displays the proper classes.
Actual: "class" options are removed seemingly at random over ~6 calls to enableClassSelect until the select element is empty.
This is one way of doing it, not sure if it would be the fastest way, but it does work.
Essentially I removed all of the options from the HTML, and instead I am only adding on the correct options for that class type.
function enableClassSelect(classType) {
// Make sure the names of these are the same as the value for the options in the class-type select
const magicians = ["Battle Mage", "Beast Tamer", "Blaze Wizard"];
const thieves = ["Dual Blade", "Night Walker", "Phantom"];
// Make sure theses are both in the same order
const classTypesNames = ["magicians", "thieves"];
const classTypes = [magicians, thieves];
let classSelect = document.getElementById("class");
// Clear the options from the classSelect, except for the default option
var length = classSelect.options.length;
if (length > 1) {
for (i = classSelect.options.length - 1; i > 0; i--) {
classSelect.remove(i);
}
}
// Check the classtype they selected, and get the list of classes for that classType
for (i = 0; i < classTypes.length; i++) {
if (classType === classTypesNames[i]) {
var classes = classTypes[i];
for (j = 0; j < classes.length; j++) {
// Create an option element with the class as the value
var opt = document.createElement("option");
opt.value = classes[j];
opt.innerHTML = classes[j];
classSelect.appendChild(opt);
}
}
}
classSelect.disabled = false;
classSelect.classList.remove("disabled-select");
return;
}
<select onchange="javascript:enableClassSelect(this.options[this.selectedIndex].value);" class="reg" id="class-type" name="class-type" required>
<option disabled selected value> -- select a class type -- </option>
<option value="magicians">Magician</option>
<option value="thieves">Thief</option>
</select>
<select class="disabled-select reg" id="class" name="class" disabled required>
<option id="class-default-option" disabled selected value> -- select a class -- </option>
</select>
There needs to be a list for each classType that contains the classes for that classType.
const warriors = ["Aran", "Dawn Warrior", "Demon Avenger"];
Then add that classType to the list of classTypes:
const classTypesNames = ["magicians", "thieves", "warriors"];
const classTypes = [magicians, thieves, warriors];
This part "resets" the options for the classSelect so that only the default one remains:
var length = classSelect.options.length;
if (length > 1) {
for (i = classSelect.options.length - 1; i > 0; i--) {
classSelect.remove(i);
}
}
From there the next section checks the value of the classType the user selected, and gets the list of classes for that classType, and creates option elements and appends them to the classSelect:
for (i = 0; i < classTypes.length; i++) {
if (classType === classTypesNames[i]) {
var classes = classTypes[i];
for (j = 0; j < classes.length; j++) {
// Create an option element with the class as the value
var opt = document.createElement("option");
opt.value = classes[j];
opt.innerHTML = classes[j];
classSelect.appendChild(opt);
}
}
}
Related
how to make two level SELECT OPTION category and subcategory - all level must required
<select id="category" required>
<option value="">select model type</option>
<option class="Volvo" value="1">Volvo</option>
<option class="Saab" value="2">Saab</option>
<option class="Opel" value="3">Opel</option>
<option class="Audi" value="4">Audi</option>
</select>
<select id="subcategory" required>
<optgroup class="Volvo">
<option value="">select model type</option>
<option value="44">XC60</option>
<option value="55">XC90</option>
</optgroup>
<optgroup class="Saab">
<option value="">select model type</option>
<option value="66">Saab 9XX</option>
<option value="77">Saab Aero-X</option>
</optgroup>
<optgroup class="Opel">
<option value="">select model type</option>
<option value="88">Corsa A</option>
<option value="99">Corsa B</option>
</optgroup>
<optgroup class="Audi">
<option value="">select model type</option>
<option value="616">Audi A4</option>
<option value="717">Audi A8</option>
</optgroup>
</select>
i need samthing like this
with javascript or jquery ?
i don't now how works javascript and i need help thanks
Here's a plan vanilla JS approach. The magic of showing the red validation comes from the combination of Javascript and CSS.
First get the values of the DOM elements by document.getElementById().
Get the values of the <option> tags.
Check if the .value of the <option> tag is not not the default one.
If it is, the add the CSS class to the <label> which shows the Required text and add the CSS class to add a border to the <option> tag.
If it is not the default value, then remove the CSS classes from the <label> and <option>
var categoryChanged = function() {
var category = document.getElementById('category');
var subcategory = document.getElementById('subcategory');
var option = category[category.selectedIndex].value;
switch (option) {
case "1":
subcategory.children[0].style.display = "block";
subcategory.children[1].style.display = "none";
subcategory.children[2].style.display = "none";
subcategory.children[3].style.display = "none";
break;
case "2":
subcategory.children[0].style.display = "none";
subcategory.children[1].style.display = "block";
subcategory.children[2].style.display = "none";
subcategory.children[3].style.display = "none";
break;
case "3":
subcategory.children[0].style.display = "none";
subcategory.children[1].style.display = "none";
subcategory.children[2].style.display = "block";
subcategory.children[3].style.display = "none";
break;
case "4":
subcategory.children[0].style.display = "none";
subcategory.children[1].style.display = "none";
subcategory.children[2].style.display = "none";
subcategory.children[3].style.display = "block";
break;
}
}
var validateCategories = function() {
// Step 1
var category = document.getElementById('category');
var subcategory = document.getElementById('subcategory');
var categoryLabel = document.getElementById('categoryLabel');
var subcategoryLabel = document.getElementById('subcategoryLabel');
// Step 2
var categoryText = category[category.selectedIndex].text; // Don't need this, only shown to show you how to get the text
var categoryValue = category[category.selectedIndex].value;
var subcategoryText = subcategory[subcategory.selectedIndex].text; // Don't need this, only shown to show you how to get the text
var subcategoryValue = subcategory[subcategory.selectedIndex].value;
// Step 3 for category <option>
if (categoryValue === "") {
// Step 4 for category <option>
category.classList.add('not-valid');
categoryLabel.classList.remove('validated-label');
categoryLabel.classList.add('required-label');
} else {
// Step 5 for category <option>
category.classList.remove('not-valid');
categoryLabel.classList.remove('required-label');
categoryLabel.classList.add('validated-label');
}
// Step 3 for subcategory <option>
if (subcategoryValue === "") {
// Step 4 for subcategory <option>
subcategory.classList.add('not-valid');
subcategoryLabel.classList.remove('validated-label');
subcategoryLabel.classList.add('required-label');
} else {
// Step 5 for subcategory <option>
subcategory.classList.remove('not-valid');
subcategoryLabel.classList.remove('required-label');
subcategoryLabel.classList.add('validated-label');
}
};
.not-valid {
border: 5px solid red;
}
.validated-label {
display: none;
}
.required-label {
color: red;
display: visible;
}
<label for="category" id="categoryLabel" class="validated-label">Required</label>
<select id="category" onchange="categoryChanged()" required>
<option value="">select model type</option>
<option class="Volvo" value="1">Volvo</option>
<option class="Saab" value="2">Saab</option>
<option class="Opel" value="3">Opel</option>
<option class="Audi" value="4">Audi</option>
</select>
<label for="subcategory" id="subcategoryLabel" class="validated-label">Required</label>
<select id="subcategory" required>
<optgroup class="Volvo" hidden>
<option value="">select model type</option>
<option value="44">XC60</option>
<option value="55">XC90</option>
</optgroup>
<optgroup class="Saab" hidden>
<option value="">select model type</option>
<option value="66">Saab 9XX</option>
<option value="77">Saab Aero-X</option>
</optgroup>
<optgroup class="Opel" hidden>
<option value="">select model type</option>
<option value="88">Corsa A</option>
<option value="99">Corsa B</option>
</optgroup>
<optgroup class="Audi" hidden>
<option value="">select model type</option>
<option value="616">Audi A4</option>
<option value="717">Audi A8</option>
</optgroup>
</select>
<button onclick="validateCategories()">Validate</button>
Currently I have a function I created that removes some options from a select menu based on a value passed from another select. I want to revert back to normal each time the function is called (add all the original options back)
HTML
<select id="Current-Tier" onchange="removetier();" class="form-control boosting-select">
<option value="100">Bronze</option>
<option value="200">Silver</option>
<option value="300">Gold</option>
<option value="400">Platinum</option>
<option value="500">Diamond</option>
</select>
<select id="Desired-Tier" class="form-control boosting-select">
<option value="100">Bronze</option>
<option value="200">Silver</option>
<option value="300">Gold</option>
<option value="400">Platinum</option>
<option value="500">Diamond</option>
</select>
JS
function removetier(){
var currentTierValue = document.getElementById("Current-Tier");
var current = currentTierValue.options[currentTierValue.selectedIndex].value;
var desiredDivisionValue = document.getElementById("Desired-Tier");
for(var i=0;i<desiredDivisionValue.length;i++){
if(desiredDivisionValue[i].value < current){
desiredDivisionValue.remove(desiredDivisionValue[i]);
}
}
Update_Desired_Rank_image();
}
Have you considered adding the hidden attribute rather than deleting them?
Then the next time you receive a request, you can go through the list programmatically and remove the hidden attribute from each option.
An example of the hidden label, BTW, is
<select id="Desired-Tier" class="form-control boosting-select">
<option value="100">Bronze</option>
<option value="200">Silver</option>
<option value="300">Gold</option>
<option value="400">Platinum</option>
<option value="500" hidden>Diamond</option>
</select>
If you run it you will see that Diamond is hidden. This way you always have access to all your options.
You can easily iterate over the select input and either store the removed items in an array or leverage the hidden attribute on the option tag:
Fiddle: https://jsfiddle.net/gLwwmh82/2/
HTML
<select id="mySelect">
<option value="">Select...</option>
<option value="test1">Test1</option>
<option value="test2">Test2</option>
<option value="test3">Test3</option>
<option value="test4">Test4</option>
<option value="test5">Test5</option>
<option value="test6">Test6</option>
</select>
<button id="btnRemove" onclick="remove()">Remove Half of Entries</button>
<button id="btnReset" onclick="reset()">Reset</button>
JS
function reset() {
var select = document.getElementById('mySelect');
var options = select.querySelectorAll('option');
for (var i = 0; i < options.length; i++) {
options[i].removeAttribute('hidden');
}
}
function remove() {
var select = document.getElementById('mySelect');
select.value = "";
var entries = select.querySelectorAll('option');
for (var i = 1; i < 5; i++) {
// Wrap the below line in your logic to know what to delete/not to delete
entries[i].setAttribute('hidden', true);
}
}
I'm doing 'Calendar Event' app. After choosing the day of the week, times and short description I can click on 'Add Event' button and add a row to table (not visible), but I don't know, how to add a cell to it.
I was trying to add cell, by grabbing '.event' class var eventContent = document.querySelectorAll('.event'); , and use appendChild() method,
for(var j = 0; j < eventContent.length; j +=1){
eventContent[j].appendChild(tdElement1);
eventContent[j].appendChild(tdElement2);
}
but the cells are not inserting as should be, after changing the day of the week.
There is the HTML code:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Daily Programmer Challenge #0004 | Events Calendar</title>
<link rel="stylesheet" href="css/0004_eventsCalendar.css">
</head>
<body>
<div id="container">
<div class="toolbarMenu">
<div class="toolLeft">
<div class="leftButtons">
<button type="button"><span><</span></button>
<button type="button"><span>></span></button>
</div>
<button type="button">today</button>
</div>
<div class="toolCenter">
<h2>Test</h2>
</div>
</div>
<hr>
<div id="content">
<div id="leftSide">
<table>
<tbody>
<tr class="eventHead">
<td class="dayHead" colspan="2"><span class="day">Monday</span><span class="dayDate"></span></td>
</tr>
<tr class="eventHead">
<td class="dayHead" colspan="2"><span class="day">Tuesday</span><span class="dayDate"></span></td>
</tr>
<tr class="eventHead">
<td class="dayHead" colspan="2"><span class="day">Wednesday</span><span class="dayDate"></span></td>
</tr>
<tr class="eventHead">
<td class="dayHead" colspan="2"><span class="day">Thursday</span><span class="dayDate"></span></td>
</tr>
<tr class="eventHead">
<td class="dayHead" colspan="2"><span class="day">Friday</span><span class="dayDate"></span></td>
</tr>
<tr class="eventHead">
<td class="dayHead" colspan="2"><span class="day">Saturday</span><span class="dayDate"></span></td>
</tr>
<tr class="eventHead">
<td class="dayHead" colspan="2"><span class="day">Sunday</span><span class="dayDate"></span></td>
</tr>
<!--
<tr class="event">
<td class="time"></td>
<td class="desc"></td>
</tr>
-->
</tbody>
</table>
<p><i><strong>Note:</strong> After adding event into table, you can EDIT it!</i></p>
</div>
<div id="rigthSide">
<h3>Calendar panel</h3>
<form id="calendarCMS" name = "calendarCMS" action="#">
<fieldset>
<select name="dayOfWeek" id="dayOfWeek">
<option value="monday">Monday</option>
<option value="tuesday">Tuesday</option>
<option value="wednesday">Wednesday</option>
<option value="thursday">Thursday</option>
<option value="friday">Friday</option>
<option value="saturday">Saturday</option>
<option value="sunday">Sunday</option>
</select>
<div id="fromToTime">
<span>from:</span>
<select name="fromTime" id="fromTime">
<option value="07.00am">07:00am</option>
<option value="07.15am">07:15am</option>
<option value="07.30am">07:30am</option>
<option value="07.45am">07:45am</option>
<option value="08.00am">08:00am</option>
<option value="08.15am">08:15am</option>
<option value="08.30am">08:30am</option>
<option value="08.45am">08:45am</option>
<option value="09.00am">09:00am</option>
<option value="09.15am">09:15am</option>
<option value="09.30am">09:30am</option>
<option value="09.45am">09:45am</option>
<option value="10.00am">10:00am</option>
<option value="10.15am">10:15am</option>
<option value="10.30am">10:30am</option>
<option value="10.45am">10:45am</option>
<option value="11.00am">11:00am</option>
<option value="11.15am">11:15am</option>
<option value="11.30am">11:30am</option>
<option value="11.45am">11:45am</option>
<option value="12.00am">12:00am</option>
<option value="12.15am">12:15am</option>
<option value="12.30am">12:30am</option>
<option value="12.45am">12:45am</option>
<option value="13.00pm">13:00pm</option>
<option value="13.15pm">13:15pm</option>
<option value="13.30pm">13:30pm</option>
<option value="13.45pm">13:45pm</option>
<option value="14.00pm">14:00pm</option>
<option value="14.15pm">14:15pm</option>
<option value="14.30pm">14:30pm</option>
<option value="14.45pm">14:45pm</option>
<option value="15.00pm">15:00pm</option>
<option value="15.15pm">15:15pm</option>
<option value="15.30pm">15:30pm</option>
<option value="15.45pm">15:45pm</option>
<option value="16.00pm">16:00pm</option>
<option value="16.15pm">16:15pm</option>
<option value="16.30pm">16:30pm</option>
<option value="16.45pm">16:45pm</option>
<option value="17.00pm">17:00pm</option>
<option value="17.15pm">17:15pm</option>
<option value="17.30pm">17:30pm</option>
<option value="17.45pm">17:45pm</option>
<option value="18.00pm">18:00pm</option>
<option value="18.15pm">18:15pm</option>
<option value="18.30pm">18:30pm</option>
<option value="18.45pm">18:45pm</option>
<option value="19.00pm">19:00pm</option>
<option value="19.15pm">19:15pm</option>
<option value="19.30pm">19:30pm</option>
<option value="19.45pm">19:45pm</option>
<option value="20.00pm">20:00pm</option>
<option value="20.15pm">20:15pm</option>
<option value="20.30pm">20:30pm</option>
<option value="20.45pm">20:45pm</option>
<option value="21.00pm">21:00pm</option>
<option value="21.15pm">21:15pm</option>
<option value="21.30pm">21:30pm</option>
<option value="21.45pm">21:45pm</option>
<option value="22.00pm">22:00pm</option>
<option value="22.15pm">22:15pm</option>
<option value="22.30pm">22:30pm</option>
<option value="22.45pm">22:45pm</option>
<option value="23.00pm">23:00pm</option>
<option value="23.15pm">23:15pm</option>
<option value="23.30pm">23:30pm</option>
<option value="23.45pm">23:45pm</option>
<option value="00.00am">00:00am</option>
<option value="00.15am">00:15am</option>
<option value="00.30am">00:30am</option>
<option value="00.45am">00:45am</option>
<option value="01.00am">01:00am</option>
<option value="01.15am">01:15am</option>
<option value="01.30am">01:30am</option>
<option value="01.45am">01:45am</option>
<option value="02.00am">02:00am</option>
<option value="02.15am">02:15am</option>
<option value="02.30am">02:30am</option>
<option value="02.45am">02:45am</option>
<option value="03.00am">03:00am</option>
<option value="03.15am">03:15am</option>
<option value="03.30am">03:30am</option>
<option value="03.45am">03:45am</option>
<option value="04.00am">04:00am</option>
<option value="04.15am">04:15am</option>
<option value="04.30am">04:30am</option>
<option value="04.45am">04:45am</option>
<option value="05.00am">05:00am</option>
<option value="05.15am">05:15am</option>
<option value="05.30am">05:30am</option>
<option value="05.45am">05:45am</option>
<option value="06.00am">06:00am</option>
<option value="06.15am">06:15am</option>
<option value="06.30am">06:30am</option>
<option value="06.45am">06:45am</option>
</select>
<span>to:</span>
<select name="toTime" id="toTime">
<option value="07.00am">07:00am</option>
<option value="07.15am">07:15am</option>
<option value="07.30am">07:30am</option>
<option value="07.45am">07:45am</option>
<option value="08.00am">08:00am</option>
<option value="08.15am">08:15am</option>
<option value="08.30am">08:30am</option>
<option value="08.45am">08:45am</option>
<option value="09.00am">09:00am</option>
<option value="09.15am">09:15am</option>
<option value="09.30am">09:30am</option>
<option value="09.45am">09:45am</option>
<option value="10.00am">10:00am</option>
<option value="10.15am">10:15am</option>
<option value="10.30am">10:30am</option>
<option value="10.45am">10:45am</option>
<option value="11.00am">11:00am</option>
<option value="11.15am">11:15am</option>
<option value="11.30am">11:30am</option>
<option value="11.45am">11:45am</option>
<option value="12.00am">12:00am</option>
<option value="12.15am">12:15am</option>
<option value="12.30am">12:30am</option>
<option value="12.45am">12:45am</option>
<option value="13.00pm">13:00pm</option>
<option value="13.15pm">13:15pm</option>
<option value="13.30pm">13:30pm</option>
<option value="13.45pm">13:45pm</option>
<option value="14.00pm">14:00pm</option>
<option value="14.15pm">14:15pm</option>
<option value="14.30pm">14:30pm</option>
<option value="14.45pm">14:45pm</option>
<option value="15.00pm">15:00pm</option>
<option value="15.15pm">15:15pm</option>
<option value="15.30pm">15:30pm</option>
<option value="15.45pm">15:45pm</option>
<option value="16.00pm">16:00pm</option>
<option value="16.15pm">16:15pm</option>
<option value="16.30pm">16:30pm</option>
<option value="16.45pm">16:45pm</option>
<option value="17.00pm">17:00pm</option>
<option value="17.15pm">17:15pm</option>
<option value="17.30pm">17:30pm</option>
<option value="17.45pm">17:45pm</option>
<option value="18.00pm">18:00pm</option>
<option value="18.15pm">18:15pm</option>
<option value="18.30pm">18:30pm</option>
<option value="18.45pm">18:45pm</option>
<option value="19.00pm">19:00pm</option>
<option value="19.15pm">19:15pm</option>
<option value="19.30pm">19:30pm</option>
<option value="19.45pm">19:45pm</option>
<option value="20.00pm">20:00pm</option>
<option value="20.15pm">20:15pm</option>
<option value="20.30pm">20:30pm</option>
<option value="20.45pm">20:45pm</option>
<option value="21.00pm">21:00pm</option>
<option value="21.15pm">21:15pm</option>
<option value="21.30pm">21:30pm</option>
<option value="21.45pm">21:45pm</option>
<option value="22.00pm">22:00pm</option>
<option value="22.15pm">22:15pm</option>
<option value="22.30pm">22:30pm</option>
<option value="22.45pm">22:45pm</option>
<option value="23.00pm">23:00pm</option>
<option value="23.15pm">23:15pm</option>
<option value="23.30pm">23:30pm</option>
<option value="23.45pm">23:45pm</option>
<option value="00.00am">00:00am</option>
<option value="00.15am">00:15am</option>
<option value="00.30am">00:30am</option>
<option value="00.45am">00:45am</option>
<option value="01.00am">01:00am</option>
<option value="01.15am">01:15am</option>
<option value="01.30am">01:30am</option>
<option value="01.45am">01:45am</option>
<option value="02.00am">02:00am</option>
<option value="02.15am">02:15am</option>
<option value="02.30am">02:30am</option>
<option value="02.45am">02:45am</option>
<option value="03.00am">03:00am</option>
<option value="03.15am">03:15am</option>
<option value="03.30am">03:30am</option>
<option value="03.45am">03:45am</option>
<option value="04.00am">04:00am</option>
<option value="04.15am">04:15am</option>
<option value="04.30am">04:30am</option>
<option value="04.45am">04:45am</option>
<option value="05.00am">05:00am</option>
<option value="05.15am">05:15am</option>
<option value="05.30am">05:30am</option>
<option value="05.45am">05:45am</option>
<option value="06.00am">06:00am</option>
<option value="06.15am">06:15am</option>
<option value="06.30am">06:30am</option>
<option value="06.45am">06:45am</option>
</select>
</div>
<textarea name="eventDesc" id="eventDesc" cols="45" rows="10" placeholder="Please write the description event details"></textarea>
<input type="submit" value="Add Event">
</fieldset>
<div id="error"></div>
</form>
</div>
</div>
</div>
<script src="js/0004_eventsCalendar.js"></script>
</body>
</html>
JavaScript code:
//self-executing function to protect our local variables
(function(){
// current date
var curentDate = new Date();
// set variable to first day of week (Monday)
var firstDay = (curentDate.getDate() - (curentDate.getDay()-1));
// array of months
var allMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
// loop through to get last day (Friday) of the curent week
for(var i = 0; i < 7; i +=1){
var lastDay = firstDay + i;
}
// add the date to DOM element (h2 tag)
document.querySelector('h2').innerHTML =
allMonths[curentDate.getMonth()] + ' ' + firstDay + ' - ' + lastDay + ', ' + curentDate.getFullYear();
// get all DOM nodes with the class name ('.dayDate')
var dayDate = document.querySelectorAll('.dayDate');
// loop through those nodes and add to DOM month, current date and year
for(var i = 0; i < dayDate.length; i+=1){
dayDate[i].innerHTML = allMonths[curentDate.getMonth()] + ' ' + (firstDay + i) + ', ' + curentDate.getFullYear();
}
// assign form HTML element of Calendar panel to variables. Where '.fromTime' and '.toTome' , are names of <select> tag
var fromTime = document.calendarCMS.fromTime;
var toTime = document.calendarCMS.toTime;
// function for manipulating times (from: and to:), in Calendar panel
function changeFromTime(e){
// triger when time in first pop-down menu '.fromTime' is higher than in second pop-down menu '.toTime'
// where selectedIndex is a number (position) of currently selected element in pop-down menu
if(fromTime.selectedIndex >= toTime.selectedIndex){
// loop throogh first pop-down menu 'fromTime', where fromTime.selectedIndex is index curently selected element
for(var i = 0; i <= fromTime.selectedIndex; i +=1){
// hide all times in second pop-down menu 'toTime' which are below times in '.fromTime' pop-down menu
toTime[i].style.display = 'none';
}
// change position '.toTime' pop-down menu index to be equal to first pop-down menu '.froTime'
return toTime.selectedIndex = i;
}
// triger when time in first pop-down menu '.fromTime' is lower than in second pop-down menu '.toTime'
if(fromTime.selectedIndex <= toTime.selectedIndex){
// reverse (remove) styling when user change to earlier time, where we removing styling only to elements which are
// below curently selected index (i = fromTime.selectedIndex) in '.fromTime' pop-down menu
for(var i = fromTime.selectedIndex; i < toTime.selectedIndex; i +=1){
toTime[i].removeAttribute('style');
}
// change position '.toTime' pop-down menu index to be equal to first pop-down menu '.froTime'
return toTime.selectedIndex = fromTime.selectedIndex;
}
}
// function use to add/remove calendar events
function addEvent(e){
//event will triger only when user press submit 'Add Event' button
if(e.target.type === 'submit'){
// prevent submit button from default behavior
e.preventDefault();
// assign a couple of variables
var textArea = document.querySelector('textarea');
var eventHead = document.querySelectorAll('.eventHead');
var trElement = document.createElement('tr');
trElement.className = 'event';
var eventDesc = document.querySelectorAll('.desc');
var eventTime = document.querySelectorAll('.time');
var errMsg = document.querySelector('#error');
errMsg.style.color = "red";
// loop through description field in HTML table
for(var i = 0; i < eventHead.length; i+=1){
// trigger when option in index in 'dayOfWeek' pop-down menu will match index of description field
if(document.calendarCMS.dayOfWeek.selectedIndex === i){
// if textarea in HTML will be empty, then the error msg will pop out, blocking user from adding event
if(textArea.value === ''){
// error msg show when user doesn't fill all necessary details
errMsg.innerHTML = 'Please fill all fields';
return;
} else{ // if all require filed will be filled
/*
// after description of event will be added to table, then will be editable
eventDesc[i].contentEditable = true;
// after times of event will be added to table, then will be editable
eventTime[i].contentEditable = true;
*/
eventHead[i].parentNode.insertBefore(trElement.cloneNode(true), eventHead[i].nextElementSibling);
var eventContent = document.querySelectorAll('.event');
var tdElement1 = document.createElement('td');
var tdElement2 = document.createElement('td');
tdElement1.className = 'time';
tdElement2.className = 'desc';
for(var j = 0; j < eventContent.length; j +=1){
eventContent[j].appendChild(tdElement1);
eventContent[j].appendChild(tdElement2);
}
// reset all field in Calendar panel
fromTime.selectedIndex = 0;
toTime.selectedIndex = 0;
textArea.value = '';
errMsg.innerHTML = '';
}
}
}
}
}
// function for higlight current day of the week
function todayDay(e){
// triger only when user click 'today' button
if(e.target.textContent === 'today'){
var focusEvent = document.querySelectorAll('.event');
// loop through to find the current day of the week and highliht it
for(var i = 0; i < focusEvent.length; i +=1){
if(curentDate.getDay() === i){
focusEvent[i-1].style.background = 'yellow';
}
}
}
}
// events listeners
document.querySelector('#calendarCMS').addEventListener('click', addEvent, false);
document.querySelector('#fromTime').addEventListener('change', changeFromTime, false);
document.querySelector('.toolLeft').addEventListener('click', todayDay, false);
})();
I do not exactly apprehend your attempt with the commented tr class "event". But what you want to achieve (at least inferring from the description) can be done by declaring addEvent as :
function addEvent(e){
//event will triger only when user press submit 'Add Event' button
if(e.target.type === 'submit'){
// prevent submit button from default behavior
e.preventDefault();
// assign a couple of variables
var textArea = document.querySelector('textarea');
var eventHead = document.querySelectorAll('.eventHead');
var trElement = document.createElement('tr');
trElement.className = 'event';
var eventDesc = document.querySelectorAll('.desc');
var eventTime = document.querySelectorAll('.time');
var errMsg = document.querySelector('#error');
errMsg.style.color = "red";
// loop through description field in HTML table
for(var i = 0; i < eventHead.length; i+=1){
// trigger when option in index in 'dayOfWeek' pop-down menu will match index of description field
if(document.calendarCMS.dayOfWeek.selectedIndex === i){
// if textarea in HTML will be empty, then the error msg will pop out, blocking user from adding event
if(textArea.value === ''){
// error msg show when user doesn't fill all necessary details
errMsg.innerHTML = 'Please fill all fields';
return;
} else{ // if all require filed will be filled
/*
// after description of event will be added to table, then will be editable
eventDesc[i].contentEditable = true;
// after times of event will be added to table, then will be editable
eventTime[i].contentEditable = true;
*/
var newTr = trElement.cloneNode(true);
eventHead[i].parentNode.insertBefore(newTr, eventHead[i].nextElementSibling);
var eventContent = document.querySelectorAll('.event');
var tdElement1 = document.createElement('td');
var tdElement2 = document.createElement('td');
tdElement1.innerText=fromTime.value + " - " + toTime.value;
tdElement2.innerText=textArea.value;
tdElement1.className = 'time';
tdElement2.className = 'desc';
for(var j = 0; j < eventContent.length; j +=1){
newTr.appendChild(tdElement1);
newTr.appendChild(tdElement2);
}
// reset all field in Calendar panel
fromTime.selectedIndex = 0;
toTime.selectedIndex = 0;
textArea.value = '';
errMsg.innerHTML = '';
}
}
}
}
}
You can try it here : https://jsfiddle.net/dn9v5qf9/
When the Primary dropdown changes, I want the other dropdown to change accordingly.
But I dont know why only the 1st Other dropdown is working while the 2nd fails to change its value accordingly. I
m aware that if I change the name of the 2nd dropdown to the same as the 1st dropdown it will work.
But as they are different fields that are to be saved in the db, so the names have to be different.
Any solution would be appreciated. Many thanks.
function setDropDown() {
var index_name =
document.getElementsByName('ForceSelection')[0].selectedIndex;
var others = document.getElementsByName('Qualifications');
for (i = 0; i < others.length; i++)
others[i].selectedIndex = index_name;
var others2 = document.getElementsByName('Qualifications2');
for (i = 0; i < others2.length; i++)
others2[i].selectedIndex = index_name2;
}
Primary dropdown<select name="ForceSelection" id="ForceSelection" onChange="javascript:return setDropDown();">
<option value="" selected>Select</option>
<option value="treatmentid1">treatmentname1</option>
<option value="treatmentid2">treatmentname2</option>
</select> other dropdown
<select id="Qualifications" name="Qualifications">
<option value="select">select</option>
<option value="treatmentid1">treatmentname1</option>
<option value="treatmentid2">treatmentname2</option>
</select> other dropdown2
<select id="Qualifications2" name="Qualifications2">
<option value="select">select</option>
<option value="treatmentid1">treatmentname1</option>
<option value="treatmentid2">treatmentname2</option>
</select>
Add a css class to your secondary drop downs and use document.querySelectorAll to get them all at once.
Then you can use a single loop to update their selectedIndex.
function setDropDown() {
var index_name =
document.getElementsByName('ForceSelection')[0].selectedIndex;
var others = document.querySelectorAll('.secondary');
for (var i = 0; i < others.length; i++) {
others[i].selectedIndex = index_name;
}
}
div {
padding: 15px;
}
<div><b>Primary dropdown:</b>
<select name="ForceSelection" id="ForceSelection" onChange="javascript:return setDropDown();">
<option value="" selected>Select</option>
<option value="treatmentid1">treatmentname1</option>
<option value="treatmentid2">treatmentname2</option>
</select>
</div>
<div>
<b>Other dropdown 1</b>:
<select class='secondary' id="Qualifications" name="Qualifications">
<option value="select">select</option>
<option value="treatmentid1">treatmentname1</option>
<option value="treatmentid2">treatmentname2</option>
</select></div>
<div> <b>Other dropdown 1</b>:
<select class='secondary' id="Qualifications2" name="Qualifications2">
<option value="select">select</option>
<option value="treatmentid1">treatmentname1</option>
<option value="treatmentid2">treatmentname2</option>
</select>
</div>
So it turns out i haven't defined sth in my code, thanks for pointing that out #Tiny Giant
function setDropDown() {
var index_name =
document.getElementsByName('ForceSelection')[0].selectedIndex;
var index_name2 =
document.getElementsByName('ForceSelection')[0].selectedIndex;
var others = document.getElementsByName('Qualifications');
for (i = 0; i < others.length; i++)
others[i].selectedIndex = index_name;
var others2 = document.getElementsByName('Qualifications2');
for (j = 0; j < others2.length; j++)
others2[j].selectedIndex = index_name2;
}
Primary dropdown<select name="ForceSelection" id="ForceSelection" onChange="javascript:return setDropDown();">
<option value="" selected>Select</option>
<option value="treatmentid1">treatmentname1</option>
<option value="treatmentid2">treatmentname2</option>
</select> other dropdown
<select id="Qualifications" name="Qualifications">
<option value="select">select</option>
<option value="treatmentid1">treatmentname1</option>
<option value="treatmentid2">treatmentname2</option>
</select> other dropdown2
<select id="Qualifications2" name="Qualifications2">
<option value="select">select</option>
<option value="treatmentid1">treatmentname1</option>
<option value="treatmentid2">treatmentname2</option>
</select>
User selects first option, second select box appears and so forth (Got this to work) but can't figure out how to add a "remove_location" class - The "remove_location" class only removes the last select box that last appeared.
So my question is: How can I "add" a "remove_location" class where if this class is clicked on, the last select box disappears (becomes non-existent).
Demo: https://jsfiddle.net/g8bwurvq/
HTML:
<!-- START OF ADDING LOCATIONS -->
<select id="select1" class="ad_inquiry_locations" value="" name="guest_pl" required>
<option value="" selected disabled>Select primary location</option>
<option value="Beloit">Beloit</option>
<option value="Concordia">Concordia</option>
<option value="Glen-Elder">Glen Elder</option>
<option value="Jewell">Jewell</option>
</select>
<!-- Start of SECOND GROUP -->
<select id="select2" class="ad_inquiry_locations hide_location" value="" name="guest_al-2">
<option value="" selected disabled>Add a location</option>
<option value="Beloit">Beloit</option>
<option value="Concordia">Concordia</option>
<option value="Glen-Elder">Glen Elder</option>
<option value="Jewell">Jewell</option>
</select>
<!-- End of SECOND GROUP -->
<!-- Start of THIRD GROUP -->
<select id="select3" class="ad_inquiry_locations hide_location" value="" name="guest_al-3">
<option value="" selected disabled>Add a location</option>
<option value="Beloit">Beloit</option>
<option value="Concordia">Concordia</option>
<option value="Glen-Elder">Glen Elder</option>
<option value="Jewell">Jewell</option>
</select>
<!-- End of THIRD GROUP -->
<!-- Start of FOURTH GROUP -->
<select id="select4" class="ad_inquiry_locations hide_location" value="" name="guest_al-4">
<option value="" selected disabled>Add a location</option>
<option value="Beloit">Beloit</option>
<option value="Concordia">Concordia</option>
<option value="Glen-Elder">Glen Elder</option>
<option value="Jewell">Jewell</option>
</select>
<!-- End of FOURTH GROUP -->
<!-- END OF ADDING LOCATIONS -->
JS:
var Lists = [
document.getElementById("select1"),
document.getElementById("select2"),
document.getElementById("select3"),
document.getElementById("select4")
],
nbLists = Lists.length;
// Binds change events to each list
for (var iList = 0; iList < nbLists; iList++) {
Lists[iList].onchange = RemoveItems(iList);
}
function RemoveItems(iList) {
return function() {
Lists[iList + 1].classList.remove('hide_location');
var value = [];
// Add the selected items of all previous lists including the one changed
for (var jList = 0; jList <= iList; jList++) value.push(Lists[jList].options[Lists[jList].selectedIndex].text);
// Hide in all succeeding lists these items
for (var kList = iList + 1; kList < nbLists; kList++)
HideItems(kList, value);
}
}
// Hide items selected in previous lists in all next lists
function HideItems(iList, value) {
var nbOptions = Lists[iList].options.length,
nbValues = value.length,
found;
if (nbValues === 0) return;
for (var iOption = 0; iOption < nbOptions; iOption++) {
// Find if this element is present in the previous lists
found = false;
for (var iValue = 0; iValue < nbValues; iValue++) {
if (Lists[iList].options[iOption].text === value[iValue]) {
found = true;
break;
}
}
// If found, we hide it
if (found) {
Lists[iList].options[iOption].style.display = "none";
Lists[iList].options[iOption].selected = "";
}
// else we un-hide it (in case it was previously hidden)
else
Lists[iList].options[iOption].style.display = "";
}
}
CSS:
.hide_location {
display: none;
}
.remove_location {
width: 100px;
height: 40px;
padding: 0;
margin: 0;
float: left;
background: blue;
cursor: pointer;
}
Redo your HTML and Javascript as follow:
Change your JS from
var Lists = [
document.getElementById("select1"),
document.getElementById("select2"),
document.getElementById("select3"),
document.getElementById("select4")
],
nbLists = Lists.length;
// Binds change events to each list
for (var iList = 0; iList < nbLists; iList++) {
Lists[iList].onchange = RemoveItems(iList);
}
function RemoveItems(iList) {
return function() {
Lists[iList + 1].classList.remove('hide_location');
var value = [];
// Add the selected items of all previous lists including the one changed
for (var jList = 0; jList <= iList; jList++) value.push(Lists[jList].options[Lists[jList].selectedIndex].text);
// Hide in all succeeding lists these items
for (var kList = iList + 1; kList < nbLists; kList++)
HideItems(kList, value);
}
}
// Hide items selected in previous lists in all next lists
function HideItems(iList, value) {
var nbOptions = Lists[iList].options.length,
nbValues = value.length,
found;
if (nbValues === 0) return;
for (var iOption = 0; iOption < nbOptions; iOption++) {
// Find if this element is present in the previous lists
found = false;
for (var iValue = 0; iValue < nbValues; iValue++) {
if (Lists[iList].options[iOption].text === value[iValue]) {
found = true;
break;
}
}
// If found, we hide it
if (found) {
Lists[iList].options[iOption].style.display = "none";
Lists[iList].options[iOption].selected = "";
}
// else we un-hide it (in case it was previously hidden)
else
Lists[iList].options[iOption].style.display = "";
}
}
To
$(document).on('change', '.ad_inquiry_locations', function() {
$(this).next('select, button').remove();
var select = $('<select />', {
'class': 'ad_inquiry_locations',
value: "",
name: "guest_al-2"
});
var option = $('<option />', {
text: 'Add a location',
disabled: 'disabled'
});
var button = $('<button />', {
text: 'Remove Location',
click: function() {
$(this).prev().remove()
if ($('.ad_inquiry_locations').length == 1) $(this).remove();
}
});
select.append(option, $('option:not(:selected):not(:first)', this).clone(true));
$(this).after(select);
select.after(button);
});
Change your HTML from
<!-- START OF ADDING LOCATIONS -->
<select id="select1" class="ad_inquiry_locations" value="" name="guest_pl" required>
<option value="" selected disabled>Select primary location</option>
<option value="Beloit">Beloit</option>
<option value="Concordia">Concordia</option>
<option value="Glen-Elder">Glen Elder</option>
<option value="Jewell">Jewell</option>
</select>
<!-- Start of SECOND GROUP -->
<select id="select2" class="ad_inquiry_locations hide_location" value="" name="guest_al-2">
<option value="" selected disabled>Add a location</option>
<option value="Beloit">Beloit</option>
<option value="Concordia">Concordia</option>
<option value="Glen-Elder">Glen Elder</option>
<option value="Jewell">Jewell</option>
</select>
<!-- End of SECOND GROUP -->
<!-- Start of THIRD GROUP -->
<select id="select3" class="ad_inquiry_locations hide_location" value="" name="guest_al-3">
<option value="" selected disabled>Add a location</option>
<option value="Beloit">Beloit</option>
<option value="Concordia">Concordia</option>
<option value="Glen-Elder">Glen Elder</option>
<option value="Jewell">Jewell</option>
</select>
<!-- End of THIRD GROUP -->
<!-- Start of FOURTH GROUP -->
<select id="select4" class="ad_inquiry_locations hide_location" value="" name="guest_al-4">
<option value="" selected disabled>Add a location</option>
<option value="Beloit">Beloit</option>
<option value="Concordia">Concordia</option>
<option value="Glen-Elder">Glen Elder</option>
<option value="Jewell">Jewell</option>
</select>
<!-- End of FOURTH GROUP -->
<!-- END OF ADDING LOCATIONS -->
To
<!-- START OF ADDING LOCATIONS -->
<select id="select1" class="ad_inquiry_locations" value="" name="guest_pl" required>
<option value="" selected disabled>Select primary location</option>
<option value="Beloit">Beloit</option>
<option value="Concordia">Concordia</option>
<option value="Glen-Elder">Glen Elder</option>
<option value="Jewell">Jewell</option>
</select>
<!-- END OF ADDING LOCATIONS -->
And you can get rid of what little CSS you have as it no longer applies.
And finally, here is a DEMO of it all working correctly.