-1

I am trying to piece together a Google Apps script for a touchscreen clocking in system, and that involves generating some buttons from an array taken from a spreadsheet, but I'm getting a bit lost working out how to get the script to document which of these automatically generated buttons has been pressed.

Basically, I am using a modified version of this script (https://www.youtube.com/watch?v=KGhGWuTjJwc) - I need it to work with a touch screen.

I have got a version of the script given in the video above working. But because the web app must work on a touch screen I need to be able to generate buttons for the input of staff ID and PIN to replace the text boxes.

To do this I am pulling in an array from a Google Sheet that contains all staff initials needed to log in, as well as adding a numeric keypad to enter a PIN.

I have (sort of) successfully borrowed a keypad from here:https://github.com/ProgrammingHero1/batch5-pin-matcher-solution but I am stuck trying to get use buttons for the staff ID input.

I have managed to generate the buttons from the spreadsheet array, using a modified version of this Create an array of buttons from Javascript array but I can't work out how to set staffid to match whichever of the auto-generated buttons was pressed last. Currently those buttons don't do anything.

If anyone can help guide me the last step of the way so that staffid is set using the buttons and not using the text box that would be very much appreciated.

Below is the code I am using. I am aware that it is a dog's breakfast - that's because I am hacking it together from various sources working at (well, realistically well beyond) the limits of my understanding!

Anyway, here is the HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

    <!-- Metro 4 -->
    <link rel="stylesheet" href="https://cdn.metroui.org.ua/v4/css/metro-all.min.css">
        <style>
      .main-box {
         max-width:500px;

      }

      .error-message {

        background:red;
        color:white
        padding: 1000px;
        border-radius: 1000px;

      }

      </style>

  </head>

  <body>

      <div class="container">

        <div class="container d-flex flex-justify-center pt-9">
      <div data-role="panel" class="main-box">
    <form id="main-form">
 
       <div class="form-group">
      

         

               
               <input type="text" data-role="input" data-prepend="Staff ID" id="staffid"> 

            
         
  
<div class="form-group">
  
  
  
  </div>

      <div class="form-group">

       
           
        <button id="start-work" class="button success" type="submit" data-action="Start work">Start work</button>
        <button id="finish-work" class="button success" type="submit" data-action="Finish work">Finish work</button>
        <button id="start-break" class="button success" type="submit" data-action="Start break">Start break</button>
        <button id="finish-break" class="button success" type="submit" data-action="Finish break">Finish break</button>
        
<div class="input-section half-width">
                    <input id="typed-numbers" class="form-control" type="text">
                    <div class="numbers">
                        <div id="key-pad" class="calc-body">
                            <div class="calc-button-row">
                                <div class="button">7</div>
                                <div class="button">8</div>
                                <div class="button">9</div>
                            </div>
                            <div class="calc-button-row">
                                <div class="button">4</div>
                                <div class="button">5</div>
                                <div class="button">6</div>
                            </div>
                            <div class="calc-button-row">
                                <div class="button">1</div>
                                <div class="button">2</div>
                                <div class="button">3</div>
                            </div>
                            <div class="calc-button-row">
                                <div class="button">&lt;</div>
                                <div class="button">0</div>
                                <div class="button">C</div>
                            </div>
                           
                        </div>
                    </div>
                </div>

      </div>
      </form>
      <div id="message" class="d-none error-message mt4">
      Error!!
      </div>
      </div>
    </div>

     

</body>
        

    <!-- Metro 4 -->
    <script src="https://cdn.metroui.org.ua/v4/js/metro.min.js"></script>
    

    <script>
    
    const TSPwebapp = {}

    TSPwebapp.onLoad = function(){
      TSPwebapp.form = document.getElementById("main-form")
      TSPwebapp.staffidInput = document.getElementById("staffid")
      TSPwebapp.pinInput = document.getElementById("typed-numbers")
      TSPwebapp.startWorkButton = document.getElementById("start-work")
      TSPwebapp.finishWorkButton = document.getElementById("finish-work")
      TSPwebapp.startBreakButton = document.getElementById("start-break")
      TSPwebapp.finishBreakButton = document.getElementById("finish-break")
      TSPwebapp.message = document.getElementById("message")

      TSPwebapp.form.addEventListener("submit",TSPwebapp.onSubmit)
      TSPwebapp.startWorkButton.addEventListener("click",TSPwebapp.startFinishWork)
      TSPwebapp.finishWorkButton.addEventListener("click",TSPwebapp.startFinishWork)
      TSPwebapp.startBreakButton.addEventListener("click",TSPwebapp.startFinishBreak)
      TSPwebapp.finishBreakButton.addEventListener("click",TSPwebapp.startFinishBreak)

    } // TSPwebapp.onLoad function

  TSPwebapp.onSubmit= function(e){
    e.preventDefault()
  } // TSPwebapp.onSubmit function

  TSPwebapp.startFinishWork = function(e){
    
    const payload = {
                      staffid: TSPwebapp.staffidInput.value,
                      pin: TSPwebapp.pinInput.value,
                      action: e.target.dataset.action
                    }
    
    google.script.run.withSuccessHandler(() => {

      TSPwebapp.staffidInput.value = ""
      TSPwebapp.pinInput.value = ""

    } ).withFailureHandler(() => {

      TSPwebapp.message.classList.remove("d-none")
      setTimeout(() => {TSPwebapp.message.classList.add("d-none")},5000)

    }).startFinishWork(payload)

  } // TSPwebapp.startFinishWork function

TSPwebapp.startFinishBreak = function(e){
    
    const payload = {
                      staffid: TSPwebapp.staffidInput.value,
                      pin: TSPwebapp.pinInput.value,
                      action: e.target.dataset.action
                    }
    
    google.script.run.withSuccessHandler(() => {

      TSPwebapp.staffidInput.value = ""
      TSPwebapp.pinInput.value = ""

    } ).withFailureHandler(() => {

      TSPwebapp.message.classList.remove("d-none")
      setTimeout(() => {TSPwebapp.message.classList.add("d-none")},5000)

    }).startFinishBreak(payload)

  } // TSPwebapp.startFinishBreak function



    </script>

  <script>

document.getElementById('key-pad').addEventListener('click', function (event) {
    const number = event.target.innerText;
    const calcInput = document.getElementById('typed-numbers');
    if (isNaN(number)) {
        if (number == 'C') {
            calcInput.value = '';
        }
    }
    else {
        const previousNumber = calcInput.value;
        const newNumber = previousNumber + number;
        calcInput.value = newNumber;
    }
});
 
</script>



<script>
                 
    document.addEventListener("DOMContentLoaded",TSPwebapp.onLoad)

    
document.addEventListener("DOMContentLoaded",function(){

google.script.run.withSuccessHandler(printBtn).useDataRange();


});

          
                function printBtn(staffData) {
                for (var i = 0; i < staffData.length; i++) {
                   var btn = document.createElement("button");
                   var t = document.createTextNode(staffData[i]);
                   btn.appendChild(t);
                  document.body.appendChild(btn);
                    }
                }
                
                window.onload = printBtn();

           </script>  

           </body>

</html>

Here is the Google Apps Script code:

function doGet(e) {
  
  Logger.log(e);
  return HtmlService.createHtmlOutputFromFile("form");
  
}

function useDataRange () {
const ss = SpreadsheetApp.getActiveSpreadsheet() 
const wsStaff = ss.getSheetByName("Staff")
const staffData = wsStaff.getRange(2,2,wsStaff.getLastRow()-1,1).getValues()
Logger.log(staffData)
return staffData;

}


function startFinishBreak(payload){

   console.log(payload)

if (!["Start work","Finish work","Start break","Finish break"].includes(payload.action)){
    throw new Error("Sign in or sign out failed")
    return
  }

console.log("Initial check passed")

  const ss = SpreadsheetApp.getActiveSpreadsheet() 
  const wsBreakData = ss.getSheetByName("Break data")
  const wsStaff = ss.getSheetByName("Staff")

  const staffData = wsStaff.getRange(2,2,wsStaff.getLastRow()-1,3).getValues()

  const matchingStaff = staffData.filter(r => r[0].toString() === payload.staffid && r[2].toString() === payload.pin)

  if(matchingStaff.length !== 1){
    throw new Error("Sign in or sign out failed")
    return
  }

    const idsData = wsBreakData.getRange(2,2,wsBreakData.getLastRow()-1,3).getValues()

  console.log(idsData)

    const matchingIdsData = idsData.filter(r => r[0].toString() === payload.staffid)

  console.log(matchingIdsData)

  const latestAction = matchingIdsData.length === 0 ? "Finish break" : matchingIdsData[matchingIdsData.length-1][2]
  
  if (latestAction === payload.action){
    throw new Error("Sign in or sign out failed")
    return
  }

  wsBreakData.appendRow([new Date(),payload.staffid,payload.pin,payload.action]) 

}

function startFinishWork(payload){

console.log(payload)

if (!["Start work","Finish work","Start break","Finish break"].includes(payload.action)){
    throw new Error("Sign in or sign out failed")
    return
  }

console.log("Initial check passed")

  const ss = SpreadsheetApp.getActiveSpreadsheet() 
  const wsWorkData = ss.getSheetByName("Work data")
  const wsStaff = ss.getSheetByName("Staff")

  const staffData = wsStaff.getRange(2,2,wsStaff.getLastRow()-1,3).getValues()

  const matchingStaff = staffData.filter(r => r[0].toString() === payload.staffid && r[2].toString() === payload.pin)

  if(matchingStaff.length !== 1){
    throw new Error("Sign in or sign out failed")
    return
  }

    const idsData = wsWorkData.getRange(2,2,wsWorkData.getLastRow()-1,3).getValues()

  console.log(idsData)

    const matchingIdsData = idsData.filter(r => r[0].toString() === payload.staffid)

  console.log(matchingIdsData)

  const latestAction = matchingIdsData.length === 0 ? "Finish work" : matchingIdsData[matchingIdsData.length-1][2]
  
  if (latestAction === payload.action){
    throw new Error("Sign in or sign out failed")
    return
  }

  wsWorkData.appendRow([new Date(),payload.staffid,payload.pin,payload.action]) 

}

I hope this description all more or less makes sense - I am trying something a way beyond by current capabilities but I do need to get this task done and hopefully I'm learning in the process.

ianm12
  • 1
  • 1

1 Answers1

0

You need to add a value and event listener to each button. Then you can use the value to determine which button was pressed.

I have updated my script to address the comments below.

First add a new division.

<div id="staffButtons">
</div>
<div id="message" class="d-none error-message mt4">

Next make some changes to original script as shown.

function printBtn(staffData) {
  let div = document.getElementById("staffButtons"); // add this
  for (var i = 0; i < staffData.length; i++) {
    var btn = document.createElement("button");
    var t = document.createTextNode(staffData[i]);
    btn.value = staffData[i]
    btn.addEventListner("click",buttonClick);
    btn.appendChild(t);
    div.appendChild(btn);  // change this
  }
}

function buttonClick() {
  document.getElementById("staffid") = this.value;
}

Reference

TheWizEd
  • 7,517
  • 2
  • 11
  • 19
  • Thanks so much for this. I figured I needed to add an event listener here, but I couldn't quite work out how. Now I get alerts showing which button was pressed. One further (dumb) question: how do I use the value from the button click to set the value of staffid in the line TSPwebapp.staffidInput = document.getElementById("staffid") ? I guess I need to add something to the buttonClick function? Thanks again! – ianm12 Aug 19 '22 at 07:33
  • I'm not exactly sure what all the `TSPwebapp` stuff does, but I changed the `buttonClick` function to replace the value in "staffid" with the value from the button. I hope that helps. – TheWizEd Aug 19 '22 at 12:48
  • Thank you. I feel like I'm nearly there now. The TSPwebapp part of this originally designed to take whatever is inside the text boxes staffid, the PIN entered and the id of the button clicked and deliver to them to the JS to it can add it to a spreadsheet (after checking PIN is correct). However, the buttonClick function doesn't seem to be passing the staffid data to the payload. After I've pressed a button the log says e.g. { staffid: '', action: 'Finish work', pin: '1900' }. Can you spot what I'm doing wrong here? – ianm12 Aug 19 '22 at 14:14
  • As I said I don't know how `TSPwebapp` works so I can't tell how it would get loaded with updated data. You could try removing the `` block. Then add to click button `TSPwebapp.staffidInput = document.getElementById("staffid")` since `TSPwebapp` is a global variable. – TheWizEd Aug 19 '22 at 14:58
  • Thanks so much for all the help with this. Just one more thing I can't work out - how do I add the buttons that are generated by the printBtn function into a div into the body of the HTML. I'm at the point where everything is working perfectly but the buttons generated by the function just appear at the bottom of the page, after the main form. Any clues would be greatly appreciated! – ianm12 Aug 26 '22 at 18:53