0

Goal

I'm trying to execute a piece of code in a Google Spreadsheets modal dialog after pressing a submit button in a form. After the submit button is pressed, I want the dialog to display a loading wheel (I've already made that), then close itself using google.script.host.close() after a 1.5 second delay (using setTimeout() for that one).

Previous Attempt

I was able to get it working before without the submit button and without the <form> element, and instead using onclick attributes on normal buttons, but I wasn't able to have the validation work properly with that solution.

Outcome

What ended up happening was immediately after pressing the submit button, the contents of the modal dialog disappeared and it just stayed open until I had to close it manually, and none of the code that I wanted to be executed was executed. When I used the Inspector to look at the source html for the dialog, the block was completely empty. All that was left was this:

<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
    </head>
    <body></body>
</html>

I tried doing the classic debugging solution of console.log(). I put a pair of log functions in the submission event handler, one before and one after the e.preventDefault(). Neither were logged. I can only assume that this means the function wasn't being executed at all.

Desired Solution

I need help identifying what went wrong, or if this is some kind of bug with Google's platform, and how I can improve or fix this (if at all).

Edit 1

I have attempted to use event.preventDefault(), as has been suggested by the answers given in the linked posts (I have edited the snippet to show how I have attempted to use it). This has not worked, and results in the same outcome described above. (Also elaborated what happened in the outcome).

Code Snippets

The snippets following are (in order) JavaScript, CSS, and HTML.

var x;
let ID = t => document.getElementById(t);
var loader = ID('loader');
document.addEventListener("DOMContentLoaded", () => {
  loader.style.visibility = 'visible';
  google.script.run.withSuccessHandler(res => {
      x = res.arr[1];
      google.script.run.callLibraryFunction('CharacterSheetCode.clearClassEdit');
      switch (res.arr[0]) {
        case 'edit':
          ID('class').value = res.arr[2].class;
          ID('subclass').value = res.arr[2].subclass;
          ID('level').value = res.arr[2].level;
          ID('hitdie').value = res.arr[2].hitdie;
          ID('spellcasting').value = res.arr[2].spells;
          makeEditable();
          break;
        case 'add':
          makeEditable();
          break;
      }

      function makeEditable() {
        ID('class').readOnly = false;
        ID('subclass').readOnly = false;
        ID('level').readOnly = false;
        ID('level').max = (20 - res.lvl) + (res.arr[2] ? Number(res.arr[2].level) : 0);
        ID('hitdie').readOnly = false;
        ID('spellcasting').readOnly = false;
        ID('addedit').disabled = false;
        ID('remove').disabled = false;
        loader.style.visibility = 'hidden';
      }
    })
    .callLibraryFunction("CharacterSheetCode.getClassInfo");
});

ID("form").addEventListener("submit", e => {
  e.preventDefault();
  loader.style.visibility = 'visible';
  var className = ID('class').value,
    subclass = ID('subclass').value,
    level = ID('level').value,
    hitdie = ID('hitdie').value,
    spells = ID('spellcasting').value;
  if (hitdie % 2 == 0 && hitdie >= 6 && hitdie <= 12) {
    setTimeout(() => google.script.host.close(), 1500);
    google.script.run.callLibraryFunction("CharacterSheetCode.addEditInfo", [className.trim(), subclass.trim(), level, hitdie, spells, x]);
  } else {
    alert(`Error: You must use a d6, d8, d10, or d12 as a hit die. A d${hitdie} will not be accepted.`);
    loader.style.visibility = 'hidden';
  }
}

function removeClass() {
  loader.style.visibility = 'visible';
  setTimeout(() => google.script.host.close(), 1500);
  google.script.run.callLibraryFunction("CharacterSheetCode.addEditInfo", ['', '', '', '', '', x]);
}
.container {
  background-color: white;
  padding: 15px;
  height: 200px;
  width: 300px;
  font-family: Georgia;
  color: black;
  font-size: 15px;
  position: absolute;
  top: 50%;
  left: 50%;
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
  text-align: center;
}

input {
  border-radius: 1em;
  text-align: center;
  font-family: Georgia;
  font-size: 15px;
}

select {
  border-radius: 1em;
  font-family: Georgia;
  font-size: 15px;
}

button {
  border-radius: 1em;
  font-family: Georgia;
  font-size: 15px;
}

button:active {
  filter: brightness(80%);
}

.loader {
  border: 5px solid #f3f3f3;
  border-radius: 50%;
  border-top: 5px solid #3498db;
  border-bottom: 5px solid #3498db;
  position: absolute;
  top: calc(50% - 30px);
  left: calc(50% - 30px);
  width: 50px;
  height: 50px;
  z-index: 10;
  animation: spin 2s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
<div id="loader" class="loader" style="visibility: hidden;"></div>
<div id="container" class="container">
  <form id="form">
    <label for="class">Class</label>
    <input type="text" id="class" required readonly="readonly"><br>
    <label for="subclass">Subclass</label>
    <input type="text" id="subclass" readonly="readonly"><br>
    <label for="level">Level</label>
    <input type="number" id="level" style="width: 50px;" min="1" max="20" required readonly="readonly" onkeypress="return event.charCode >= 48 && event.charCode <= 57">
    <label for="hitdie">Hit Die: d</label>
    <input type="number" id="hitdie" style="width: 50px" min="6" max="12" step="2" required readonly="readonly" onkeypress="return event.charCode >= 48 && event.charCode <= 57"><br>
    <label for="spellcasting">Spellcasting:</label>
    <select id="spellcasting" readonly="readonly">
      <option>None</option>
      <option>Full</option>
      <option>Half</option>
      <option>Third</option>
      <option>Pact</option>
    </select><br>
    <button id="addedit" type="submit" disabled>Add/Edit</button><br>
    <button id="remove" onclick="removeClass()" disabled>Remove Class</button>
    <div>Note: The process of updating the sheet can sometimes take up to 20-40 seconds.</div>
  </form>
</div>
TheMaster
  • 45,448
  • 6
  • 62
  • 85
Ben Craven
  • 37
  • 5
  • If the linked duplicate answers doesn't answer your question, [edit] your question to explain how the answers don't satisfy your question. If you're having trouble implementing a solution in the duplicate or don't understand a solution provided, ask a new specific question with the part you're having trouble with. – TheMaster Jul 19 '22 at 23:19
  • Kindly ask a new question for new problems. The original problem of blank page resolved using the duplicates. Right? – TheMaster Jul 20 '22 at 09:16
  • @TheMaster No, I'm still getting the blank page despite integrating `event.preventDefault()`. There were no new problems, I'm just elaborating on some background details that happened after the original problems were occurring. – Ben Craven Jul 20 '22 at 20:38
  • Did you redeploy it? – TheMaster Jul 20 '22 at 22:23
  • You should also put `ID("form").addEventListener("submit", e => { e.preventDefault(...` inside the window load event handler – TheMaster Jul 20 '22 at 22:41
  • @BenCraven Try removing the `type="submit"` from the button, that is the problem most of the time for me. – Saiansh Singh Jul 20 '22 at 22:48

0 Answers0