Vincular a otra página HTML en Google Apps Script

Resuelto MOTIVECODEX asked hace 11 años • 3 respuestas

Al vincular desde ScriptDbConsole.html a legend.html, aparece el siguiente mensaje de error:

Lo sentimos, el archivo que has solicitado no existe. Compruebe la dirección e inténtelo de nuevo.

Esto normalmente funcionaría en un entorno normal, pero supongo que no aquí. Está en script.google.com.

Al crear un nuevo archivo .html en el proyecto script.google.com, lo crea en la misma ubicación que los demás, por lo que este código debería funcionar, ¿verdad? ¿Cómo puedo abrir legend.html desde ScriptDbConsole.html?

<a href='legend.html' target='_blank'>Open in new window</a>
MOTIVECODEX avatar Mar 28 '13 02:03 MOTIVECODEX
Aceptado

Si bien HtmlService le permite publicar HTML, no "aloja" páginas y no puede acceder a los diversos archivos html en su proyecto de Apps Script mediante URL directamente. En cambio, su aplicación web tendrá una URL cuando se publique, y esa es la única URL que tiene.

A continuación se muestra una manera de mostrar páginas separadas de su secuencia de comandos y hacer que se comporten de manera similar a los enlaces de archivos html.

A la doGet()función se le pasa un evento cuando se llama, y ​​podemos aprovechar eso para indicar qué página queremos servir. Si el ID de nuestra aplicación web es <SCRIPTURL>, así es como se verá una URL más una cadena de consulta que solicita una página específica:

https://script.google.com/macros/s/<SCRIPTURL>/dev?page=my1

Usando HTML con plantilla, podemos generar la URL y la cadena de consulta necesarias sobre la marcha. En nuestro doGet(), solo necesitamos analizar la cadena de consulta para determinar qué página servir.

Aquí está el guión, con dos páginas de muestra que contienen botones para alternar entre ellas.

Código.gs

/**
 * Get the URL for the Google Apps Script running as a WebApp.
 */
function getScriptUrl() {
 var url = ScriptApp.getService().getUrl();
 return url;
}

/**
 * Get "home page", or a requested page.
 * Expects a 'page' parameter in querystring.
 *
 * @param {event} e Event passed to doGet, with querystring
 * @returns {String/html} Html to be served
 */
function doGet(e) {
  Logger.log( Utilities.jsonStringify(e) );
  if (!e.parameter.page) {
    // When no specific page requested, return "home page"
    return HtmlService.createTemplateFromFile('my1').evaluate();
  }
  // else, use page parameter to pick an html file from the script
  return HtmlService.createTemplateFromFile(e.parameter['page']).evaluate();
}

mi1.html

<html>
  <body>
    <h1>Source = my1.html</h1>
    <?var url = getScriptUrl();?><a href='<?=url?>?page=my2'> <input type='button' name='button' value='my2.html'></a>
  </body>
</html>

mi2.html

<html>
  <body>
    <h1>Source = my2.html</h1>
    <?var url = getScriptUrl();?><a href='<?=url?>?page=my1'> <input type='button' name='button' value='my1.html'></a>
  </body>
</html>
Mogsdad avatar May 22 '2013 16:05 Mogsdad

Aplicación web de varias páginas

Esta es una aplicación web básica de cuatro páginas que funciona. Solo muestra el título de la página y cuatro botones en la barra lateral izquierda para la navegación.

Código.gs:

function getScriptURL(qs) {
  var url = ScriptApp.getService().getUrl();
  //Logger.log(url + qs);
  return url + qs ;
}

function doGet(e) 
{
  //Logger.log('query params: ' + Utilities.jsonStringify(e));
  if(e.queryString !=='')
  {  
    switch(e.parameter.mode)
    {
      case 'page4':
        setPage('Page4')      
        return HtmlService
        .createTemplateFromFile('Page4')
        .evaluate()
        .addMetaTag('viewport', 'width=device-width, initial-scale=1')
        .setTitle("Page4"); 
        break;  
      case 'page3':
        setPage('Page3');        
        return HtmlService
        .createTemplateFromFile('Page3')
        .evaluate()
        .addMetaTag('viewport', 'width=device-width, initial-scale=1')
        .setTitle("Page3");
        break;
      case 'page2':
        setPage('Page2');        
        return HtmlService
        .createTemplateFromFile('Page2')
        .evaluate()
        .addMetaTag('viewport', 'width=device-width, initial-scale=1')
        .setTitle("Page2");
        break;  
      case 'page1':
         setPage('Page1');
         return HtmlService
        .createTemplateFromFile('Page1')
        .evaluate()
        .addMetaTag('viewport', 'width=device-width, initial-scale=1')
        .setTitle("Page1");
        break;
      default:
        setPage('Page1');
        return HtmlService
        .createTemplateFromFile('Page1')
        .evaluate()
        .addMetaTag('viewport', 'width=device-width, initial-scale=1')
        .setTitle("Page1");
        break;
    }
  }
  else
  {
    setPage('Page1');
    return HtmlService
    .createTemplateFromFile('Page1')
    .evaluate()
    .addMetaTag('viewport', 'width=device-width, initial-scale=1')
    .setTitle("Page1");
  }
}

