Reputation: 79
I have a table named, student_db which is like this :-
Name Gender Grade City
John Male 2 North
Dave Male 4 North
Garry Male 3 North
Chirsty Female 5 East
Monica Female 4 East
Andrew Male 3 East
Patrick Male 7 South
Maria Female 3 South
I need to select 3 students with this list, names of the students are taken as input. But there are some constraints :
1) 1 Female has to be selected.
2) A maximum of 2 persons from the same city can be selected.
3) Sum of the grade of the selected 3 persons cannot exceed 11.
4) Once three valid selections are made, rest of the checkboxes should freeze automatically.
5) If while selecting a person any of the constraint gets violated, that particular selections gets unchecked and a alert message is displayed to the user.
Is it possible to add so many constraints to a check box ??
EDIT
I have managed to add 2 constraints :-
1) If the grade sum exceeds 11, an alert message will get displayed.
2) Once three valid selections are made, rest checkboxes will get freezed.
This is what I've tried :-
<script src="http://code.jquery.com/jquery-1.9.1.js" type="text/javascript"></script>
<script type="text/javascript">
jQuery(function() {
var max = 3;
var checkboxes = $('input[type="checkbox"]');
checkboxes.change(function() {
var current = checkboxes.filter(':checked').length;
checkboxes.filter(':not(:checked)').prop('disabled', current >= max);
});
});
</script>
<script>
function jsFunction(element) {
var sum = 0,i;
var elements = document.getElementsByClassName('chkbox');
for (i = 0; i<elements.length; i++) {
if (elements[i].checked) {
sum += parseInt(elements[i].value);
}
}
if (sum > 11) {
alert("11 maximum grade allowed !!");
element.checked = false;
}
}
</script>
<form name='checkbox1[]' method="post" action="select_student.php">
<label class="cb1" for="checkbox1"> </label>
<input type="hidden" name="checkbox1[]" id="check" value="null">
<?php
session_start();
mysql_connect("localhost", "my_db", "my_password") or die (mysql_error ());
mysql_select_db("my_db") or die(mysql_error());
$strSQL = "SELECT Name,Grade FROM student_db";
$rs = mysql_query($strSQL);
echo "<b><h2>List of Students :-</h2></b>";
while($row = mysql_fetch_array($rs)) {
$man = $row['Name'];
echo '<input type="checkbox" value="'.$row['Name'].'|'.$row['Grade'].'" class="chkbox" name="checkbox1[]" onchange="jsFunction(this)" />';
echo $man;
}
?>
<br>
<input type="submit" value="SUBMIT" id="button1" style= "height:40px; width:150px; font-weight: bold; font-size:10;">
</form>
The JS function is used to check whether the Grade sum is exceeding 11 or not and the jQuery Functions freezes other boxes once 3 valid selections are made. But I am unable to add other constraints.
Upvotes: 1
Views: 2855
Reputation: 7960
Sorry for the delayed response! I got caught up in some other stuff yesterday and had to pick back up this morning . . . hopefully, this will help you out.
What you have is a pretty good start . . . here's a few changes that I would suggest:
1) First off, some HTML changes:
store off all of your student data (i.e., the "gender", "grade", and "city" values) as data
attributes in the checkbox, like this:
<input type="checkbox" value="NAME_VALUE" class="chkbox" name="checkbox1[]"
data-gender="GENDER_VALUE" data-grade="GRADE_VALUE" data-city="CITY_VALUE"
onchange="jsFunction(this)" />
next, since you are already using jQuery, for clarity and easy of maintenance in the future, apply the onchange
event listener dynamically, rather than hardcoding it into the input, like this:
<input type="checkbox" value="NAME_VALUE" class="chkbox" name="checkbox1[]"
data-gender="GENDER_VALUE" data-grade="GRADE_VALUE" data-city="CITY_VALUE" />
. . . and, in the script, after the page load:
$(".chkbox").on("change", jsFunction);
And, finally (just as a heads up), if you intend to us a <label>
tag with a for
attribute (e.g., you are showing one for your "hidden" input), you will need a matching id
attribute in yout <input>
, in order for them to be paired.
2) As for your scripting, I threw together the following that accomplishes all of the validation checks that you were looking for and standardizes some of your coding (you had a heavily mixed use of jQuery and vanilla JS).
var MAX_CHECKED = 3;
var MAX_GRADE = 11;
$("document").ready(function() {
$(".chkbox").on("change", jsFunction);
});
function jsFunction() {
var sum = 0;
var cities = [];
var elements = $(".chkbox");
var checkedElements = elements.filter(":checked");
checkedElements.each(function() {
sum += parseInt($(this).data("grade"), 10);
cities.push($(this).data("city"));
});
var uniqueCities = cities.filter(function(currentCity, cityIndex, cityArray) {
return (cityIndex === cityArray.indexOf(currentCity));
});
if (sum > MAX_GRADE ) {
alert(MAX_GRADE + " maximum grade allowed!!");
$(this).prop("checked", false);
}
else if (uniqueCities.length !== cities.length) {
alert("You may not select more than one student from each city!!");
$(this).prop("checked", false);
}
else {
if (checkedElements.length >= MAX_CHECKED) {
if (checkedElements.filter("[data-gender='Female']").length < 1) {
alert("At least one female student must be selected!!");
$(this).prop("checked", false);
}
else {
elements.filter(':not(:checked)').prop('disabled', true);
}
}
else {
elements.filter(':not(:checked)').prop('disabled', false);
}
}
}
Most of the code should be pretty straightforward . . . let me touch on a couple of the key or more complex parts . . .
MAX_CHECKED
and MAX_GRADE
) up at the top and outside of any functions, so that they are accessible anywhere and easy to update (i.e., you don't have to search through the code to find them).jQuery(function() {
that you used to $("document").ready(function() {
simply for readablity. :) They do the same thing.$(".chkbox").on("change", jsFunction);
. Additionally, you'll notice that I changed the selector. Since each checkbox is tagged with the "chkbox" class, I selected based on that, it is significantly faster than $('input[type="checkbox"]')
uniqueCities
- the function used to create this value isn't quite as straighforward as the rest of the code, so I'll clarify it a little. It is using the .filter
method that is native to Arrays
, to trim down the selections to only unique values. It does this by doing a callback which checks to see if the index of the current item (i.e., cityIndex
) is the same as the index of the first instance of that value (i.e., currentCity
) in the array (i.e., cityArray
). If it is, then that value is added to the "filtered" array (i.e., uniqueCities
).else
statement that re-enables the checkboxes if the maximum number of selections have been made, but then one of them is unchecked. This will allow the user to change their mind, even if they had already hit the max, at some point.A couple of extra notes
1) You need to change the value of Patrick's to "6" at the most, in order to check that the "at least one female" logic is working . . . currently, the lowest combination of all male students, from unique cities, is John, Garry, and Patrick, but their grade total is 12, so it triggers the "grade sum is too high" validation first. :)
2) While I didn't cover the code for this, you need to develop a version of this validation logic for your "Submit" button as well. If you don't, then someone could select two boys and hit "Submit" and the "at least one female" logic would never be triggered.
One way would be to put the "at least one female" validation in its own method and calling both from the "I just clicked on a checkbox" validation and in a "I just clicked on the submit button" validation. The main difference would be that, for the submit, you would not check to see if the max number of selections had been made, before triggering the "female" check. That would also be a good place to add an "at least one selection has been made" validation, as well.
Upvotes: 1