Nathaniel MacIver
Nathaniel MacIver

Reputation: 397

Refresh HTML Document via Javascript in a GAS Embedded Environment

So I've created a simple time-keeping app in Google Appscript to store data in spreadsheets and display the information in an embedded Javascript/JQuery applet on the internal Google Site. It looks like this:

Snapshot of program

My problem is that some users leave the browser page open for too long and have to click the object twice in order to log out or log in, or refresh the page. I was hoping to set an interval timer to do the refresh for them to save them a step. Below is my code on the front end to process an interval refresh and recreate the body HTML after a set amount of idle time:

<script src="https://code.jquery.com/jquery-1.8.3.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.0/jquery-ui.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js" type="text/javascript"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://...moment.js"></script>
<script src="https://...moment-with-locales.js"></script>
<script src="https://...moment-timezone-with-data.js"></script>
<script>
// When the page loads.
function start(){
 try{var dateString = moment(new Date()).format('L');}
 catch(e){var dateString = getNowDateString();}
 document.getElementById("title").style.display = "none";
 document.getElementById("clock").style.display = "none";
 document.getElementById("loader").style.display = "block";
 document.getElementById("interface").style.display = "none";
 google.script.run.withSuccessHandler(showTimeTrack).pullCard(JSON.stringify({email:DATA.email, date:dateString, source:'TimeTrack'}));
}
function showTimeTrack(payload) {
console.log(payload);
var body = $('body').clone();
var time = new Date().getTime();
var data = JSON.parse(payload);
var greenflag = (data.greenflag) ? true: false;
var interface = document.getElementById('interface');
var emailDiv = document.createElement('small');
emailDiv.appendChild(document.createTextNode('Connected as: '));
emailDiv.appendChild(document.createElement('br'));
emailDiv.appendChild(document.createTextNode(DATA.email));
emailDiv.appendChild(document.createElement('br'));
emailDiv.appendChild(document.createElement('br'));
interface.appendChild(emailDiv);

var lastLogDiv = document.createElement('small');
lastLogDiv.innerHTML = '<b>'+data.timecard.info.message+'</b>';
lastLogDiv.appendChild(document.createElement('br'));
if(data.timecard.info.lastRole.length > 0)
{
  lastLogDiv.appendChild(document.createTextNode('As: '+data.timecard.info.lastRole));
}
interface.appendChild(lastLogDiv);

//...Creating various HTML Elements...

interface.appendChild(logBtn); 
interface.appendChild(document.createElement('br')); 
interface.appendChild(document.createElement('br'));

var cardButton = document.createElement('button');
cardButton.innerHTML = 'View Timecard';
console.log(DATA);
cardButton.onclick = function(){openWindowWithPost(JSON.stringify({timecard: data.timecard, directory: DATA.DIRECTORY}));}
interface.appendChild(cardButton);
interface.appendChild(document.createElement('br'));
interface.appendChild(document.createElement('br'));

 setClock();
 document.getElementById("loader").style.display = "none";
 document.getElementById("title").style.display = "block";
 document.getElementById("clock").style.display = "block";
 document.getElementById("interface").style.display = "block";
 
 var refreshIntervalId = setInterval(function(){
    $(document.body).bind("mousemove keypress", function(e) {
       time = new Date().getTime();console.log(time);});
    console.log('Current run is at '+moment(time).format('MMMM Do YYYY, h:mm:ss a'));
   if(new Date().getTime() - time >= 10000) 
      {
        var body = $('body').clone(); document.body.innerHTML = ''; $('body').html(body); start(); var body = $('body').clone(); 
        time = new Date().getTime(); 
        console.log('refreshed at '+moment(new Date()).format('MMMM Do YYYY, h:mm:ss a'));
        clearInterval(refreshIntervalId);
      }
  else {
         console.log('checked at '+moment(new Date()).format('MMMM Do YYYY, h:mm:ss a'));
        }}, 3000);
}
//////////////////////////////////////////////////////FUNCTION SETCLOCK////////////////////////////////////////////////////////////////////////////////////
function setClock()
{
  var now = moment(new Date()).tz(DATA.timeZone).format('hh:mm:ss A z');
  $('#time').html(now);
   setTimeout('setClock()',500);
}
</script>
<!DOCTYPE html>
<html>
<head>
<script>
var DATA = <?!= JSON.stringify(dataFromServerTemplate) ?>;
</script>
<?!= HtmlService.createHtmlOutputFromFile('CSS').getContent(); ?>
</head>
<body onload="start()">

<div id = "loader" class="heart-rate">
  <svg version="1.0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100%" height="100%" viewBox="0 0 125 73" enable-background="new 0 0 150 73">
    <polyline fill="none" stroke="#CE0000" stroke-width="3" stroke-miterlimit="10" points="0,45.486 38.514,45.486 44.595,33.324 50.676,45.486 57.771,45.486 62.838,55.622 71.959,9 80.067,63.729 84.122,45.486 97.297,45.486 103.379,40.419 110.473,45.486 150,45.486"
    />
  </svg>
  <div class="fade-in"></div>
  <div class="fade-out"></div>
</div>

<p  id = 'title' style="font-size:18px; text-align: center; display: none;"><b>Time<font color="#ff0000">Track</font></b></p>
<div id="clock" style = "display: none;"><small>Current Time:<div id = 'time'></div></small></div><br>
<div id="interface" tex-align: center;></div>  
<div id = 'modal' class = 'modal'>
<div id = 'modalContent' class = 'modal-content'>
</div></div>
<span id = 'closeModal' class = 'close'></span>
<form id="timeCardPost" method="post" action="MustSetURL" target="TheWindow">
<input type="hidden" name="payload" value="set card JSON here" />
</form>
<?!= HtmlService.createHtmlOutputFromFile('JS-TimeTrack').getContent();?>
</body>
</html>

unfortunately, after the first refresh, the interval seems to reload the page and then add another copy of the body under it ad infinitum, like in the screenshot below:

Constant appendages!

I've tried location.reload(with true and false statements). That just results in a white screen. I've tried setting the HTML body to (), but that seems to work the same way. Would anyone know how to reset the body tag of the page instead of just concatenating?

Thanks, Nathaniel

Upvotes: 0

Views: 410

Answers (1)

Alan Wells
Alan Wells

Reputation: 31300

jquery clone() method makes a copy of the selected element. What you are ending up with is body tags inside of other body tags, each one nested inside of the other.

Currently

var body = $('body').clone();
document.body.innerHTML = ''; 
$('body').html(body); 
start(); 
var body = $('body').clone();

Try

var body = document.body.innerHTML;//Get the HTML inside of the `body` tag
document.body.innerHTML = '';//Clear the existing HTML from the `body` tag

console.log('body: ' + body);

document.body.innerHTML = body;

start(); 

Upvotes: 1

Related Questions