Search code examples
javascriptgoogle-apps-scriptsubmitform-submitiframe-app

Converting from NATIVE to IFRAME Sandbox with Enter Key Submit


I have a similar problem to this post when trying to convert my apps script web app to use IFRAME Sandbox. I have converted to 'input = "button"' as suggested.

My web app is a simple form for students to use to sign in and out of a school library. The idea for the app is for it to be as easy as possible for students to use. Students should enter their id number and be able to either click the submit button or hit the enter key. Their ID is then validated before being stored in a spreadsheet and they get a message back saying thanks for signing in or out, or please enter a valid ID Number. Then focus should return to the text box and be cleared, ready for the next student to enter their id.

I had it working as described above using NATIVE mode. When I tried to convert it to IFRAME mode, clicking the button works, but if you hit the enter key everything just disappears and no data goes to the spreadsheet. How can I get hitting the enter key to work the same as clicking the submit button?

index.html code:

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
</head>
<body>
<h3>Please Sign In &amp; Out</h3>
<div id="box" class="frame">
  <form id="signSheet" onsubmit="google.script.run
      .withSuccessHandler(updateInfo)
      .validateID(this.parentNode)">
    <input type="text" name="myID" id="myID" placeholder="Enter your student ID" autocomplete="off">
    <input type="button" value="Submit" onmouseup="google.script.run
      .withSuccessHandler(updateInfo)
      .validateID(this.parentNode)">
  </form>
  <span id="thank_you" hidden="true"></span>
</div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<?!= include('javascript'); ?>

</body>
</html>

javascript.html code:

<script>
function updateInfo(ret){

        if(ret[0]){
          $( "#thank_you" ).removeClass("error");
          $( "#thank_you" ).addClass("valid");
        }
        else{
          $( "#thank_you" ).removeClass("valid");
          $( "#thank_you" ).addClass("error");
        }
        $( "#thank_you" ).text(ret[1]);
        $( "#thank_you" ).show("slow");
        $( "#signSheet" )[0].reset();
        $( "#myID" ).focus();
        console.log(ret);
      }

</script>

Code.gs code:

//spreadsheet key is needed to access the spreadsheet.
var itemSpreadsheetKey = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';

//Open the spreadsheet and get the sheet objects
var openedSS = SpreadsheetApp.openById(itemSpreadsheetKey);
var studentList = openedSS.getSheetByName("Student List");//Spreadsheet must match with sheet name
var studentRecord = openedSS.getSheetByName("Sign In-Out Record");

function doGet() {
  var html = HtmlService.createTemplateFromFile('index').evaluate()
               .setTitle('Sign In/Out Sheet')
               .setSandboxMode(HtmlService.SandboxMode.IFRAME);
  return html;
}

function include(filename) {
  Logger.log('enter include');
  Logger.log(filename);
  var html = HtmlService.createHtmlOutputFromFile(filename).getContent();
  Logger.log(html);
  return html;
}

function validateID(form){
  var idNum = form.myID;
  var valid = false;
  var numIdList = studentList.getLastRow()-1; //-1 is to exclude header row
  //get the item array
  var idArray = studentList.getRange(2,1,numIdList,1).getValues();
  i= idArray.length;
  while(i--){
    if(idArray[i][0]==idNum & idNum!='') {
      valid=true;
      break;
    }
  }
  if(valid)
    return [1, updateRecord(idNum)];
  else return [0, "ID number " + idNum + " not recognized. Please enter a valid ID number."];
}

function updateRecord(idNum){
        studentRecord.appendRow([idNum]);
        var formulas = studentRecord.getRange("B2:D2").getFormulasR1C1();
        var lRow = studentRecord.getLastRow();
        var range = studentRecord.getRange(lRow, 2, 1, 3);
        range.setFormulas(formulas);
        var vals = range.getValues();
        var now = new Date();
        studentRecord.getRange(lRow, 5, 1, 1).setValue(now);
        now = Utilities.formatDate(now, "EST", "HH:MM a");
        idNum = "Thanks " + vals[0][0] + ", you have signed " + vals[0][2] + " at " + now;
        return idNum;
  }

Update: I found this post and added the following code to javascript.html:

$(document).ready(function() {
  $(window).keydown(function(event){
    if(event.keyCode == 13) {
      var idVal = $("#myID").val();
      google.script.run.withSuccessHandler(updateInfo).validateID(idVal);
      return false;
    }
  });
})

This solved the the problem for me with a little more tweaking to parts of index.html and Code.gs


Solution

  • I found this post and added the following code to javascript.html:

    $(document).ready(function() {
      $(window).keydown(function(event){
        if(event.keyCode == 13) {
          var idVal = $("#myID").val();
          google.script.run.withSuccessHandler(updateInfo).validateID(idVal);
          return false;
        }
      });
    })
    

    This listens for the enter key and sends the value of the text field to the apps script function. In this case I didn't need to use `event.preventDefault();'

    Then I had to adjust the button's onmouseup function to take this.parentNode.myID and change my apps script function to take a value instead of a form object.