Home > Software design >  Google Apps Script (web deploy) auto reload page
Google Apps Script (web deploy) auto reload page

Time:10-18

I have written two small Google Apps, deployed as web apps, to "live stream" my son's baseball games. One app (I call it "Game Day") lets those watching the game see the score, inning, balls, strikes, and outs. The second app (I call it "Score Keeper") lets somebody update those stats. Both apps access a Google Spreadsheet.

Both apps show the correct stats from the Google Spreadsheet when first loaded, but only update the stats when the webpage is manually reloaded. I would like to auto reload "Game Day" every X seconds, but when I use something like setTimeout("location.reload(true);", 10000); in my Javascript file, when the page reloads, it is blank.

I have the same problem with the "Score Keeper" app in that after clicking a button--to increment the number of balls, for example--nothing changes on the web page unless I manually reload. The button does correctly increment the number of balls in the spreadsheet. If I then manually reload, it reads the stats from the spreadsheet and so displays the correct stats again.

I have read about and tried to implement google.script.run.withSuccessHandler(), but how the withSuccessHandler() works is currently beyond my understanding. If that is indeed the way to do it, I'd love help implementing it for my particular case as I have not been able to extrapolate from other people's examples.

Here is my code:

"Game Day" Code.gs:

var id = 'Google Spreadsheet ID';
var ss = SpreadsheetApp.openById(id);
var sheet = ss.getSheetByName('score');
var statsRange = sheet.getRange(2,1,1,9);

function doGet(e) {
  var temp = HtmlService.createTemplateFromFile('index');
  temp.stats = getScore();
  return temp.evaluate();
}

function getScore() {
  var s = statsRange.getValues();
  return s[0];
}

function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename).getContent();
}

"Game Day" index.html:

<div class="container">

  <div class="row">
    <div class="col s12 center-align">
      <h5><?= stats[0]   " (home) v. "   stats[1]   " (guest)"; ?></h5>
    </div>
  </div>
  
  <div class="row">
    <div class="col s4 center-align"><b>Home</b></div>
    <div class="col s4 center-align"><b>Inning</b></div>
    <div class="col s4 center-align"><b>Guest</b></div>
  </div>

  <div class="row">
    <div class="col s4 center-align stat"><?= stats[4] ?></div>
    <div class="col s2 right-align stat"><?= stats[2] ?></div>
    <div class="col s2 left-align stat"><?= stats[3] ?></div>
    <div class="col s4 center-align stat"><?= stats[5] ?></div>
  </div>

  <div class="row"></div>

  <div class="row">
    <div class="col s4 center-align"><b>Balls</b></div>
    <div class="col s4 center-align"><b>Strikes</b></div>
    <div class="col s4 center-align"><b>Outs</b></div>
  </div>

  <div class="row">
    <div class="col s4 center-align stat"><?= stats[6] ?></div>
    <div class="col s4 center-align stat"><?= stats[7] ?></div>
    <div class="col s4 center-align stat"><?= stats[8] ?></div>
  </div>

  <div class="row">
    <div class="col s12 center-align refresh">refresh page to update stats</div>
  </div>

</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<?!= include('index-js'); ?>

"Game Day" index-js.html:

<script>
  setTimeout("location.reload(true);", 10000);
</script>

I also just tried adding a Simple Trigger in the Google Apps Script editor to run on the doGet() function every minute. It executed the trigger every minute, but the page did not change.

CodePudding user response:

You can use google.script.run and html data attributes to achieve your goal:

code.gs

function getStats() {
  return new Array(15).fill("").map(Math.random)
}

function doGet(e) {
 return HtmlService.createTemplateFromFile('index').evaluate();
}

function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename)
      .getContent();
}

index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top" />
    <style>
      .stats::after {
        content: attr(data-stats-value);
      }
    </style>
  </head>

  <body>
    <div class="container">
      <div class="row">
        <div class="col s12 center-align">
          <h5 id="header"></h5>
        </div>
      </div>

      <div class="row">
        <div class="col s4 center-align"><b>Home</b></div>
        <div class="col s4 center-align"><b>Inning</b></div>
        <div class="col s4 center-align"><b>Guest</b></div>
      </div>

      <div class="row">
        <div
          class="col s4 center-align stats"
          data-stats-index="4"
          data-stats-value=""
        ></div>
        <div
          class="col s2 right-align stats"
          data-stats-index="2"
          data-stats-value=""
        ></div>
        <div
          class="col s2 left-align stats"
          data-stats-index="3"
          data-stats-value=""
        ></div>
        <div
          class="col s4 center-align stats"
          data-stats-index="5"
          data-stats-value=""
        ></div>
      </div>

      <div class="row"></div>

      <div class="row">
        <div class="col s4 center-align"><b>Balls</b></div>
        <div class="col s4 center-align"><b>Strikes</b></div>
        <div class="col s4 center-align"><b>Outs</b></div>
      </div>

      <div class="row">
        <div
          class="col s4 center-align stats"
          data-stats-index="6"
          data-stats-value=""
        ></div>
        <div
          class="col s4 center-align stats"
          data-stats-index="7"
          data-stats-value=""
        ></div>
        <div
          class="col s4 center-align stats"
          data-stats-index="8"
          data-stats-value=""
        ></div>
      </div>

      <div class="row">
        <div class="col s12 center-align refresh">
          refresh page to update stats
        </div>
      </div>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
    <?!= include('index-js'); ?>
  </body>
</html>

index-js.html

<script>
  const updateScore = (stats) => {
  document.querySelector('#header').textContent =
    stats[0]   ' (home) v. '   stats[1]   ' (guest)';
  document
    .querySelectorAll('.stats')
    .forEach(
      (el) => (el.dataset.statsValue = stats[Number(el.dataset.statsIndex)])
    );
};
setInterval(
  () => {google.script.run.withSuccessHandler(updateScore).getStats()},
  10000
);
</script>
  • Related