SOLVED: jQuery $(this) not recognizing checkbox elements in tr
up vote
0
down vote
favorite
SOLVED: the problem was with my jQuery, but it wasn't a problem with the "this" keywords - it was a problem with how I set up the selectors.
jQuery's native browser event handlers (.change(), .click(), .focus(), and .blur()) will only get attached to elements that exist at the time the jQuery function runs - but not elements which are added after the initial render (at least, not with how I had the selectors set up). Since the table, rows, cells, and checkboxes are all dynamically created via my JS file, I needed to attach an .on() method to the static div (#table_goes_here) wherein my table was dynamically added, and THEN pass the "change" event handler and ":checkbox" selector as method arguments. SO I fixed the problem by changing the jQuery script file to the code below. If you're someone who'd like to learn more about jQuery event handling, this jQuery documentation page is exactly what you need.
<script>
$(document).ready(function() {
$("#table_goes_here").on("change", ":checkbox", function() {
var noticeCountHTML = document.getElementById("noticeCount");
var noticeCount = $("#table_goes_here").find("tr").length;
noticeCountHTML.innerHTML = noticeCount;
if ($(this).is(":checked")) {
noticeCount -= 1;
$(this).closest(".account_data").css("background-color", "rgba(64, 64, 64, 0.7)");
} else {
noticeCount += 1;
$(this).closest(".account_data").css("background-color", "rgba(255, 255, 255, 1)");
}
noticeCountHTML.innerHTML = noticeCount;
})
});
</script>
// --------------------------vvv INITIAL POST vvv--------------------------
I'm trying to use JQuery to highlight dynamically-created rows in a table when a checkbox in that row is unchecked, as well as update a counter element showing how many rows are checked. I'm using Google Apps Scripts, specifically the project is an HTML template output (html, js, and css files). Everything works EXCEPT the row highlighting upon unchecking the box and updating the checked-row-counter (>_<) I've looked everywhere for a solution, but have thus far come up empty. The only thing I can think of is that the $(this) variable in my jquery script file isn't getting set to the checkbox, but I can't use Chrome Dev Tools to watch "this" (unless someone knows a way to do this within GAS...?). Any help that can be offered will be greatly appreciated.
Here's my code.gs...
function openLateAccountsNoticesWindow() {
var htmlTemp = HtmlService.createTemplateFromFile('send_notices/HTML').evaluate();
var html = HtmlService.createHtmlOutput(htmlTemp);
SpreadsheetApp.getUi().showModalDialog(html, 'Send Notices');
};
// INCLUDE creates an import so files can be added inside the main index.
function include(filename){
return HtmlService.createHtmlOutputFromFile(filename).getContent();
};
// The getAccountsWithOpenBal function creates an array of accounts with
// an outstanding balance > $0.
function getAccountsWithOpenBal() {
// Code to get the array of accounts from my spreadsheet goes here,
// but I'll provide a stand-in array below for debugging purposes.
var accounts = [
{Unit: "123 Abc Street", Name: "John Doe", Balance: 500.10},
{Unit: "456 Maple Street", Name: "Mary Jane", Balance: 250.05},
{Unit: "765 Stone Road", Name: "Mark Isaguy", Balance: 1300.45},
{Unit: "999 Nine Avenue", Name: "Lauren Lady", Balance: 45.23}];
var lateAccountsArray = ;
for (var i=0; i < accounts.length; i++) {
if (parseFloat(accounts[i]['Balance']) > 0) {
var balToNum = parseFloat(accounts[i]['Balance']);
var bal2Decimals = balToNum.toFixed(2);
var balWithCommas = bal2Decimals.toString().replace(/B(?=(d{3})+(?!d))/g, ",");
accounts[i]['Balance'] = balWithCommas;
lateAccountsArray.push(accounts[i]);
}
}
return lateAccountsArray;
};
My html...
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<?!= include('send_notices/CSS') ?>
</head>
<body>
<h4 id="header">Accounts with Current Balance Owed:</h4>
<div id="table_goes_here">
</div>
<br>
<h4>Number of Notices to Submit: <span id="noticeCount"></span></h4>
<br>
<button class="action" id="submitButton" onclick="form_data()">Submit</button> <button class="cancel" onclick="google.script.host.close()">Cancel</button>
<br>
</body>
<?!= include('send_notices/JS') ?>
</html>
Here's the script from my js file that generates the table...
<script>
window.onload = function() {
google.script.run.withSuccessHandler(addAccountsData).getAccountsWithOpenBal();
}
function addAccountsData(lateAccountsArray) {
var div = document.getElementById("table_goes_here");
var table = document.createElement("TABLE");
table.setAttribute("id", "debtorList");
var tableBody = document.createElement('TBODY');
table.appendChild(tableBody);
// TABLE HEADERS
// Create header row, and append to table body
var headerRow = document.createElement('TR');
tableBody.appendChild(headerRow);
// Next, create each header cell
// Unit Column Header ("unit" = "address")
var unitTH = document.createElement('TH');
unitTH.setAttribute("style", "width: 25%");
unitTH.appendChild(document.createTextNode("Address"));
// Name Column Header (name of account holder)
var nameTH = document.createElement('TH');
nameTH.setAttribute("style", "width: 22%");
nameTH.appendChild(document.createTextNode("Name"));
// Currency Column Header
var currencyTH = document.createElement('TH');
currencyTH.setAttribute("style", "width: 5%");
currencyTH.appendChild(document.createTextNode(""));
// Balance Column Header
var balanceTH = document.createElement('TH');
balanceTH.setAttribute("style", "width: 5%; text-align: right");
balanceTH.appendChild(document.createTextNode("Balance"));
// Checkbox Column Header
var includeTH = document.createElement('TH');
includeTH.setAttribute("style", "width: 10%; text-align: center");
includeTH.appendChild(document.createTextNode("Include"));
// Append all headers to header row
headerRow.appendChild(unitTH);
headerRow.appendChild(nameTH);
headerRow.appendChild(currencyTH);
headerRow.appendChild(balanceTH);
headerRow.appendChild(includeTH);
// I use getRowCount when filling in the table
// rows in order to attach a unique id attr to
// each row and checkbox.
var rowCount = 0;
function getRowCount() {
rowCount += 1;
return rowCount;
}
// Loop through each account, creating a row for each one.
for (var i=0; i < lateAccountsArray.length; i++) {
var tr = document.createElement("TR");
rowCount = getRowCount();
tr.classList.add("account_data");
tr.setAttribute("id", "row" + rowCount);
// td cell for unit/address
var unitTD = document.createElement("TD");
unitTD.classList.add("account_unit");
unitTD.setAttribute("value", lateAccountsArray[i]["Unit"]);
unitTD.appendChild(document.createTextNode(lateAccountsArray[i]["Address"]));
// td cell for account-holder name
var nameTD = document.createElement("TD");
nameTD.classList.add("name");
nameTD.setAttribute("value", lateAccountsArray[i]["Name"]);
nameTD.appendChild(document.createTextNode(lateAccountsArray[i]["Name"]));
// td cell for $ (to keep them aligned, regardless of the
// number of digits in their balance.
var currencyTD = document.createElement("TD");
currencyTD.classList.add("currency");
currencyTD.appendChild(document.createTextNode("$"));
// td cell for balance amount
var balanceTD = document.createElement("TD");
balanceTD.classList.add("balance");
balanceTD.setAttribute("value", lateAccountsArray[i]["Balance"]);
balanceTD.appendChild(document.createTextNode(lateAccountsArray[i]["Balance"]));
// td cell for checkbox
var checkboxTD = document.createElement("TD");
checkboxTD.classList.add("checkboxTD");
var checkbox = document.createElement("INPUT");
checkbox.classList.add("checkbox");
checkbox.setAttribute("id", "checkbox" + rowCount);
checkbox.setAttribute("type", "checkbox");
checkbox.setAttribute("checked", true);
checkboxTD.appendChild(checkbox);
// Attach all td cells to tr
tr.appendChild(unitTD);
tr.appendChild(nameTD);
tr.appendChild(currencyTD);
tr.appendChild(balanceTD);
tr.appendChild(checkboxTD);
// Attach tr to tableBody
tableBody.appendChild(tr);
// Set the initial count for the number of notices.
if (i == lateAccountsArray.length - 1) {
var noticeCount = document.getElementById("noticeCount");
noticeCount.innerHTML = i;
}
}
div.appendChild(table)
};
</script>
And here's the script from my js file that is SUPPOSED to highlight the closest tr and update #noticeCount when :checkbox is checked...
<script>
$(document).ready(function() {
$(":checkbox").change(function() {
var noticeCountEle = document.getElementById("noticeCount");
var noticeCount = parseFloat(noticeCountEle.text());
if ($(this).is(":checked")) {
noticeCount += 1;
$(this).closest("tr").css("background-color", "rgba(255, 255, 255, 1)");
} else {
noticeCount -= 1;
$(this).closest("tr").css("background-color", "rgba(64, 64, 64, 0.7)");
}
noticeCountEle.innerHTML = noticeCount;
})
});
</script>
I've tried .closest("tr"), .closest(".account_data"), and I've tried getting the ID of the row and passing that, but none of them seem to work. My hunch is that the (this) keyword isn't right, but I'm not sure how to fix it/get around it.
javascript jquery html google-apps-script this
|
show 1 more comment
up vote
0
down vote
favorite
SOLVED: the problem was with my jQuery, but it wasn't a problem with the "this" keywords - it was a problem with how I set up the selectors.
jQuery's native browser event handlers (.change(), .click(), .focus(), and .blur()) will only get attached to elements that exist at the time the jQuery function runs - but not elements which are added after the initial render (at least, not with how I had the selectors set up). Since the table, rows, cells, and checkboxes are all dynamically created via my JS file, I needed to attach an .on() method to the static div (#table_goes_here) wherein my table was dynamically added, and THEN pass the "change" event handler and ":checkbox" selector as method arguments. SO I fixed the problem by changing the jQuery script file to the code below. If you're someone who'd like to learn more about jQuery event handling, this jQuery documentation page is exactly what you need.
<script>
$(document).ready(function() {
$("#table_goes_here").on("change", ":checkbox", function() {
var noticeCountHTML = document.getElementById("noticeCount");
var noticeCount = $("#table_goes_here").find("tr").length;
noticeCountHTML.innerHTML = noticeCount;
if ($(this).is(":checked")) {
noticeCount -= 1;
$(this).closest(".account_data").css("background-color", "rgba(64, 64, 64, 0.7)");
} else {
noticeCount += 1;
$(this).closest(".account_data").css("background-color", "rgba(255, 255, 255, 1)");
}
noticeCountHTML.innerHTML = noticeCount;
})
});
</script>
// --------------------------vvv INITIAL POST vvv--------------------------
I'm trying to use JQuery to highlight dynamically-created rows in a table when a checkbox in that row is unchecked, as well as update a counter element showing how many rows are checked. I'm using Google Apps Scripts, specifically the project is an HTML template output (html, js, and css files). Everything works EXCEPT the row highlighting upon unchecking the box and updating the checked-row-counter (>_<) I've looked everywhere for a solution, but have thus far come up empty. The only thing I can think of is that the $(this) variable in my jquery script file isn't getting set to the checkbox, but I can't use Chrome Dev Tools to watch "this" (unless someone knows a way to do this within GAS...?). Any help that can be offered will be greatly appreciated.
Here's my code.gs...
function openLateAccountsNoticesWindow() {
var htmlTemp = HtmlService.createTemplateFromFile('send_notices/HTML').evaluate();
var html = HtmlService.createHtmlOutput(htmlTemp);
SpreadsheetApp.getUi().showModalDialog(html, 'Send Notices');
};
// INCLUDE creates an import so files can be added inside the main index.
function include(filename){
return HtmlService.createHtmlOutputFromFile(filename).getContent();
};
// The getAccountsWithOpenBal function creates an array of accounts with
// an outstanding balance > $0.
function getAccountsWithOpenBal() {
// Code to get the array of accounts from my spreadsheet goes here,
// but I'll provide a stand-in array below for debugging purposes.
var accounts = [
{Unit: "123 Abc Street", Name: "John Doe", Balance: 500.10},
{Unit: "456 Maple Street", Name: "Mary Jane", Balance: 250.05},
{Unit: "765 Stone Road", Name: "Mark Isaguy", Balance: 1300.45},
{Unit: "999 Nine Avenue", Name: "Lauren Lady", Balance: 45.23}];
var lateAccountsArray = ;
for (var i=0; i < accounts.length; i++) {
if (parseFloat(accounts[i]['Balance']) > 0) {
var balToNum = parseFloat(accounts[i]['Balance']);
var bal2Decimals = balToNum.toFixed(2);
var balWithCommas = bal2Decimals.toString().replace(/B(?=(d{3})+(?!d))/g, ",");
accounts[i]['Balance'] = balWithCommas;
lateAccountsArray.push(accounts[i]);
}
}
return lateAccountsArray;
};
My html...
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<?!= include('send_notices/CSS') ?>
</head>
<body>
<h4 id="header">Accounts with Current Balance Owed:</h4>
<div id="table_goes_here">
</div>
<br>
<h4>Number of Notices to Submit: <span id="noticeCount"></span></h4>
<br>
<button class="action" id="submitButton" onclick="form_data()">Submit</button> <button class="cancel" onclick="google.script.host.close()">Cancel</button>
<br>
</body>
<?!= include('send_notices/JS') ?>
</html>
Here's the script from my js file that generates the table...
<script>
window.onload = function() {
google.script.run.withSuccessHandler(addAccountsData).getAccountsWithOpenBal();
}
function addAccountsData(lateAccountsArray) {
var div = document.getElementById("table_goes_here");
var table = document.createElement("TABLE");
table.setAttribute("id", "debtorList");
var tableBody = document.createElement('TBODY');
table.appendChild(tableBody);
// TABLE HEADERS
// Create header row, and append to table body
var headerRow = document.createElement('TR');
tableBody.appendChild(headerRow);
// Next, create each header cell
// Unit Column Header ("unit" = "address")
var unitTH = document.createElement('TH');
unitTH.setAttribute("style", "width: 25%");
unitTH.appendChild(document.createTextNode("Address"));
// Name Column Header (name of account holder)
var nameTH = document.createElement('TH');
nameTH.setAttribute("style", "width: 22%");
nameTH.appendChild(document.createTextNode("Name"));
// Currency Column Header
var currencyTH = document.createElement('TH');
currencyTH.setAttribute("style", "width: 5%");
currencyTH.appendChild(document.createTextNode(""));
// Balance Column Header
var balanceTH = document.createElement('TH');
balanceTH.setAttribute("style", "width: 5%; text-align: right");
balanceTH.appendChild(document.createTextNode("Balance"));
// Checkbox Column Header
var includeTH = document.createElement('TH');
includeTH.setAttribute("style", "width: 10%; text-align: center");
includeTH.appendChild(document.createTextNode("Include"));
// Append all headers to header row
headerRow.appendChild(unitTH);
headerRow.appendChild(nameTH);
headerRow.appendChild(currencyTH);
headerRow.appendChild(balanceTH);
headerRow.appendChild(includeTH);
// I use getRowCount when filling in the table
// rows in order to attach a unique id attr to
// each row and checkbox.
var rowCount = 0;
function getRowCount() {
rowCount += 1;
return rowCount;
}
// Loop through each account, creating a row for each one.
for (var i=0; i < lateAccountsArray.length; i++) {
var tr = document.createElement("TR");
rowCount = getRowCount();
tr.classList.add("account_data");
tr.setAttribute("id", "row" + rowCount);
// td cell for unit/address
var unitTD = document.createElement("TD");
unitTD.classList.add("account_unit");
unitTD.setAttribute("value", lateAccountsArray[i]["Unit"]);
unitTD.appendChild(document.createTextNode(lateAccountsArray[i]["Address"]));
// td cell for account-holder name
var nameTD = document.createElement("TD");
nameTD.classList.add("name");
nameTD.setAttribute("value", lateAccountsArray[i]["Name"]);
nameTD.appendChild(document.createTextNode(lateAccountsArray[i]["Name"]));
// td cell for $ (to keep them aligned, regardless of the
// number of digits in their balance.
var currencyTD = document.createElement("TD");
currencyTD.classList.add("currency");
currencyTD.appendChild(document.createTextNode("$"));
// td cell for balance amount
var balanceTD = document.createElement("TD");
balanceTD.classList.add("balance");
balanceTD.setAttribute("value", lateAccountsArray[i]["Balance"]);
balanceTD.appendChild(document.createTextNode(lateAccountsArray[i]["Balance"]));
// td cell for checkbox
var checkboxTD = document.createElement("TD");
checkboxTD.classList.add("checkboxTD");
var checkbox = document.createElement("INPUT");
checkbox.classList.add("checkbox");
checkbox.setAttribute("id", "checkbox" + rowCount);
checkbox.setAttribute("type", "checkbox");
checkbox.setAttribute("checked", true);
checkboxTD.appendChild(checkbox);
// Attach all td cells to tr
tr.appendChild(unitTD);
tr.appendChild(nameTD);
tr.appendChild(currencyTD);
tr.appendChild(balanceTD);
tr.appendChild(checkboxTD);
// Attach tr to tableBody
tableBody.appendChild(tr);
// Set the initial count for the number of notices.
if (i == lateAccountsArray.length - 1) {
var noticeCount = document.getElementById("noticeCount");
noticeCount.innerHTML = i;
}
}
div.appendChild(table)
};
</script>
And here's the script from my js file that is SUPPOSED to highlight the closest tr and update #noticeCount when :checkbox is checked...
<script>
$(document).ready(function() {
$(":checkbox").change(function() {
var noticeCountEle = document.getElementById("noticeCount");
var noticeCount = parseFloat(noticeCountEle.text());
if ($(this).is(":checked")) {
noticeCount += 1;
$(this).closest("tr").css("background-color", "rgba(255, 255, 255, 1)");
} else {
noticeCount -= 1;
$(this).closest("tr").css("background-color", "rgba(64, 64, 64, 0.7)");
}
noticeCountEle.innerHTML = noticeCount;
})
});
</script>
I've tried .closest("tr"), .closest(".account_data"), and I've tried getting the ID of the row and passing that, but none of them seem to work. My hunch is that the (this) keyword isn't right, but I'm not sure how to fix it/get around it.
javascript jquery html google-apps-script this
noticeCountEle.text()
isn't valid and is probably throwing error. Look in browser dev tools console
– charlietfl
Nov 12 at 20:26
you can change the scope of the dev tools console and stacktrace to be your GAS hosted webapp. This will work for any iframe or nested function call.
– Jonathon
Nov 12 at 20:30
I tried using dev tools, but with GAS, the source file isn't available (or if it is, I haven't found a way to access it). I first tried noticeCountEle.val() but that didn't work.
– Trevor
Nov 12 at 20:30
Thanks @Jonathon, I'll give that a try.
– Trevor
Nov 12 at 20:31
In Dev Tools, I can only see my code in the Elements tab, not Sources (I think this has something to do with Google's caja sanitization), so unfortunately I still can't see what "this" is getting set to. I don't get why it wouldn't get set to the checkbox given the context, but considering any code I use that involves "this" isn't working, I'm increasingly thinking that's the issue =/
– Trevor
Nov 13 at 15:32
|
show 1 more comment
up vote
0
down vote
favorite
up vote
0
down vote
favorite
SOLVED: the problem was with my jQuery, but it wasn't a problem with the "this" keywords - it was a problem with how I set up the selectors.
jQuery's native browser event handlers (.change(), .click(), .focus(), and .blur()) will only get attached to elements that exist at the time the jQuery function runs - but not elements which are added after the initial render (at least, not with how I had the selectors set up). Since the table, rows, cells, and checkboxes are all dynamically created via my JS file, I needed to attach an .on() method to the static div (#table_goes_here) wherein my table was dynamically added, and THEN pass the "change" event handler and ":checkbox" selector as method arguments. SO I fixed the problem by changing the jQuery script file to the code below. If you're someone who'd like to learn more about jQuery event handling, this jQuery documentation page is exactly what you need.
<script>
$(document).ready(function() {
$("#table_goes_here").on("change", ":checkbox", function() {
var noticeCountHTML = document.getElementById("noticeCount");
var noticeCount = $("#table_goes_here").find("tr").length;
noticeCountHTML.innerHTML = noticeCount;
if ($(this).is(":checked")) {
noticeCount -= 1;
$(this).closest(".account_data").css("background-color", "rgba(64, 64, 64, 0.7)");
} else {
noticeCount += 1;
$(this).closest(".account_data").css("background-color", "rgba(255, 255, 255, 1)");
}
noticeCountHTML.innerHTML = noticeCount;
})
});
</script>
// --------------------------vvv INITIAL POST vvv--------------------------
I'm trying to use JQuery to highlight dynamically-created rows in a table when a checkbox in that row is unchecked, as well as update a counter element showing how many rows are checked. I'm using Google Apps Scripts, specifically the project is an HTML template output (html, js, and css files). Everything works EXCEPT the row highlighting upon unchecking the box and updating the checked-row-counter (>_<) I've looked everywhere for a solution, but have thus far come up empty. The only thing I can think of is that the $(this) variable in my jquery script file isn't getting set to the checkbox, but I can't use Chrome Dev Tools to watch "this" (unless someone knows a way to do this within GAS...?). Any help that can be offered will be greatly appreciated.
Here's my code.gs...
function openLateAccountsNoticesWindow() {
var htmlTemp = HtmlService.createTemplateFromFile('send_notices/HTML').evaluate();
var html = HtmlService.createHtmlOutput(htmlTemp);
SpreadsheetApp.getUi().showModalDialog(html, 'Send Notices');
};
// INCLUDE creates an import so files can be added inside the main index.
function include(filename){
return HtmlService.createHtmlOutputFromFile(filename).getContent();
};
// The getAccountsWithOpenBal function creates an array of accounts with
// an outstanding balance > $0.
function getAccountsWithOpenBal() {
// Code to get the array of accounts from my spreadsheet goes here,
// but I'll provide a stand-in array below for debugging purposes.
var accounts = [
{Unit: "123 Abc Street", Name: "John Doe", Balance: 500.10},
{Unit: "456 Maple Street", Name: "Mary Jane", Balance: 250.05},
{Unit: "765 Stone Road", Name: "Mark Isaguy", Balance: 1300.45},
{Unit: "999 Nine Avenue", Name: "Lauren Lady", Balance: 45.23}];
var lateAccountsArray = ;
for (var i=0; i < accounts.length; i++) {
if (parseFloat(accounts[i]['Balance']) > 0) {
var balToNum = parseFloat(accounts[i]['Balance']);
var bal2Decimals = balToNum.toFixed(2);
var balWithCommas = bal2Decimals.toString().replace(/B(?=(d{3})+(?!d))/g, ",");
accounts[i]['Balance'] = balWithCommas;
lateAccountsArray.push(accounts[i]);
}
}
return lateAccountsArray;
};
My html...
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<?!= include('send_notices/CSS') ?>
</head>
<body>
<h4 id="header">Accounts with Current Balance Owed:</h4>
<div id="table_goes_here">
</div>
<br>
<h4>Number of Notices to Submit: <span id="noticeCount"></span></h4>
<br>
<button class="action" id="submitButton" onclick="form_data()">Submit</button> <button class="cancel" onclick="google.script.host.close()">Cancel</button>
<br>
</body>
<?!= include('send_notices/JS') ?>
</html>
Here's the script from my js file that generates the table...
<script>
window.onload = function() {
google.script.run.withSuccessHandler(addAccountsData).getAccountsWithOpenBal();
}
function addAccountsData(lateAccountsArray) {
var div = document.getElementById("table_goes_here");
var table = document.createElement("TABLE");
table.setAttribute("id", "debtorList");
var tableBody = document.createElement('TBODY');
table.appendChild(tableBody);
// TABLE HEADERS
// Create header row, and append to table body
var headerRow = document.createElement('TR');
tableBody.appendChild(headerRow);
// Next, create each header cell
// Unit Column Header ("unit" = "address")
var unitTH = document.createElement('TH');
unitTH.setAttribute("style", "width: 25%");
unitTH.appendChild(document.createTextNode("Address"));
// Name Column Header (name of account holder)
var nameTH = document.createElement('TH');
nameTH.setAttribute("style", "width: 22%");
nameTH.appendChild(document.createTextNode("Name"));
// Currency Column Header
var currencyTH = document.createElement('TH');
currencyTH.setAttribute("style", "width: 5%");
currencyTH.appendChild(document.createTextNode(""));
// Balance Column Header
var balanceTH = document.createElement('TH');
balanceTH.setAttribute("style", "width: 5%; text-align: right");
balanceTH.appendChild(document.createTextNode("Balance"));
// Checkbox Column Header
var includeTH = document.createElement('TH');
includeTH.setAttribute("style", "width: 10%; text-align: center");
includeTH.appendChild(document.createTextNode("Include"));
// Append all headers to header row
headerRow.appendChild(unitTH);
headerRow.appendChild(nameTH);
headerRow.appendChild(currencyTH);
headerRow.appendChild(balanceTH);
headerRow.appendChild(includeTH);
// I use getRowCount when filling in the table
// rows in order to attach a unique id attr to
// each row and checkbox.
var rowCount = 0;
function getRowCount() {
rowCount += 1;
return rowCount;
}
// Loop through each account, creating a row for each one.
for (var i=0; i < lateAccountsArray.length; i++) {
var tr = document.createElement("TR");
rowCount = getRowCount();
tr.classList.add("account_data");
tr.setAttribute("id", "row" + rowCount);
// td cell for unit/address
var unitTD = document.createElement("TD");
unitTD.classList.add("account_unit");
unitTD.setAttribute("value", lateAccountsArray[i]["Unit"]);
unitTD.appendChild(document.createTextNode(lateAccountsArray[i]["Address"]));
// td cell for account-holder name
var nameTD = document.createElement("TD");
nameTD.classList.add("name");
nameTD.setAttribute("value", lateAccountsArray[i]["Name"]);
nameTD.appendChild(document.createTextNode(lateAccountsArray[i]["Name"]));
// td cell for $ (to keep them aligned, regardless of the
// number of digits in their balance.
var currencyTD = document.createElement("TD");
currencyTD.classList.add("currency");
currencyTD.appendChild(document.createTextNode("$"));
// td cell for balance amount
var balanceTD = document.createElement("TD");
balanceTD.classList.add("balance");
balanceTD.setAttribute("value", lateAccountsArray[i]["Balance"]);
balanceTD.appendChild(document.createTextNode(lateAccountsArray[i]["Balance"]));
// td cell for checkbox
var checkboxTD = document.createElement("TD");
checkboxTD.classList.add("checkboxTD");
var checkbox = document.createElement("INPUT");
checkbox.classList.add("checkbox");
checkbox.setAttribute("id", "checkbox" + rowCount);
checkbox.setAttribute("type", "checkbox");
checkbox.setAttribute("checked", true);
checkboxTD.appendChild(checkbox);
// Attach all td cells to tr
tr.appendChild(unitTD);
tr.appendChild(nameTD);
tr.appendChild(currencyTD);
tr.appendChild(balanceTD);
tr.appendChild(checkboxTD);
// Attach tr to tableBody
tableBody.appendChild(tr);
// Set the initial count for the number of notices.
if (i == lateAccountsArray.length - 1) {
var noticeCount = document.getElementById("noticeCount");
noticeCount.innerHTML = i;
}
}
div.appendChild(table)
};
</script>
And here's the script from my js file that is SUPPOSED to highlight the closest tr and update #noticeCount when :checkbox is checked...
<script>
$(document).ready(function() {
$(":checkbox").change(function() {
var noticeCountEle = document.getElementById("noticeCount");
var noticeCount = parseFloat(noticeCountEle.text());
if ($(this).is(":checked")) {
noticeCount += 1;
$(this).closest("tr").css("background-color", "rgba(255, 255, 255, 1)");
} else {
noticeCount -= 1;
$(this).closest("tr").css("background-color", "rgba(64, 64, 64, 0.7)");
}
noticeCountEle.innerHTML = noticeCount;
})
});
</script>
I've tried .closest("tr"), .closest(".account_data"), and I've tried getting the ID of the row and passing that, but none of them seem to work. My hunch is that the (this) keyword isn't right, but I'm not sure how to fix it/get around it.
javascript jquery html google-apps-script this
SOLVED: the problem was with my jQuery, but it wasn't a problem with the "this" keywords - it was a problem with how I set up the selectors.
jQuery's native browser event handlers (.change(), .click(), .focus(), and .blur()) will only get attached to elements that exist at the time the jQuery function runs - but not elements which are added after the initial render (at least, not with how I had the selectors set up). Since the table, rows, cells, and checkboxes are all dynamically created via my JS file, I needed to attach an .on() method to the static div (#table_goes_here) wherein my table was dynamically added, and THEN pass the "change" event handler and ":checkbox" selector as method arguments. SO I fixed the problem by changing the jQuery script file to the code below. If you're someone who'd like to learn more about jQuery event handling, this jQuery documentation page is exactly what you need.
<script>
$(document).ready(function() {
$("#table_goes_here").on("change", ":checkbox", function() {
var noticeCountHTML = document.getElementById("noticeCount");
var noticeCount = $("#table_goes_here").find("tr").length;
noticeCountHTML.innerHTML = noticeCount;
if ($(this).is(":checked")) {
noticeCount -= 1;
$(this).closest(".account_data").css("background-color", "rgba(64, 64, 64, 0.7)");
} else {
noticeCount += 1;
$(this).closest(".account_data").css("background-color", "rgba(255, 255, 255, 1)");
}
noticeCountHTML.innerHTML = noticeCount;
})
});
</script>
// --------------------------vvv INITIAL POST vvv--------------------------
I'm trying to use JQuery to highlight dynamically-created rows in a table when a checkbox in that row is unchecked, as well as update a counter element showing how many rows are checked. I'm using Google Apps Scripts, specifically the project is an HTML template output (html, js, and css files). Everything works EXCEPT the row highlighting upon unchecking the box and updating the checked-row-counter (>_<) I've looked everywhere for a solution, but have thus far come up empty. The only thing I can think of is that the $(this) variable in my jquery script file isn't getting set to the checkbox, but I can't use Chrome Dev Tools to watch "this" (unless someone knows a way to do this within GAS...?). Any help that can be offered will be greatly appreciated.
Here's my code.gs...
function openLateAccountsNoticesWindow() {
var htmlTemp = HtmlService.createTemplateFromFile('send_notices/HTML').evaluate();
var html = HtmlService.createHtmlOutput(htmlTemp);
SpreadsheetApp.getUi().showModalDialog(html, 'Send Notices');
};
// INCLUDE creates an import so files can be added inside the main index.
function include(filename){
return HtmlService.createHtmlOutputFromFile(filename).getContent();
};
// The getAccountsWithOpenBal function creates an array of accounts with
// an outstanding balance > $0.
function getAccountsWithOpenBal() {
// Code to get the array of accounts from my spreadsheet goes here,
// but I'll provide a stand-in array below for debugging purposes.
var accounts = [
{Unit: "123 Abc Street", Name: "John Doe", Balance: 500.10},
{Unit: "456 Maple Street", Name: "Mary Jane", Balance: 250.05},
{Unit: "765 Stone Road", Name: "Mark Isaguy", Balance: 1300.45},
{Unit: "999 Nine Avenue", Name: "Lauren Lady", Balance: 45.23}];
var lateAccountsArray = ;
for (var i=0; i < accounts.length; i++) {
if (parseFloat(accounts[i]['Balance']) > 0) {
var balToNum = parseFloat(accounts[i]['Balance']);
var bal2Decimals = balToNum.toFixed(2);
var balWithCommas = bal2Decimals.toString().replace(/B(?=(d{3})+(?!d))/g, ",");
accounts[i]['Balance'] = balWithCommas;
lateAccountsArray.push(accounts[i]);
}
}
return lateAccountsArray;
};
My html...
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<?!= include('send_notices/CSS') ?>
</head>
<body>
<h4 id="header">Accounts with Current Balance Owed:</h4>
<div id="table_goes_here">
</div>
<br>
<h4>Number of Notices to Submit: <span id="noticeCount"></span></h4>
<br>
<button class="action" id="submitButton" onclick="form_data()">Submit</button> <button class="cancel" onclick="google.script.host.close()">Cancel</button>
<br>
</body>
<?!= include('send_notices/JS') ?>
</html>
Here's the script from my js file that generates the table...
<script>
window.onload = function() {
google.script.run.withSuccessHandler(addAccountsData).getAccountsWithOpenBal();
}
function addAccountsData(lateAccountsArray) {
var div = document.getElementById("table_goes_here");
var table = document.createElement("TABLE");
table.setAttribute("id", "debtorList");
var tableBody = document.createElement('TBODY');
table.appendChild(tableBody);
// TABLE HEADERS
// Create header row, and append to table body
var headerRow = document.createElement('TR');
tableBody.appendChild(headerRow);
// Next, create each header cell
// Unit Column Header ("unit" = "address")
var unitTH = document.createElement('TH');
unitTH.setAttribute("style", "width: 25%");
unitTH.appendChild(document.createTextNode("Address"));
// Name Column Header (name of account holder)
var nameTH = document.createElement('TH');
nameTH.setAttribute("style", "width: 22%");
nameTH.appendChild(document.createTextNode("Name"));
// Currency Column Header
var currencyTH = document.createElement('TH');
currencyTH.setAttribute("style", "width: 5%");
currencyTH.appendChild(document.createTextNode(""));
// Balance Column Header
var balanceTH = document.createElement('TH');
balanceTH.setAttribute("style", "width: 5%; text-align: right");
balanceTH.appendChild(document.createTextNode("Balance"));
// Checkbox Column Header
var includeTH = document.createElement('TH');
includeTH.setAttribute("style", "width: 10%; text-align: center");
includeTH.appendChild(document.createTextNode("Include"));
// Append all headers to header row
headerRow.appendChild(unitTH);
headerRow.appendChild(nameTH);
headerRow.appendChild(currencyTH);
headerRow.appendChild(balanceTH);
headerRow.appendChild(includeTH);
// I use getRowCount when filling in the table
// rows in order to attach a unique id attr to
// each row and checkbox.
var rowCount = 0;
function getRowCount() {
rowCount += 1;
return rowCount;
}
// Loop through each account, creating a row for each one.
for (var i=0; i < lateAccountsArray.length; i++) {
var tr = document.createElement("TR");
rowCount = getRowCount();
tr.classList.add("account_data");
tr.setAttribute("id", "row" + rowCount);
// td cell for unit/address
var unitTD = document.createElement("TD");
unitTD.classList.add("account_unit");
unitTD.setAttribute("value", lateAccountsArray[i]["Unit"]);
unitTD.appendChild(document.createTextNode(lateAccountsArray[i]["Address"]));
// td cell for account-holder name
var nameTD = document.createElement("TD");
nameTD.classList.add("name");
nameTD.setAttribute("value", lateAccountsArray[i]["Name"]);
nameTD.appendChild(document.createTextNode(lateAccountsArray[i]["Name"]));
// td cell for $ (to keep them aligned, regardless of the
// number of digits in their balance.
var currencyTD = document.createElement("TD");
currencyTD.classList.add("currency");
currencyTD.appendChild(document.createTextNode("$"));
// td cell for balance amount
var balanceTD = document.createElement("TD");
balanceTD.classList.add("balance");
balanceTD.setAttribute("value", lateAccountsArray[i]["Balance"]);
balanceTD.appendChild(document.createTextNode(lateAccountsArray[i]["Balance"]));
// td cell for checkbox
var checkboxTD = document.createElement("TD");
checkboxTD.classList.add("checkboxTD");
var checkbox = document.createElement("INPUT");
checkbox.classList.add("checkbox");
checkbox.setAttribute("id", "checkbox" + rowCount);
checkbox.setAttribute("type", "checkbox");
checkbox.setAttribute("checked", true);
checkboxTD.appendChild(checkbox);
// Attach all td cells to tr
tr.appendChild(unitTD);
tr.appendChild(nameTD);
tr.appendChild(currencyTD);
tr.appendChild(balanceTD);
tr.appendChild(checkboxTD);
// Attach tr to tableBody
tableBody.appendChild(tr);
// Set the initial count for the number of notices.
if (i == lateAccountsArray.length - 1) {
var noticeCount = document.getElementById("noticeCount");
noticeCount.innerHTML = i;
}
}
div.appendChild(table)
};
</script>
And here's the script from my js file that is SUPPOSED to highlight the closest tr and update #noticeCount when :checkbox is checked...
<script>
$(document).ready(function() {
$(":checkbox").change(function() {
var noticeCountEle = document.getElementById("noticeCount");
var noticeCount = parseFloat(noticeCountEle.text());
if ($(this).is(":checked")) {
noticeCount += 1;
$(this).closest("tr").css("background-color", "rgba(255, 255, 255, 1)");
} else {
noticeCount -= 1;
$(this).closest("tr").css("background-color", "rgba(64, 64, 64, 0.7)");
}
noticeCountEle.innerHTML = noticeCount;
})
});
</script>
I've tried .closest("tr"), .closest(".account_data"), and I've tried getting the ID of the row and passing that, but none of them seem to work. My hunch is that the (this) keyword isn't right, but I'm not sure how to fix it/get around it.
javascript jquery html google-apps-script this
javascript jquery html google-apps-script this
edited Nov 14 at 15:54
asked Nov 12 at 19:52
Trevor
13
13
noticeCountEle.text()
isn't valid and is probably throwing error. Look in browser dev tools console
– charlietfl
Nov 12 at 20:26
you can change the scope of the dev tools console and stacktrace to be your GAS hosted webapp. This will work for any iframe or nested function call.
– Jonathon
Nov 12 at 20:30
I tried using dev tools, but with GAS, the source file isn't available (or if it is, I haven't found a way to access it). I first tried noticeCountEle.val() but that didn't work.
– Trevor
Nov 12 at 20:30
Thanks @Jonathon, I'll give that a try.
– Trevor
Nov 12 at 20:31
In Dev Tools, I can only see my code in the Elements tab, not Sources (I think this has something to do with Google's caja sanitization), so unfortunately I still can't see what "this" is getting set to. I don't get why it wouldn't get set to the checkbox given the context, but considering any code I use that involves "this" isn't working, I'm increasingly thinking that's the issue =/
– Trevor
Nov 13 at 15:32
|
show 1 more comment
noticeCountEle.text()
isn't valid and is probably throwing error. Look in browser dev tools console
– charlietfl
Nov 12 at 20:26
you can change the scope of the dev tools console and stacktrace to be your GAS hosted webapp. This will work for any iframe or nested function call.
– Jonathon
Nov 12 at 20:30
I tried using dev tools, but with GAS, the source file isn't available (or if it is, I haven't found a way to access it). I first tried noticeCountEle.val() but that didn't work.
– Trevor
Nov 12 at 20:30
Thanks @Jonathon, I'll give that a try.
– Trevor
Nov 12 at 20:31
In Dev Tools, I can only see my code in the Elements tab, not Sources (I think this has something to do with Google's caja sanitization), so unfortunately I still can't see what "this" is getting set to. I don't get why it wouldn't get set to the checkbox given the context, but considering any code I use that involves "this" isn't working, I'm increasingly thinking that's the issue =/
– Trevor
Nov 13 at 15:32
noticeCountEle.text()
isn't valid and is probably throwing error. Look in browser dev tools console– charlietfl
Nov 12 at 20:26
noticeCountEle.text()
isn't valid and is probably throwing error. Look in browser dev tools console– charlietfl
Nov 12 at 20:26
you can change the scope of the dev tools console and stacktrace to be your GAS hosted webapp. This will work for any iframe or nested function call.
– Jonathon
Nov 12 at 20:30
you can change the scope of the dev tools console and stacktrace to be your GAS hosted webapp. This will work for any iframe or nested function call.
– Jonathon
Nov 12 at 20:30
I tried using dev tools, but with GAS, the source file isn't available (or if it is, I haven't found a way to access it). I first tried noticeCountEle.val() but that didn't work.
– Trevor
Nov 12 at 20:30
I tried using dev tools, but with GAS, the source file isn't available (or if it is, I haven't found a way to access it). I first tried noticeCountEle.val() but that didn't work.
– Trevor
Nov 12 at 20:30
Thanks @Jonathon, I'll give that a try.
– Trevor
Nov 12 at 20:31
Thanks @Jonathon, I'll give that a try.
– Trevor
Nov 12 at 20:31
In Dev Tools, I can only see my code in the Elements tab, not Sources (I think this has something to do with Google's caja sanitization), so unfortunately I still can't see what "this" is getting set to. I don't get why it wouldn't get set to the checkbox given the context, but considering any code I use that involves "this" isn't working, I'm increasingly thinking that's the issue =/
– Trevor
Nov 13 at 15:32
In Dev Tools, I can only see my code in the Elements tab, not Sources (I think this has something to do with Google's caja sanitization), so unfortunately I still can't see what "this" is getting set to. I don't get why it wouldn't get set to the checkbox given the context, but considering any code I use that involves "this" isn't working, I'm increasingly thinking that's the issue =/
– Trevor
Nov 13 at 15:32
|
show 1 more comment
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53269166%2fsolved-jquery-this-not-recognizing-checkbox-elements-in-tr%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
noticeCountEle.text()
isn't valid and is probably throwing error. Look in browser dev tools console– charlietfl
Nov 12 at 20:26
you can change the scope of the dev tools console and stacktrace to be your GAS hosted webapp. This will work for any iframe or nested function call.
– Jonathon
Nov 12 at 20:30
I tried using dev tools, but with GAS, the source file isn't available (or if it is, I haven't found a way to access it). I first tried noticeCountEle.val() but that didn't work.
– Trevor
Nov 12 at 20:30
Thanks @Jonathon, I'll give that a try.
– Trevor
Nov 12 at 20:31
In Dev Tools, I can only see my code in the Elements tab, not Sources (I think this has something to do with Google's caja sanitization), so unfortunately I still can't see what "this" is getting set to. I don't get why it wouldn't get set to the checkbox given the context, but considering any code I use that involves "this" isn't working, I'm increasingly thinking that's the issue =/
– Trevor
Nov 13 at 15:32