How can I make this JQuery and HTML, per-row specific?
In CB UserList the form appears multiple times (one for every record) and the below code is expected to produce the submit button and the modules to show/hide for every record that appears on the list separately. When a user makes a selection on the first row, everything works fine but only for the first row. Button and module divs show/hide properly on the first row (first record) only. The problem is that as the code is now, the selection on the first row is applied to all rows and the show/hide appears to all rows simultaneously. I need it to appear in each row separately, like when I select the first or any row, the other rows to remain unchanged unless I select them. Maybe I need something like parent/child/siblings relation for the button and the modules?
My html is as follows
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="form-group">
<select name="test" class="form-control">
<option label="Please select" selected="selected" value="">Please select</option>
<optgroup label="test1" style="font-weight: bolder;">
<option label="1a" value="UserSubmit, free"></option>
<option label="1b" value="6"></option>
<option label="1c" value="3"></option>
</optgroup>
<optgroup label="test2" style="font-weight: bolder;">
<option label="2a" value="O24"></option>
<option label="2b" value="O12"></option>
<option label="2c" value="O6"></option>
<option label="2d" value="O2"></option>
</optgroup>
</select>
</div>
<div id="free">{loadmoduleid 240}</div>
<div id="button"><input name="submit" type="submit" value="somevalue" id="submit-button" class="btn btn-primary UserSubmit" /></div>
<div id="6">{loadmoduleid 234}</div>
<div id="3">{loadmoduleid 235}</div>
<div id="O24">{loadmoduleid 236}</div>
<div id="O12">{loadmoduleid 237}</div>
<div id="O6">{loadmoduleid 238}</div>
<div id="O2">{loadmoduleid 239}</div>
</div>
</div>
My JQuery
$(document).ready(function () {
$("select").on('change', function () {
var x = this.selectedIndex;
if (x == "1") {
$(".UserSubmit").show();
$("#free").show();
$("#6").hide();
$("#3").hide();
$("#O24").hide();
$("#O12").hide();
$("#O6").hide();
$("#O2").hide();
} else if (x == "2") {
$(".UserSubmit").hide();
$("#free").hide();
$("#6").show();
$("#3").hide();
$("#O24").hide();
$("#O12").hide();
$("#O6").hide();
$("#O2").hide();
} else if (x == "3") {
more ifs until x == "7"
} else {
$(".UserSubmit").hide();
$("#free").hide();
$("#6").hide();
$("#3").hide();
$("#O24").hide();
$("#O12").hide();
$("#O6").hide();
$("#O2").hide();
}
});
$(".UserSubmit").css("display", "none");
$("#free").css("display", "none");
$("#6").css("display", "none");
$("#3").css("display", "none");
$("#O24").css("display", "none");
$("#O12").css("display", "none");
$("#O6").css("display", "none");
$("#O2").css("display", "none");
});
Okay, I scribbled something, I hope I understood correctly and this code reflects what you wanted.
const selectElement = document.querySelectorAll('select');
selectElement.forEach(select => {
const colElement = select.parentNode.closest('.col-md-6');
const withoutFormGroup = (Array.from(colElement.children).filter(child => child.id !== select.id));
// hidden all elements
withoutFormGroup.forEach(child => {
child.style.display = 'none';
});
// show selected element
select.addEventListener('change', function() {
const indexSelected = this.selectedIndex;
const indexValue = this.value;
// show selected element
withoutFormGroup.forEach((child, index) => {
child.style.display = child.id === indexValue ? 'block' : 'none';
// if selected element is 1 then show
// first and second element
if (indexSelected === 1 && (index === 0 || index === 1)) {
child.style.display = 'block';
}
});
});
});
.container {
display: inline-block;
padding: 20px;
border: 1px solid red;
}
.col-md-6>*+* {
margin-top: 10px;
}
.row+.row {
margin-top: 20px;
}
.active {
background-color: #000;
color: #fff;
}
<div class="container">
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="form-group">
<select name="test" class="form-control">
<option label="Please select" selected="selected" value="">Please select</option>
<optgroup label="test1" style="font-weight: bolder;">
<option label="1a" value="UserSubmit, free"></option>
<option label="1b" value="6"></option>
<option label="1c" value="3"></option>
</optgroup>
<optgroup label="test2" style="font-weight: bolder;">
<option label="2a" value="O24"></option>
<option label="2b" value="O12"></option>
<option label="2c" value="O6"></option>
<option label="2d" value="O2"></option>
</optgroup>
</select>
</div>
<div id="free">{loadmoduleid 240}</div>
<div id="button">
<input name="submit" type="submit" value="somevalue" id="submit-button" class="btn btn-primary UserSubmit" />
</div>
<div id="6">{loadmoduleid 234}</div>
<div id="3">{loadmoduleid 235}</div>
<div id="O24">{loadmoduleid 236}</div>
<div id="O12">{loadmoduleid 237}</div>
<div id="O6">{loadmoduleid 238}</div>
<div id="O2">{loadmoduleid 239}</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="form-group">
<select name="test" class="form-control">
<option label="Please select" selected="selected" value="">Please select</option>
<optgroup label="test1" style="font-weight: bolder;">
<option label="1a" value="UserSubmit, free"></option>
<option label="1b" value="6"></option>
<option label="1c" value="3"></option>
</optgroup>
<optgroup label="test2" style="font-weight: bolder;">
<option label="2a" value="O24"></option>
<option label="2b" value="O12"></option>
<option label="2c" value="O6"></option>
<option label="2d" value="O2"></option>
</optgroup>
</select>
</div>
<div id="free">{loadmoduleid 240}</div>
<div id="button">
<input name="submit" type="submit" value="somevalue" id="submit-button" class="btn btn-primary UserSubmit" />
</div>
<div id="6">{loadmoduleid 234}</div>
<div id="3">{loadmoduleid 235}</div>
<div id="O24">{loadmoduleid 236}</div>
<div id="O12">{loadmoduleid 237}</div>
<div id="O6">{loadmoduleid 238}</div>
<div id="O2">{loadmoduleid 239}</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="form-group">
<select name="test" class="form-control">
<option label="Please select" selected="selected" value="">Please select</option>
<optgroup label="test1" style="font-weight: bolder;">
<option label="1a" value="UserSubmit, free"></option>
<option label="1b" value="6"></option>
<option label="1c" value="3"></option>
</optgroup>
<optgroup label="test2" style="font-weight: bolder;">
<option label="2a" value="O24"></option>
<option label="2b" value="O12"></option>
<option label="2c" value="O6"></option>
<option label="2d" value="O2"></option>
</optgroup>
</select>
</div>
<div id="free">{loadmoduleid 240}</div>
<div id="button">
<input name="submit" type="submit" value="somevalue" id="submit-button" class="btn btn-primary UserSubmit" />
</div>
<div id="6">{loadmoduleid 234}</div>
<div id="3">{loadmoduleid 235}</div>
<div id="O24">{loadmoduleid 236}</div>
<div id="O12">{loadmoduleid 237}</div>
<div id="O6">{loadmoduleid 238}</div>
<div id="O2">{loadmoduleid 239}</div>
</div>
</div>
</div>
It's best if you put this code from id="free"
to id="02"
in an additional div with some class because currently I rely on the "col-md-6"
class and it can be disastrous ;)
And most importantly, I haven't been using jquery for a few years, so the code is in plain js ;)
I can see that you are relying on the id, remember that there can only be one id the same on a page. You cannot duplicate them. It's best to use data attributes.
EDIT
In one of the threads you wrote "... list of hundreds or thousands of users ..." And you did not mention that in the description;). I modified the solution and hide the data using css, not js. If we do not do this, before js starts working, all elements that should not be visible will be visible on the website.
const selectElement = document.querySelectorAll('select');
selectElement.forEach(select => {
const modules = select.parentNode.nextElementSibling;
// show selected element
select.addEventListener('change', function() {
const indexSelected = this.selectedIndex;
const indexValue = this.value;
// show selected element
[].slice.call(modules.children).forEach((child, index) => {
child.style.display = child.dataset.id === indexValue ? 'block' : 'none';
// if selected element is 1 then show
// first and second element
if (indexSelected === 1 && (index === 0 || index === 1)) {
child.style.display = 'block';
}
});
});
});
.container {
display: flex;
padding: 20px;
align-items: top;
border: 1px solid red;
gap: 30px;
}
.form-group {
margin-bottom: 10px;
}
.modules>* {
display: none;
}
<div class="container">
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="form-group">
<select name="test" class="form-control">
<option label="Please select" selected="selected" value="">Please select</option>
<optgroup label="test1" style="font-weight: bolder;">
<option label="1a" value="UserSubmit, free"></option>
<option label="1b" value="6"></option>
<option label="1c" value="3"></option>
</optgroup>
<optgroup label="test2" style="font-weight: bolder;">
<option label="2a" value="O24"></option>
<option label="2b" value="O12"></option>
<option label="2c" value="O6"></option>
<option label="2d" value="O2"></option>
</optgroup>
</select>
</div>
<div class="modules">
<div data-id="free">{loadmoduleid 240}</div>
<div data-id="button">
<input name="submit" type="submit" value="somevalue" id="submit-button" class="btn btn-primary UserSubmit" />
</div>
<div data-id="6">{loadmoduleid 234}</div>
<div data-id="3">{loadmoduleid 235}</div>
<div data-id="O24">{loadmoduleid 236}</div>
<div data-id="O12">{loadmoduleid 237}</div>
<div data-id="O6">{loadmoduleid 238}</div>
<div data-id="O2">{loadmoduleid 239}</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="form-group">
<select name="test" class="form-control">
<option label="Please select" selected="selected" value="">Please select</option>
<optgroup label="test1" style="font-weight: bolder;">
<option label="1a" value="UserSubmit, free"></option>
<option label="1b" value="6"></option>
<option label="1c" value="3"></option>
</optgroup>
<optgroup label="test2" style="font-weight: bolder;">
<option label="2a" value="O24"></option>
<option label="2b" value="O12"></option>
<option label="2c" value="O6"></option>
<option label="2d" value="O2"></option>
</optgroup>
</select>
</div>
<div class="modules">
<div data-id="free">{loadmoduleid 240}</div>
<div data-id="button">
<input name="submit" type="submit" value="somevalue" id="submit-button" class="btn btn-primary UserSubmit" />
</div>
<div data-id="6">{loadmoduleid 234}</div>
<div data-id="3">{loadmoduleid 235}</div>
<div data-id="O24">{loadmoduleid 236}</div>
<div data-id="O12">{loadmoduleid 237}</div>
<div data-id="O6">{loadmoduleid 238}</div>
<div data-id="O2">{loadmoduleid 239}</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="form-group">
<select name="test" class="form-control">
<option label="Please select" selected="selected" value="">Please select</option>
<optgroup label="test1" style="font-weight: bolder;">
<option label="1a" value="UserSubmit, free"></option>
<option label="1b" value="6"></option>
<option label="1c" value="3"></option>
</optgroup>
<optgroup label="test2" style="font-weight: bolder;">
<option label="2a" value="O24"></option>
<option label="2b" value="O12"></option>
<option label="2c" value="O6"></option>
<option label="2d" value="O2"></option>
</optgroup>
</select>
</div>
<div class="modules">
<div data-id="free">{loadmoduleid 240}</div>
<div data-id="button">
<input name="submit" type="submit" value="somevalue" id="submit-button" class="btn btn-primary UserSubmit" />
</div>
<div data-id="6">{loadmoduleid 234}</div>
<div data-id="3">{loadmoduleid 235}</div>
<div data-id="O24">{loadmoduleid 236}</div>
<div data-id="O12">{loadmoduleid 237}</div>
<div data-id="O6">{loadmoduleid 238}</div>
<div data-id="O2">{loadmoduleid 239}</div>
</div>
</div>
</div>
</div>
I added a modules
class in which I hide elements using css. Well, these elements have a data-id
not an id
. It should be correct now.
You can use the toggle()
method on the div whose id matches the selected option.
$(document).ready(function () {
$("select").on('change', function () {
var target = $('option:selected', this).attr('data-toggle-target');
$('#' + target).toggle();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="form-group">
<select name="test" class="form-control">
<option label="Please select" selected="selected" value="">Please select</option>
<optgroup label="test1" style="font-weight: bolder;">
<option label="1a" value="value1a" data-toggle-target="6"></option>
<option label="1b" value="value1b" data-toggle-target="3"></option>
<option label="1c" value="value1c" data-toggle-target="024"></option>
</optgroup>
<optgroup label="test2" style="font-weight: bolder;">
<option label="2a" value="value2a" data-toggle-target="012"></option>
<option label="2b" value="value2b" data-toggle-target="06"></option>
<option label="2c" value="value2c" data-toggle-target="02"></option>
</optgroup>
</select>
</div>
<div id="free">{loadmoduleid 240}</div>
<div id="button"><input name="submit" type="submit" value="somevalue" id="submit-button" class="btn btn-primary UserSubmit" /></div>
<div id="6">{loadmoduleid 234}</div>
<div id="3">{loadmoduleid 235}</div>
<div id="O24">{loadmoduleid 236}</div>
<div id="O12">{loadmoduleid 237}</div>
<div id="O6">{loadmoduleid 238}</div>
<div id="O2">{loadmoduleid 239}</div>
</div>
</div>
And if you don't need the value
attribut on the options anywhere else, I suggest you replace the value
of each option with the corresponding id's of the divs and you can simplify you jQuery to this:
$(document).ready(function () {
$("select").on('change', function () {
var target = $(this).val();
$('#' + target).toggle();
});
});
Sadly, this won't work if you hit the same option twice in a row, since the <select>
selected item doesn't change. You could use click
event on the <select>
, but that fires twice (first when you open the dropdown, second when selecting the value) so you would need to filter out the first event. click
event on <option>
doesn't work, at least on Chrome.