I need to reinitialize the state of some html elements from two different events (an html select change and a checkbox change), so I created a function that I placed outside the "ready" function to do that, and call it from both events.
However, JSLint flags this call to it:
$('#unitsselect').change(function() {
unitSelected = true;
reinitializeRecipientsAndGenerateVals();
. . .
...as being "out of scope"; specifically, it tells me,
'reinitializeRecipientsAndGenerateVals' is out of scope.
and indicates that line as the problematic one.
reinitializeRecipientsAndGenerateVals()
is indeed outside that change event handler, and also outside the "ready" function. I put it inside the ready function to see if that was the problem, but I still get that warning from JSLint with it there.
How can I reuse this function so that I don't have to move it inside both change event handlers?
Note: This has an "used out of scope" section, but not an "is out of scope"
According to this, all versions of JSLint use "{a} used outside of binding context"
Even when I move the function right into the change event handler, JSLint complains in the same way.
For Travis, here is the whole enchilada:
$(document).ready(function() {
var unitSelected = false;
var checkboxSelected = false;
// When unit is selected, populate the data range value elements; if checkbox selected,
// also populate email recipients and generate vals (specific day or based on a pattern)
$('#unitsselect').change(function() {
unitSelected = true;
reinitializeRecipientsAndGenerateVals();
var unitval = $('#unitsselect').val();
// This is admittedly kludgy - copying the same ajax call multiple times, changing only
// the report number; but a forloop attempt failed because of the asynchronous nature of
// it all; for some reason, populatedatarangeprams() was called only once, and with a
// rptval of 5 (when it "should have been" 1..4 instead).
var model = JSON.stringify({ unit: unitval, report: 1 });
$.ajax({
type: 'GET',
url: '@Url.Action("GetUnitDataRangeParamsVals", "UnitReportDataRangeParams")',
data: { unit: unitval, report: 1 },
contentType: 'application/json',
cache: false,
success: function(returneddata) {
populatedatarangeprams(1, returneddata);
},
error: function() {
alert('error - returneddata.error.stringify');
}
});
model = JSON.stringify({ unit: unitval, report: 2 });
$.ajax({
type: 'GET',
url: '@Url.Action("GetUnitDataRangeParamsVals", "UnitReportDataRangeParams")',
data: { unit: unitval, report: 2 },
contentType: 'application/json',
cache: false,
success: function(returneddata) {
populatedatarangeprams(2, returneddata);
},
error: function() {
alert('error - returneddata.error.stringify');
}
});
model = JSON.stringify({ unit: unitval, report: 3 });
$.ajax({
type: 'GET',
url: '@Url.Action("GetUnitDataRangeParamsVals", "UnitReportDataRangeParams")',
data: { unit: unitval, report: 3 },
contentType: 'application/json',
cache: false,
success: function(returneddata) {
populatedatarangeprams(3, returneddata);
},
error: function() {
alert('error - returneddata.error.stringify');
}
});
model = JSON.stringify({ unit: unitval, report: 4 });
$.ajax({
type: 'GET',
url: '@Url.Action("GetUnitDataRangeParamsVals", "UnitReportDataRangeParams")',
data: { unit: unitval, report: 4 },
contentType: 'application/json',
cache: false,
success: function(returneddata) {
populatedatarangeprams(4, returneddata);
},
error: function() {
alert('error - returneddata.error.stringify');
}
});
if (!checkboxSelected) {
return;
}
// from http://stackoverflow.com/questions/36870365/how-can-i-elegantize-this-verbose-jquery/
rptval = $('[id^=ckbx_]').filter(':checked').val();
setEmailAndGenerateValsForUnitReportPair(unitval, rptval);
}); // $('#unitsselect').change(function ()
// Checkbox selection has changed; if Unit has been selected, populate the email and generate vals
$(".ckbx").change(function() {
if (!this.checked) {
checkboxSelected = false;
reinitializeRecipientsAndGenerateVals();
return;
}
checkboxSelected = true;
// this unchecks all other checkboxes (from http://stackoverflow.com/questions/17785010/jquery-uncheck-other-checkbox-on-one-checked):
$('.ckbx').not(this).prop('checked', false);
reinitializeRecipientsAndGenerateVals();
// If no unit is selected, vals can not be set, so exit now
if (!unitSelected) {
return;
}
var unitval = $('#unitsselect').val();
var rptval = $(this).val();
setEmailAndGenerateValsForUnitReportPair(unitval, rptval);
}); // $(".ckbx").change(function ()
}); // "ready" function
function setEmailAndGenerateValsForUnitReportPair(unitval, rptval) {
var model = JSON.stringify({ unit: unitval, report: rptval });
$.ajax({
type: 'GET',
url: '@Url.Action("GetUnitReportPairEmailAddresses", "UnitReportPair")',
data: { unit: unitval, report: rptval },
contentType: 'application/json', //<= this is paired with stringify above; if comment out one, comment out both
cache: false,
success: function(returneddata) {
populateemails(returneddata);
},
error: function() {
alert(returneddata.error.stringify);
}
});
// The above AJAX call retrieved email addr vals; the next one is for the "Generate and Email Report" section of the page
$.ajax({
type: 'GET',
url: '@Url.Action("GetUnitReportPairGenerateVals", "UnitReportPairGenerateVals")',
data: { unit: unitval, report: rptval },
contentType: 'application/json',
cache: false,
success: function(returneddata) {
populategeneratevals(returneddata);
},
error: function() {
alert(returneddata.error.stringify);
}
});
}
//Adapted from Jakes's answer here: http://stackoverflow.com/questions/2204250/check-if-checkbox-is-checked-with-jquery
function isCheckedById(id) {
var checked = $("input[id=" + id + "]:checked").length;
return (checked != 0);
}
function populateemails(trampdata) {
// first, clear them all
$("#email1").val('');
$("#email2").val('');
$("#email3").val('');
// Now set those for which there are values
if (trampdata.UnitReportPairEmailVals.length > 0) {
$("#email1").val(trampdata.UnitReportPairEmailVals[0]);
}
if (trampdata.UnitReportPairEmailVals.length > 1) {
$("#email2").val(trampdata.UnitReportPairEmailVals[1]);
}
if (trampdata.UnitReportPairEmailVals.length > 2) {
$("#email3").val(trampdata.UnitReportPairEmailVals[2]);
}
}
function populategeneratevals(generateddata) {
// first, clear them all, if they had been set to something else
$("#dayofmonthselect").val('1st');
$("#ordinalselect").val('First');
$("#dayofweekselect").val('Monday');
$("#weekormonthselect").val('Month');
// Now set those for which there are values
var domOrdinalified = ordinalify(generateddata.generatevals.DayOfMonth);
$("#dayofmonthselect").val(domOrdinalified);
$("#ordinalselect").val(generateddata.generatevals.PatternOrdinal);
$("#dayofweekselect").val(generateddata.generatevals.PatternDOW);
$("#weekormonthselect").val(generateddata.generatevals.PatternInterval);
// Now set the correct radio button
if ($("#dayofmonthselect").val() === 0) {
$("#groupRptGenerationAndSendingByDayOfMonth").prop("checked", true);
} else {
$("#groupRptGenerationAndSendingBasedOnAPattern").prop("checked", true);
}
}
function ordinalify(domint) {
if (domint === 1 || domint === 21 || domint === 31) {
return domint + 'st';
}
if (domint === 2 || domint === 22) {
return domint + 'nd';
}
if (domint === 3 || domint === 23) {
return domint + 'rd';
}
return domint + 'th';
}
function populatedatarangeprams(rptval, returneddata) {
if (rptval === 1) {
// Produce Usage
$("#produsagefrom").val(returneddata.datarangeparams.TimeUnitsFrom);
$("#produsageto").val(returneddata.datarangeparams.TimeUnitsTo);
} else if (rptval === 2) {
// Delivery Performance
$("#delperffrom").val(returneddata.datarangeparams.TimeUnitsFrom);
$("#delperfto").val(returneddata.datarangeparams.TimeUnitsTo);
} else if (rptval === 3) {
// Price Compliance
$("#pricecompliancefrom").val(returneddata.datarangeparams.TimeUnitsFrom);
$("#pricecomplianceto").val(returneddata.datarangeparams.TimeUnitsTo);
} else if (rptval === 4) {
// Fill Rate
$("#fillratefrom").val(returneddata.datarangeparams.TimeUnitsFrom);
$("#fillrateto").val(returneddata.datarangeparams.TimeUnitsTo);
}
// TODO: Add 5 if/when Contract vs Market is added
}
function reinitializeRecipientsAndGenerateVals() {
$("#email1").val('');
$("#email2").val('');
$("#email3").val('');
$("#dayofmonthselect").val('1st');
$("#ordinalselect").val('First');
$("#dayofweekselect").val('Monday');
$("#weekormonthselect").val('Month');
}
Okay, I've tracked it down to this:
foo(); // <- function call
function foo() { // <- function declaration
}
Seem like it's an obscure way to say "Declare function before calling it!" or "Do not rely on hoisting!".
You can fix it by moving function declaration to the top.