Как отлаживать Javascript, обслуживаемый через HtmlService?
Я использую HtmlService для обслуживания веб-страницы с формой и некоторым Javascript, но я не знаю, как отлаживать клиентский код. Поскольку HtmlService использует песочницу iframe, я не могу использовать консоль разработчика браузера, и я не могу понять, как писать журналы в Stackdriver; ни console.log, ни 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();
}
}
РЕДАКТИРОВАТЬ: разобрался; Оказалось, что проблема в моем веб-браузере (Вивальди). Вместо этого перешел на Google Chrome, и теперь все работает нормально. Странно, учитывая, что оба браузера основаны на Chromium, ну да ладно.
1 ответ
Я понял; Оказывается, мой браузер (Vivaldi) плохо работает с любым методом, который HtmlService представляет контент. Я перешел на Google Chrome и теперь получаю вывод в консоли разработчика.