I have a table that has a header with a checkbox in that row. The data gets dynamically added in the table with javascript. Now checking on the checkbox that is in the header row checks or unchecks all the checkboxes of all rows.. I have done it till here in the method "checkUncheck()", i.e.:
<input type="checkbox" id="chkAppId" onclick="checkUncheck()"/>
But now, suppose there are 10 records dynamically added in the table. I have checked the main checkbox in the header. After that, I uncheck one of the checkboxes, e.g.: on the 10th row, then the checkbox of the header must be unchecked....and if I check all of the 10 rows of checkboxes manually, then the checkbox of main header must be checked. This is something normally observed in Yahoo, gmail, etc...
One way would be to count the number of checked ones and compare it with the total number of rows, and if found equal, then check the main one; otherwise, uncheck the main one. But I can't figure out where to do that... not working!
Update
<html>
<head><title>Checkbox puzzle</title></head>
<body>
<input type="checkbox" id="chkAppId" onclick="checkUncheck()"/>Main<br/>
<input type="checkbox" id="chkAppId1" onclick="check()"/>chk1<br/>
<input type="checkbox" id="chkAppId2" onclick="check()"/>chk2<br/>
<input type="checkbox" id="chkAppId3" onclick="check()"/>chk3<br/>
<script type="text/javascript">
function checkUncheck()
{
var totalRows = 4;
if(document.getElementById("chkAppId").checked){
checkedAll = true;
}
else{
checkedAll = false;
}
for(i = 1; i< totalRows; i++){
document.getElementById("chkAppId"+i).checked = checkedAll;
}
}
function check()
{
var totalRows = 4,count=0;
for(i = 1; i< totalRows; i++) {
if(document.getElementById("chkAppId"+i).checked){
count= count+1;
}
}
if(count ==totalRows - 1){
//alert("check Main");
document.getElementById("chkAppId").checked = true;
}
else
{
//alert("uncheck Main");
document.getElementById("chkAppId").checked = false;
}
}
</script>
</body>
</html>
This would be a simpler version that can explain the purpose, for anyone else who may need to implement such things.
When you dynamically insert the checkboxes, do you give them each different IDs?
Post the code you have and someone may be able to help you.
Here's a self-contained example with 'dynamic' rows.
<HTML>
<input type="button" value="add row" onclick="add_row()">
<table border id="my_table">
<TR><TH><input type="checkbox" onclick="header_check_click()" id="header_check"></TH><TH>HEADER</TH></TR>
</table>
<FORM name="frm">
<script language="javascript">
var g_check_ids = [];
function header_check_click()
{
var header_check = document.getElementById("header_check");
for (var k in g_check_ids)
{
var the_check = document.getElementById("check" + g_check_ids[k]);
the_check.checked = header_check.checked;
}
}
function fix_header_checkbox()
{
var all_checked = true;
for (var k in g_check_ids)
{
var the_check = document.getElementById("check" + g_check_ids[k]);
if (!the_check.checked)
{ all_checked = false;
}
}
var header_check = document.getElementById("header_check");
header_check.checked = all_checked;
}
function add_row()
{
var tbl = document.getElementById("my_table");
var cnt = tbl.rows.length;
var row = tbl.insertRow(cnt);
var checkCell = row.insertCell(0);
checkCell.innerHTML = "<input onclick=\"fix_header_checkbox()\" type=\"checkbox\" id=check" + cnt + ">";
g_check_ids.push(cnt);
var txtCell = row.insertCell(1);
txtCell.innerHTML = "Cell " + cnt;
fix_header_checkbox();
}
add_row();
</script>
</FORM>
</HTML>
Related
I have this problem here
The problem has been solved, but my question is how can I get the second value from that, or the third one. The sheet will have many tables and at some point I will need a total for each table. Also, is there any solution to automatically find the the array number which contain date row for each table (instead defining this manually). Hope my explanation make sense.
Thank you!
Kind regards,
L.E. Test file
If I understood your question correctly, instead of breaking the loop when a match to "Total" is found do whatever is needed to be done within the loop like so...
var today = toDateFormat(new Date());
var todaysColumn =
values[5].map(toDateFormat).map(Number).indexOf(+today);
var emailDate = Utilities.formatDate(new Date(today),"GMT+1",
"dd/MM/yyyy");
for (var i=0; i<values.length; i++){
if (values[i][0]=='Total'){
nr = i;
Logger.log(nr);
var output = values[nr][todaysColumn];
// Do something with the output here I"m assuming you email it
}
}
The loop will keep going and find every "Total" and do the same thing. This answer assumes that the "Totals" are in the same column. You can get fancier with this if you only want certain tables to send and not others, but this should get you started.
I didn't quite understand the second part of your question...
"Also, is there any solution to automatically find the the array
number which contain date row for each table (instead defining this
manually). Hope my explanation make sense."
I'm guessing you want all the rows that contain "Total" in the specific column. You could instantiate a variable as an empty array like so, var totals = [];. Then instead of sending the email or whatever in the first loop you would push the row values to the array like so, totals.push(nr+1) . //adding 1 gives you the actual row number (rows count from 1 but arrays count from 0). You could then simply loop through the totals array and do whatever you wanted to do. Alternatively you could create an array of all the values instead of row numbers like totals.push(values[nr][todaysColumn]) and loop through that array. Lots of ways to solve this problem!
Ok based on our conversation below I've edited the "test" sheet and updated the code. Below are my edits
All edits have been made in your test sheet and verified working in Logger. Let me know if you have any questions.
Spreadsheet:
Added "Validation" Tab
Edited "Table" tab so the row with "Email Address" in Column A lines up with the desired lookup values (dates or categories)...this was only for the first two tables as all the others already had this criteria.
Code:
Create table/category selector...
In the editor go to File >> New >> HTMLfile
Name the file "inputHTML"
Copy and paste the following code into that file
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form class="notice_form" autocomplete="off" onsubmit="formSubmit(this)" target="hidden_iframe">
<select id="tables" onchange="hideunhideCatagory(this.value)" required></select>
<p></p>
<select id="categories" style="display:none"></select>
<hr/>
<button class="submit" type="submit">Get Total</button>
</form>
<script>
window.addEventListener('load', function() {
console.log('Page is loaded');
});
</script>
<script
src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
// The code in this function runs when the page is loaded.
$(function() {
var tableRunner = google.script.run.withSuccessHandler(buildTableList);
var catagoryRunner = google.script.run.withSuccessHandler(buildCatagoryList);
tableRunner.getTables();
catagoryRunner.getCategories();
});
function buildTableList(tables) {
var list = $('#tables');
list.empty();
list.append('<option></option>');
for (var i = 0; i < tables.length; i++) {
if(tables[i]==''){break;}
list.append('<option>' + tables[i] + '</option>');
}
}
function buildCatagoryList(categories) {
var list = $('#categories');
list.empty();
list.append('<option></option>');
for (var i = 0; i < categories.length; i++) {
if(categories[i]==''){break;}
list.append('<option>' + categories[i] + '</option>');
}
}
function hideunhideCatagory(tableValue){
var catElem = document.getElementById("categories");
if(tableValue == "Total Calls By Date" || tableValue == "Total Appointments by Date"){
catElem.style.display = "none"
document.required = false;
}else{
catElem.style.display = "block"
document.required = true;
}
}
function formSubmit(argTheFormElement) {
var table = $("select[id=tables]").val(),
catagory = $("select[id=categories]").val();
console.log(table)
google.script.run
.withSuccessHandler(google.script.host.close)
.getTotal(table,catagory);
}
</script>
</body>
<div id="hiframe" style="display:block; visibility:hidden; float:right">
<iframe name="hidden_iframe" height="0px" width="0px" ></iframe>
</div>
</html>
Edits to Code.gs file
Replace code in Code.gs with this...
//This is a simple trigger that creates the menu item in your sheet
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Run Scripts Manually')
.addItem('Get Total','fncOpenMyDialog')
.addToUi();
}
//This function launches the dialog and is launched by the menu item
function fncOpenMyDialog() {
//Open a dialog
var htmlDlg = HtmlService.createHtmlOutputFromFile('inputHTML')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(200)
.setHeight(150);
SpreadsheetApp.getUi()
.showModalDialog(htmlDlg, 'Select table to get total for');
};
//main function called by clicking "Get Total" on the dialogue...variables are passed to this function from the formSubmit in the inputHTML javascript
function getTotal(table,catagory) {
function toDateFormat(date) {
try {return date.setHours(0,0,0,0);}
catch(e) {return;}
}
//get all values
var values = SpreadsheetApp
.openById("10pB0jDPG8HYolECQ3eg1lrOFjXQ6JRFwQ-llvdE2yuM")
.getSheetByName("Tables")
.getDataRange()
.getValues();
//declare/instantiate your variables
var tableHeaderRow, totalRow, tableFound = false;
//begin loop through column A in Tables Sheet
for (var i = 0; i<values.length; i++){
//test to see if values have already been found if so break the loop
if(tableFound == true){break;}
//check to see if value matches selected table
if (values[i][0]==table){
//start another loop immediately after the match row
for(var x=i+1; x<values.length; x++){
if(values[x][0] == "Email Address"){ //This header needs to consistantly denote the row that contains the headers
tableHeaderRow = x;
tableFound = true;
}else if(values[x][0] == "Total"){
totalRow = x;
break;
}
}
}
}
Logger.log("Header Row = "+tableHeaderRow)
Logger.log("Total Row = "+ totalRow)
var today = toDateFormat(new Date())
var columnToTotal;
if(catagory==''){
columnToTotal = values[tableHeaderRow].map(toDateFormat).map(Number).indexOf(+today);
}else{
columnToTotal = values[tableHeaderRow].indexOf(catagory);
}
var output = values[totalRow][columnToTotal];
Logger.log(output);
var emailDate = Utilities.formatDate(new Date(today),"GMT+1", "dd/MM/yyyy");
//here is where you would put your code to do something with the output
}
/** The functions below are used by the form to populate the selects **/
function getTables(){
var cFile = SpreadsheetApp.getActive();
var cSheet = cFile.getSheetByName('Validation');
var cSheetHeader = cSheet.getRange(1,1,cSheet.getLastRow(),cSheet.getLastColumn()).getValues().shift();
var tabelCol = (cSheetHeader.indexOf("Tables")+1);
var tables = cSheet.getRange(2,tabelCol,cSheet.getLastRow(),1).getValues();
return tables.filter(function (elem){
return elem != "";
});
}
function getCatagories(){
var cFile = SpreadsheetApp.getActive();
var cSheet = cFile.getSheetByName('Validation');
var cSheetHeader = cSheet.getRange(1,1,cSheet.getLastRow(),cSheet.getLastColumn()).getValues().shift();
var catagoriesCol = (cSheetHeader.indexOf("Catagory")+1);
var catagories = cSheet.getRange(2,catagoriesCol,cSheet.getLastRow(),1).getValues();
return catagories.filter(function (elem){
return elem != "";
});
}
As below code, i can uncheck another rows radiobuttons. But i need to uncheck only which first column values are same in gridview.
<script language="javascript" type="text/javascript">
function SelectSingleRadiobutton(rdbtnid) {
var rdBtn = document.getElementById(rdbtnid);
var rdBtnList = document.getElementsByTagName("input");
for (i = 0; i < rdBtnList.length; i++) {
if (rdBtnList[i].type == "radio" && rdBtnList[i].id != rdBtn.id)
{
rdBtnList[i].checked = false;
}
}
}
</script>
For example in this img when i click the (first row) "Teklif-2"
then i want to try uncheck only which first column values are "5555763648"
My grid structure is same with this example.
I managed to save the text that is in the input field but the problem is that i do not know how to save the button. The buttons turn white when i click on them and the price of that seat will be visible in the input field. The price saves but the button does not stay white.
<script>
function changeBlue(element) {
var backgroundColor = element.style.background;
if (backgroundColor == "white") {
element.style.background = "blue";
add(-7.5)
} else {
element.style.background = "white";
add(7.5)
}
}
function add(val) {
var counter = document.getElementById('testInput').value;
var b = parseFloat(counter,10) + val;
if (b < 0) {
b = 0;
}
document.getElementById('testInput').value = b;
return b;
}
function save(){
var fieldValue = document.getElementById("testInput").value;
localStorage.setItem("text", fieldValue)
var buttonStorage = document.getElementsByClass("blauw").value;
localStorage.setItem("button", buttonStorage)
}
function load(){
var storedValue = localStorage.getItem("text");
if(storedValue){
document.getElementById("testInput").value = storedValue;
}
var storedButton = localStorage.getItem("button");
if(storedButton){
document.getElementsByClass("blauw").value = storedButton;
}
}
</script>
<body onload="load()">
<input type="text" id="testInput"/>
<input type="button" id="testButton" value="Save" onclick="save()"/>
<input class="blauw" type="button" id="testButton2" value="click me to turn white"
style="background-color:blue" onclick="changeBlue(this)">
<input class="blauw" type="button" id="testButton2" value="click me to turn white"style="background-color:blue" onclick="changeBlue(this)">
</body>
i made a small sample of what i want to do. And i do not want to use the Id's of the buttons because i have like 500 of them in a table.
That's because getElementsByClass (it's getElementsByClassName btw) returns a node list of all the elements with that class.
To make it work, you need to go through all the items in the list, using a for-loop, and set the value of each individual element to the localStorage-value.
See these links for more information:
Link 1
Link 2
Very small mockup to give you an idea:
(In the JS, I put in comments the lines of code you would be using for your situation.)
function changeValues() {
var list = document.getElementsByClassName("child"); //var list = document.getElementsByClassName("blauw");
for (var i=0; i<list.length; i++) {
list[i].innerHTML = "Milk"; //list[i].value = storedButton;
}
}
<ul class="example">
<li class="child">Coffee</li>
<li class="child">Tea</li>
</ul>
<p>Click the button to change the text of the first list item (index 0).</p>
<button onclick="changeValues()">Try it</button>
I got a table that has an entry that looks like this:
<tr>
<td><input type="checkbox" name="ids[]"/><a style="cursor: pointer;" onclick="addtopath('parameter1', 'parameter2')" class="btn_addpath"> Add</a></td>
</tr>
As you can see every table entry countains the function "addtopath('parameter1', 'paramter2');"
The parameters are generated via php; so each item is different. Also, every entry has a checkbox. This is where the trouble occurs.
I want to create a function that runs the "addtopath" function for every table item, that is checked, as if the user clicked the "Add" button.
Hope it makes sense.
Modern browsers...
function runChecked() {
var links = mytable.querySelectorAll("input[name='ids[]']:checked + a.btn_addpath");
[].forEach.call(links, function(link) {
link.onclick();
});
}
IE8+...
function runChecked() {
var inputs = mytable.querySelectorAll("input[name='ids[]']");
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].checked)
inputs[i].nextSibling.onclick();
}
}
IE6+...
function runChecked() {
var inputs = mytable.getElementsByTagName("input");
for (var i = 0, len = inputs.length; i < len; i++) {
if (inputs[i].name === "ids[]" && inputs[i].checked)
inputs[i].nextSibling.onclick();
}
}
I would add the parameters to data attributes in case you want to move to jQuery at some point. It's also good practice.
<td><input type="checkbox" data-one="one" data-two="two" class="btn_addpath"/>Add</td>
<td><input type="checkbox" data-one="three" data-two="four" class="btn_addpath"/>Add</td>
<td><input type="checkbox" data-one="five" data-two="six" class="btn_addpath"/>Add</td>
<td><input type="checkbox" data-one="seven" data-two="eight" class="btn_addpath"/>Add</td>
function addToPath(p1, p2) {
console.log(p1, p2);
}
var checkboxes = document.getElementsByClassName('btn_addpath');
var checkboxArr = [].slice.call(checkboxes);
checkboxArr.forEach(function (el) {
var p1 = el.getAttribute('data-one');
var p2 = el.getAttribute('data-two');
el.onchange = function () {
if (this.checked) { addToPath(p1, p2); }
};
});
If you use jQuery you can use the following code:
$("input[type=checkbox]:checked").siblings('a').click();
Test it at http://jsfiddle.net/tMe46/
This should emulate onClick event at all links in checked boxes
$("input[type=checkbox]:checked + a").click();
I have dynamic multiple check boxes which is used to restore multiple files. It works perfectly when I have more than 1 check boxes. Here is my php code for check boxes:
<form name="RestoreFile">
<input type="checkbox" title="'.$FldDoc['FldDocumentName'].'" name="restore_checkbox" value="'.$FldDoc['FldDocumentID'].'" id="restore_'.$NodeId.'_'.$FldDoc['FldDocumentID'].'"/>
<input type="button" value="Restore" onclick="RestoreDocFile(\''.$NodeId.'\',this.form.restore_checkbox);" />
</form>
And the definition of function RestoreDocFile() is given below:
function getSelected(opt)
{
var selected = new Array();
var index = 0;
for (var intLoop = 0; intLoop < opt.length; intLoop++) {
if (opt[intLoop].checked)
{
index = selected.length;
selected[index] = new Object;
selected[index].value = opt[intLoop].value;
selected[index].index = intLoop;
}
}
return selected;
}
function RestoreDocFile(nodeid, opt)
{
var getSelectDocIds = getSelected(opt);
//alert(nodeid+','+getSelectDocIds);
var strSelectedDocIds = "";
var i=0;
for (var item in getSelectDocIds)
{
if(i!=0)
{
strSelectedDocIds+=":";
}
strSelectedDocIds += getSelectDocIds[item].value ;
i++;
}
}
The problem is that if there has 1 checkbox at the time of form load it doesn't work properly.
Try replacing
onclick="RestoreDocFile(\''.$NodeId.'\',this.form.restore_checkbox);"
with
onclick="RestoreDocFile(\''.$NodeId.'\',this.form.getElementsByName(\'restore_checkbox\'));"
This will ensure you get a NodeList regardless of how many checkboxes there are.