function getPageData()
{
  var s='';
  s+='<input type="button" value="Page1" onClick="getUrl(\'?mode=page1\');" />';
  s+='<br /><input type="button" value="Page2" onClick="getUrl(\'?mode=page2\');" />';
  s+='<br /><input type="button" value="Page3" onClick="getUrl(\'?mode=page3\');" />';
  s+='<br /><input type="button" value="Page4" onClick="getUrl(\'?mode=page4\');" />';
  var rObj={menu:s,title:getPage()};
  Logger.log(rObj);
  return rObj;
}

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

paginas.gs

Decidí cambiar al servicio de propiedades de scripts de usuario, ya que es posible que desee tener más de un usuario. A menudo desarrollo scripts que sólo yo uso.

function setPage(page) {
  var ps=PropertiesService.getUserProperties();
  ps.setProperty('PageTitle', page);
  return ps.getProperty('PageTitle');
}

function initPage() {
  var ps=PropertiesService.getUserProperties();
  ps.setProperty('PageTitle','');
  return ps.getProperty('PageTitle');
}

function getPage() {
  var ps=PropertiesService.getUserProperties();
  var pt=ps.getProperty('PageTitle');
  return pt;
}

globals.gs:

Estaba usando esto para el título de la página, pero decidí que algunos de ustedes tal vez deseen tener varios usuarios, por lo que el servicio de propiedades de usuario es una selección más lógica. Probablemente usaré esto para otra cosa, así que lo dejé ahí. Pero tú decides.

function getGlobals(){
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName('Globals');
  var rg=sh.getRange(1,1,getGlobalHeight(),2);
  var vA=rg.getValues();
  var g={};
  for(var i=0;i<vA.length;i++){
    g[vA[i][0]]=vA[i][1];
  }
  return g;
}

function setGlobals(dfltObj){
  if(dfltObj){
    var ss=SpreadsheetApp.getActive();
    var sh=ss.getSheetByName('Globals');
    var rg=sh.getRange(1,1,getGlobalHeight(),2);
    var vA=rg.getValues();
    for(var i=0;i<vA.length;i++){
      vA[i][1]=dfltObj[vA[i][0]];
    }
    rg.setValues(vA);
  }
}

function getGlobal(key) {
  var rObj=getGlobals();
  if(rObj.hasOwnProperty(key)){
    return rObj[key];
  }else{
    throw(Utilities.formatString('JJE-SimpleUtilitiesScripts-Error: Globals does not contain a key named %s.',key));
  }  
}

function setGlobal(key,value){
  var curObj=getGlobals();
  curObj[key]=value;
  setGlobals(curObj);
}

function getGlobalHeight(){
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName('Globals');
  var rg=sh.getRange(1,1,sh.getMaxRows(),1);
  var vA=rg.getValues();
  for(var i=0;i<vA.length;i++){
    if(!vA[i][0]){
      break;
    }
  }
  return i;
}

Página1.html:

1 of 4. They start out the same. I make them this way and if I need to customize them I'll usually just do it right inside the html page. But it's also possible to add additional javascript or css pages to support variations from page to page.

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <?!= include('res') ?>
    <?!= include('css') ?>
  </head>
  <body>
    <?!= include('content') ?>
    <?!= include('script') ?>
  </body>
</html>
<html><head>

content.html:

    <div class="sidenav"></div>
    <div class="header">
      <h1 id="ttl"></h1>
    </div>
    <div class="main"></div>

script.html:

<script>
  $(function(){
    google.script.run
    .withSuccessHandler(updatePageData)
    .getPageData();
  });
    function getUrl(qs){
      google.script.run
      .withSuccessHandler(loadNewPage)
      .getScriptURL(qs);
    }
     function updatePageData(dObj){
      $('.sidenav').html(dObj.menu);
      $('.header #ttl').html(dObj.title);
    }
    function loadNewPage(url){
      window.open(url,"_top");
    }
    console.log('script.html');
</script>

css.html:

A very simple styles page.

<style>
input[type="button"],input[type="text"],label{margin:2px 2px 5px 5px;}
body {
  background-color:#fbd393;
  font-family: "Lato", sans-serif;
}
.sidenav {
  height: 100%;
  width: 75px;
  position: fixed;
  z-index: 1;
  top: 0;
  left: 0;
  background-color: #EEE;
  overflow-x: hidden;
  padding-top: 5px;
}

.sidenav a {
  padding: 6px 8px 6px 16px;
  text-decoration: none;
  font-size: 16px;
  color: #818181;
  display: block;
}
.sidenav a:hover,label:hover {
  color: #770000;
}
.header{
  margin-left: 75px; /* Same as the width of the sidenav */
  font-size: 16px; 
  padding: 0px 5px;
  background-color:#fbd393;
  height:60px;
}

.main {
  margin-left: 75px; /* Same as the width of the sidenav */
  font-size: 16px; /* Increased text to enable scrolling */
  padding: 0px 5px;
  background-color:#e9e8de;
  height:450px;
}

@media screen and (max-height: 450px) {
  .sidenav {padding-top: 5px;}
  .sidenav a {font-size: 16px;}
}

</style>

res.html:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

Animation:

ingrese la descripción de la imagen aquí

Cooper avatar Apr 20 '2019 05:04 Cooper