Converting from NATIVE to IFRAME sandbox

2019-03-01 13:38发布

问题:

I have a large application that I want to convert from NATIVE to IFRAME sandbox now that NATIVE is deprecated. The general flow of the application is as follows: The user fills out a form on the beginning page and presses a Begin button. The beginning page is then hidden, and based upon values from the first page, the user is then shown a new page. My problem when using IFRAME is that the new page is never shown. It works as expected in NATIVE mode. I have created a simplified script that exhibits the problem. Please help me understand what I am forgetting or doing wrong.

Code.gs

function doGet() {
  Logger.log('enter doget');
  var html = HtmlService.createTemplateFromFile('BeginHeader').evaluate()
    .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;
}

Javascript.html

<script
  src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<script
  src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js">
</script>
<script 
  src="https://apis.google.com/js/api.js?onload=onApiLoad">
</script>

<script>
  function showForm(hdr) {
    console.log('enter showform');
    console.log(hdr);
    console.log('hiding first page');
    document.getElementById('beginDiv').style.display = 'none';
    var el = document.getElementById('recordDiv');
    el.innerHTML = hdr;
    console.log('showing new page');
    el.style.display = 'block';
  }

  function oops(error) {
    console.log('entered oops');
    alert(error.message);
  }
</script>

<script>
  $(document).ready(function() {
    console.log('begin ready');
    $("#beginForm").submit(function() {
      console.log('enter begin submit');
      //console.log('hiding first page');
      //document.getElementById('beginDiv').style.display = 'none';
      console.log('including page 2');
      google.script.run
      .withSuccessHandler(showForm)
      .withFailureHandler(oops)
      .include('Page2');
    });
  });

</script>

BeginHeader.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <div id="beginDiv" style="display:block">
      <p>Click on Begin. </p>
      <form id="beginForm">
        <input type="submit" value="Begin">
      </form>
    </div>

<!-- results of content being filled in -->
    <div id="recordDiv"></div>

<?!= include('Javascript'); ?>

  </body>
</html>

Page2.html

<!DOCTYPE html>
<html>
  <body>
      <p> This is page 2. </p>
  </body>
</html>

回答1:

There is no point in ever using a button of the "submit" type, unless you want to force the form to make an HTTP Request, and reload the application. That's what a "submit" type button does. It causes the page to be reloaded. The "submit" type button is meant to work together with a form in a certain way. It causes a GET or POST request to happen. That's what the problem is. So, you'll need to reconfigure things a little bit.

Just use a plain button.

<input type="button" value="Begin" onmouseup="gotoPg2()">

I created a gotoPg2() function to test it:

<script>
  window.gotoPg2 = function() {
    console.log('enter begin submit');
    //console.log('hiding first page');
    //document.getElementById('beginDiv').style.display = 'none';
    console.log('including page 2');
    google.script.run
      .withSuccessHandler(showForm)
      .withFailureHandler(oops)
      .include('Page2');
  };
</script>

If you use that, they you don't need the $(document).ready(function() { etc. code anymore. And, if you don't need that code, then you don't need to load jQuery.

Unless you are using jQuery for other things, then you don't need:

<script
  src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<script
  src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js">
</script>

The NATIVE mode was probably blocking the intended usage of the "submit" request. That's why the code in NATIVE was working. IFRAME allows things to work as they are built and intended to work, which means that the page was probably trying to be reloaded, and an error was occurring. I was getting a 404 page error in the browser console.