Reputation: 1012
I am creating a form that allows users to set a grading scale to be applied to test templates. This form has a number input for A,B,C,D,F. I'm trying to use javascript (jquery) to keep each of the numbers in the appropriate order.
In the fiddle I changed to html inputs so I could easily make use of js fiddle, that part shouldn't matter
What I have so far is working somewhat however, it is still possible to send a value above or below the set value for another grade level. What I'd like is to increment the other grade letter value to disallow this overlap. Please let me know if you need more clarification.
Here is the html for the inputs:
<div class="form-group" style="width:500px;">
@Html.LabelFor(a => a.GradeScale, "Enter the number values for the grade scale")
<div>
<span class="large-text">A</span> @Html.TextBox("ARange", 100, "", new { @id = "aRange", @type = "number", @class = "thin-column", @max = 100, @min = 4 })
to <span id="aLowRange">94</span>
</div>
<div>
<span class="large-text">B</span> @Html.TextBox("BRange", 93, "", new { @id = "bRange", @type = "number", @class = "thin-column", @max = 99, @min = 3 })
to <span id="bLowRange">85</span>
</div>
<span class="large-text">C</span> @Html.TextBox("CRange", 84, "", new { @id = "cRange", @type = "number", @class = "thin-column", @max = 98, @min = 2 })
to <span id="cLowRange">77</span>
<div>
<span class="large-text">D</span> @Html.TextBox("DRange", 76, "", new { @id = "dRange", @type = "number", @class = "thin-column", @max = 97, @min = 1 })
to <span id="dLowRange">70</span>
</div>
<div>
<span class="large-text">F</span> @Html.TextBox("FRange", 69, "", new { @id = "fRange", @type = "number", @class = "thin-column", @max = 96, @min = 0 })
to <span id="fLowRange">0</span>
</div>
</div>
here is the javascript I've written:
$(function () {
$('#aRange,#bRange,#cRange,#dRange,#fRange').on('change', function () {
var aLowRange = parseInt($('#bRange').val()) + 1;
$('#aLowRange').text(aLowRange);
var bLowRange = parseInt($('#cRange').val()) + 1;
$('#bLowRange').text(bLowRange);
var cLowRange = parseInt($('#dRange').val()) + 1;
$('#cLowRange').text(cLowRange);
var dLowRange = parseInt($('#fRange').val()) + 1;
$('#dLowRange').text(dLowRange);
//check to see if the low val is higher than the high val then correct
$('#bRange').val() >= parseInt($('#bLowRange').val()) ? $('#bLowRange').text(parseInt($('#bLowRange').val()) + 1) : "";
$('#cRange').val() >= parseInt($('#cLowRange').val()) ? $('#cLowRange').text(parseInt($('#cLowRange').val()) + 1) : "";
$('#dRange').val() >= parseInt($('#dLowRange').val()) ? $('#dLowRange').text(parseInt($('#dLowRange').val()) + 1) : "";
$('#fRange').val() >= parseInt($('#fLowRange').val()) ? $('#fLowRange').text(parseInt($('#fLowRange').val()) + 1) : "";
});
});
and here is a fiddle showing what I have so far in action. I'm open to javascript or jquery assistance:
https://jsfiddle.net/jacobrutter/nub2gsoL/
I don't need a complete solution, if you can point me in the right direction I'll run with it. Thanks!
Upvotes: 2
Views: 126
Reputation: 51
Here is a link to jsfiddle solution:
https://jsfiddle.net/cmurk0zh/
helper functions:
function findIndex(value, array) {
for(var i = 0; i < array.length; i++) {
if (array[i].letter === value) {
return i;
}
}
}
var gradeValues = [
{
letter: 'a',
max: 100,
min: 94
},
{
letter: 'b',
max: 100,
min: 94
},
{
letter: 'c',
max: 100,
min: 94
},
{
letter: 'd',
max: 100,
min: 94
},
{
letter: 'f',
max: 100,
min: 94
},
];
function setMaxInputValue(thisGrade) {
$('#' + thisGrade.letter + 'Range').val(thisGrade.max);
}
function setMinLabelText(thisGrade) {
$('#' + thisGrade.letter + 'LowRange').text(thisGrade.min);
}
on change:
$(function () {
//when an input val changes, adjust the low range appropriately
$('#aRange,#bRange,#cRange,#dRange,#fRange').on('change', function (event) {
var changedValueId = event.currentTarget.id;
var startIndex = findIndex(changedValueId[0], gradeValues);
// get values
for (var i = 0; i < gradeValues.length; i++ ) {
gradeValues[i].max = parseInt($('#' + gradeValues[i].letter + 'Range').val());
gradeValues[i].min = $('#' + gradeValues[i].letter + 'LowRange').text();
}
// Correct same
var thisGrade = gradeValues[startIndex];
if (thisGrade.min >= thisGrade.max) {
thisGrade.min = thisGrade.max - 1;
setMaxInputValue(thisGrade);
setMinLabelText(thisGrade);
}
// correct above
for (var i = startIndex; i > 0; i--) {
var previousGradeValue = gradeValues[i-1];
previousGradeValue.min = gradeValues[i].max + 1;
setMinLabelText(previousGradeValue);
if (previousGradeValue.max <= previousGradeValue.min) {
previousGradeValue.max = previousGradeValue.min + 1;
setMaxInputValue(previousGradeValue);
}
}
// correct below
for (var i = startIndex; i < gradeValues.length - 1; i++) {
var nextGradeValue = gradeValues[i+1];
nextGradeValue.max = gradeValues[i].min - 1;
setMaxInputValue(nextGradeValue);
if (nextGradeValue.max <= nextGradeValue.min) {
nextGradeValue.min = nextGradeValue.max - 1;
setMinLabelText(nextGradeValue);
}
}
});
});
I parameterized some of the variables so that it could be iterated through. The main thing about this solution, is that it finds which one was changed and modifies the values above and below.
This solution does not have full bound checking at beginning and end values.
Upvotes: 1
Reputation: 1012
Well here is the javascript I put together that solves my use case but isn't very DRY. I think I'll use it and circle back later to refactor.
$(function () {
//when an input val changes, adjust the low range appropriately
$('#aRange,#bRange,#cRange,#dRange,#fRange').on('change', function () {
var aRange = parseInt($('#aRange').val());
var bRange = parseInt($('#bRange').val());
var cRange = parseInt($('#cRange').val());
var dRange = parseInt($('#dRange').val());
var fRange = parseInt($('#fRange').val());
var aLowRange = parseInt($('#bRange').val()) + 1;
$('#aLowRange').text(aLowRange);
var bLowRange = parseInt($('#cRange').val()) + 1;
$('#bLowRange').text(bLowRange);
var cLowRange = parseInt($('#dRange').val()) + 1;
$('#cLowRange').text(cLowRange);
var dLowRange = parseInt($('#fRange').val()) + 1;
$('#dLowRange').text(dLowRange);
//check to see one grade value crosses another then correct
var rangeArray = [aRange, bRange, cRange, dRange, fRange];
var nameArray = ['aRange', 'bRange', 'cRange', 'dRange', 'fRange'];
var lowNameArray = ['aLowRange', 'bLowRange', 'cLowRange', 'dLowRange', 'fLowRange'];
for (var i = 0; i < rangeArray.length; i++) {
if (rangeArray[i] <= rangeArray[i + 1]) {
rangeArray[i + 1] -= 1;
$('#' + nameArray[i + 1]).val(rangeArray[i + 1]);
var lowRange = parseInt($('#' + nameArray[i + 1]).val()) + 1;
$('#' + lowNameArray[i]).text(lowRange);
}
}
});
});
Thank you for taking a moment to discuss it with me, it helped me think about the problem in different ways. (I'm open to improvements, if you do improve upon it, I'll happily mark yours as answer.)
Upvotes: 0