You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Sheets模态框提交表单后HTML清空问题求助

问题排查与修复方案

需求目标

  • 点击Google表格模态框表单的提交按钮后,显示加载动画,延迟1.5秒后通过google.script.host.close()关闭弹窗
  • 保留表单原生验证功能

当前问题

点击提交按钮后,模态框内容立即清空,仅留下空HTML结构:

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

弹窗需手动关闭,提交事件处理函数未触发(console.log无输出),预期代码未执行。

过往尝试与已做操作

  • 曾用普通按钮onclick实现功能,但无法触发表单验证
  • 已尝试在提交事件中添加event.preventDefault(),问题仍未解决

代码片段

JavaScript

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]);
}

CSS

.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);
  }
}

HTML

<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>

问题原因分析

  1. JavaScript语法错误:提交事件监听函数末尾缺少闭合括号),导致JS解析失败,整个脚本中断执行。浏览器遇到语法错误时会停止执行后续代码,包括event.preventDefault(),表单会默认提交,导致模态框内容被清空。
  2. 元素获取时机问题:var loader = ID('loader');在DOMContentLoaded事件前执行,此时DOM可能尚未完全加载,loader可能为null,后续操作会报错。

修复方案

1. 修复语法错误

在提交事件监听函数末尾添加闭合括号:

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';
  }
}); // 添加闭合括号

2. 调整元素获取时机

将loader的获取逻辑移到DOMContentLoaded事件内部,确保DOM加载完成后再获取元素:

document.addEventListener("DOMContentLoaded", () => {
  var loader = ID('loader'); // 移到事件内部
  loader.style.visibility = 'visible';
  // 后续代码保持不变
});

3. 优化表单提交逻辑(可选)

为避免google.script.run异步操作未完成就关闭弹窗,建议在addEditInfo执行成功后再触发关闭:

if (hitdie % 2 == 0 && hitdie >= 6 && hitdie <= 12) {
  loader.style.visibility = 'visible';
  google.script.run
    .withSuccessHandler(() => {
      setTimeout(() => google.script.host.close(), 1500);
    })
    .callLibraryFunction("CharacterSheetCode.addEditInfo", [className.trim(), subclass.trim(), level, hitdie, spells, x]);
}

4. 修复removeClass函数的潜在问题

在函数内部获取loader元素,确保DOM已加载:

function removeClass() {
  var loader = ID('loader');
  loader.style.visibility = 'visible';
  google.script.run
    .withSuccessHandler(() => {
      setTimeout(() => google.script.host.close(), 1500);
    })
    .callLibraryFunction("CharacterSheetCode.addEditInfo", ['', '', '', '', '', x]);
}

内容的提问来源于stack exchange,提问作者Ben Craven

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 06:57:17