Как мне отладить Javascript, обслуживаемый через HtmlService?

#javascript #debugging #google-apps-script #client #vivaldi

#javascript #отладка #google-apps-script #клиент #вивальди

Вопрос:

Я использую HtmlService для обслуживания веб-страницы с формой и некоторым Javascript, но я не знаю, как отлаживать код на стороне клиента. Поскольку HtmlService использует песочницу iframe, я не могу использовать консоль разработчика браузера, и я не могу понять, как записывать журналы в Stackdriver; ни консоль.журнал или Logger.log, похоже, ничего не делают. Поскольку код зависит от доступа к функциям на стороне сервера, я также не могу просто загрузить страницу и открыть ее в браузере. Есть ли хороший способ сделать это?

Для справки вот мой (неполный) код:
index.html

 <!DOCTYPE html>
<html>
  <head>
    <base target="_self"/>
    <meta charset="utf-8"/>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc NcPb1dKGj7Sk" crossorigin="anonymous" />
    <style>small {
        color: grey;
      }
      body {
        background-color: aliceblue;
      }
      div.container {
        background-color: white;
      }
      input:invalid, select:invalid{
        border-color: red;
      }
      input:valid, select:valid{
        border-color: darkgreen;
      }
    </style>
  </head>
  <body>
    <div class="container border rounded-lg mt-2 mb-2 pt-2 pb-2" style="max-width: 50rem;">
      <div class="row">
        <div class="col">
          <h1 class="text-center">Bokning av Informationskväll</h1>
          <hr/>
          <form id="bookingForm">
            <div class="form-row">
              <label class="form-group col">E-postadress<input type="email" class="form-control" name="email" required/></label>
              <label class="form-group col">För- och efternamn<input type="text" class="form-control" name="fullName" required/></label>
            </div>
            <hr/>
            <div class="form-row">
              <label class="form-group col">Välj tilfälle<select class="form-control col required" name="eventId" id="timeSlotSelect" required></select></label>
              <label class="form-group col">Antal personer <small>(inklusive dig själv)</small>
                <select class="form-control col required" name="numVisitors" id="visitorSelect" required>
                  <option value="1" selected>Bara mig själv</option>
                  <option value="2">2</option>
                  <option value="3">3</option>
                  <option value="4">4</option>
                </select>
              </label>
            </div>
            <hr/>
            <div class="form-row">
              <button class="btn btn-primary btn-block" id="submitButton">Boka</button>
            </div>
          </form>
        </div>
      </div>
    </div>
    <script>
      const form = document.forms['bookingForm'];
      const submitButton = document.getElementById('submitButton');
      let timeSlotSelect = document.getElementById('timeSlotSelect');
      const visitorSelect = document.getElementById('visitorSelect');
      const timeSlots = google.script.run.withFailureHandler(failurePopup).getAvailableTimeslots();

      function populateTimeSlots(){
        //let timeSlots = google.script.run.withSuccessHandler(successPopup).withFailureHandler(failurePopup).getAvailableTimeslots();
        console.log(timeSlots);
        alert(timeSlots.toString());
        let option = document.createElement("OPTION");
        timeSlotSelect.options.add(option);
        option.value = "";
        option.text = "Välj tillfälle...";
        for (let timeSlot of timeSlots){
          console.log(timeSlot);
          let option = document.createElement("OPTION");
          timeSlotSelect.options.add(option);
          option.value = timeSlot.eventId;
          option.text = timeSlot.eventTitle   " ["   timeSlot.bookedSlots   "/"   timeSlot.maxCapacity   "]";
          if (timeSlot.availableSlots < 1){
            option.disabled = true;
          }
          console.log(option);
        }
      }

      function checkNumSlots(){
        //let timeSlots = google.script.run.getAvailableTimeslots().withFailureHandler(failurePopup);

      }

      function successPopup(message){
        alert("Success!n " message.toString();
        console.log(message);
      }
      function failurePopup(error){
        alert("Uh oh!n " error.toString());
        console.log(error);
      }
      function submitBooking(){
        //alert("Försöker skicka in bokning...");
        let formFields = new FormData(form);
        let timeStamp = new Date();
        formFields.set("timeStamp", timeStamp);
        google.script.run.withSuccessHandler(successPopup).withFailureHandler(failurePopup).bookTimeSlot(formFields);
        form.reset();
      }
      form.addEventListener('submit', function(event){
        event.preventDefault();
        submitBooking();
      });
      window.addEventListener('load', populateTimeSlots);

    </script>
  </body>
</html>  

Code.gs

 var scriptProp = PropertiesService.getScriptProperties();
var scriptLock = LockService.getScriptLock();

function initialSetup() {
  const properties = {spreadsheetId: "1s0qVkY_zgISKfKckWJeg49fJVLxedF5eOVnCybbI1hw", dataSheetName: "bookingData", infoSheetName: "eventInfo"};
  scriptProp.setProperties(properties);
  const spreadSheet = SpreadsheetApp.openById(properties.spreadsheetId);
}

function doGet(){
  var output = HtmlService.createTemplateFromFile('index').evaluate();
  output.setTitle("Bokning av infokväll Hälsingegymnasiet");
  return output;
}

function getAvailableTimeslots(){
  Logger.log("Sidan frågar efter tillgängliga tillfällen...");
  scriptLock.waitLock(30000);
  try {
    let events = [];
    const id = scriptProp.getProperty('spreadsheetId');
    const infoSheetName = scriptProp.getProperty('infoSheetName');
    const ss = SpreadsheetApp.openById(id);
    const eventSheet = ss.getSheetByName(infoSheetName);
    //Logger.log(header);
    const lastRow = eventSheet.getLastRow();
    const lastColumn = eventSheet.getLastColumn();
    const header = eventSheet.getRange(1, 1, 1, lastColumn).getValues()[0];
    const data = eventSheet.getRange(2, 1, lastRow-1, lastColumn).getValues();
    for (var i=0; i < lastRow-1; i  ){
      let event = {};
      for (var j=0; j < lastColumn-1; j  ){
        event[header[j]] = data[i][j];
        //Logger.log(header[j] " : " range[i][j]);
      }
      //Logger.log(event);
      events.push(event);
    }
    //Logger.log(events);
    return events;
  }catch(e){
    Logger.log("Ett fel inträffade: " e);
    return e;
  }
  finally {
    scriptLock.releaseLock()
  }
}

function bookTimeslot(formData){
  scriptLock.waitLock(30000);
  try{
    Logger.log("Inskickat formulär: " formData);
    const id = scriptProp.getProperty('spreadsheetId');
    const dataSheetName = scriptProp.getProperty('dataSheetName');
    const ss = SpreadsheetApp.openById(id);
    const bookingSheet = ss.getSheetByName(dataSheetName);
    const lastColumn = bookingSheet.getLastColumn();
    const header = bookingSheet.getRange(1, 1, 1, lastColumn).getValues()[0];



  }catch(e){
    Logger.log("Ett fel inträffade: " e);
    return e;
  }finally{
    scriptLock.releaseLock();
  }
}  

РЕДАКТИРОВАТЬ: понял это; оказалось, проблема с моим веб-браузером (Vivaldi). Вместо этого переключился на Google Chrome, и теперь все работает нормально. Немного странно, учитывая, что оба браузера основаны на Chromium, но ладно.

Комментарии:

1. Поскольку HtmlService использует песочницу, я не могу использовать консоль разработчика браузера , что ?!

2. Насколько я могу судить, HtmlService обслуживает содержимое HTML в iframe и переписывает все, что в нем содержится JS. Это означает, что 1. HTML-страницы скрыты от инспектора элементов и 2. Ошибки / сообщения / журналы HTML / JS не выводятся на консоль. Ну, по крайней мере, я думаю, что это происходит.

3. Вы … пробовали использовать консоль разработчика браузера?

4. @RafaGuillermo Ну, да, иначе я бы так не сказал. В любом случае, возникла проблема с моим веб-браузером (Vivaldi); переключился на Chrome, и теперь он работает нормально.

Ответ №1:

Я понял это; оказывается, мой браузер (Vivaldi) плохо работает с любым методом, который HtmlService представляет контент. Я переключился на Google Chrome, и теперь я получаю вывод в консоли разработчика.