Я пытался использовать некоторые диалоговые окна пользовательского интерфейса JQuery в приложении, которое я изначально написал в App Maker, и я хотел бы иметь его в качестве обычного веб-приложения. Но у меня были некоторые проблемы с событиями, происходящими чаще, чем ожидалось.
Этот код является частью гораздо большего приложения, потому что я считаю его полезным для решения проблем за счет уменьшения количества вещей, с которыми мне приходится иметь дело. Когда код попадает на html-страницу, он читает и читает события в определенном календаре и отображает их вместе с кнопками, которые позволяют пользователю редактировать и сохранять описание каждого события, а также удалять события. В этом случае я также добавил несколько дополнительных кнопок Sav и Edt, которые делают то же самое, за исключением того, что они не используют диалог. Похоже на следующее изображение.
Когда вы нажмете левую нижнюю кнопку «Редактировать», вы увидите диалоговое окно, которое выглядит следующим образом:
Что происходит, если вы нажмете кнопку «Редактировать» под описанием события, откроется диалоговое окно с описанием этого события в текстовой области. Если вы нажмете кнопку «Сохранить» в диалоговом окне, то оно должно сохранить это описание обратно в описании этого события в календаре, а затем снова отобразить события. Но если бы вы нажали кнопку редактирования, а затем кнопку сохранения семь раз ниже, это вывод консоли:
Для каждого openEventDescriptionEditDialog: idS = 05 должен быть один saveEventDescription: idS = 05 и один userCodeAppPanel: 6 dispEvents (). Иногда в журнале указывается количество dispEvents с номером слева. Они происходят все одновременно, потому что они находятся на обратном вызове .withSuccessHandler. Но, как вы можете видеть, в первый раз вы получаете только один, а во второй раз вы получаете два, третий раз 3, четвертый раз 5, пятый раз 5 и так далее.
/*
Unrecognized feature: 'vibrate'.
userCodeAppPanel:2 Unrecognized feature: 'vibrate'.
userCodeAppPanel:46 My code
userCodeAppPanel:6 dispEvents()
1995166154-warden_bin_i18n_warden.js:56 Net state changed from IDLE to BUSY
1995166154-warden_bin_i18n_warden.js:194 Co {message: "There was an error during the transport or process…this request. Error code = 10, Path = /wardeninit", name: "TransportError", stack: "TransportError: There was an error during the tran…/js/1995166154-warden_bin_i18n_warden.js:178:252)"}
1995166154-warden_bin_i18n_warden.js:56 Net state changed from BUSY to IDLE
userCodeAppPanel:15 openEventDescriptionEditDialog: idS=05 , text=Remove the if alreadySent routine.
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 26307.999999999993, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=First Time
1995166154-warden_bin_i18n_warden.js:56 Net state changed from IDLE to BUSY
1995166154-warden_bin_i18n_warden.js:56 Net state changed from BUSY to IDLE
userCodeAppPanel:6 dispEvents()
1995166154-warden_bin_i18n_warden.js:56 Net state changed from IDLE to BUSY
1995166154-warden_bin_i18n_warden.js:56 Net state changed from BUSY to IDLE
userCodeAppPanel:15 openEventDescriptionEditDialog: idS=05 , text=First Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 38723.69999999955, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Second Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 38723.69999999955, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Second Time
1995166154-warden_bin_i18n_warden.js:56 Net state changed from IDLE to BUSY
2userCodeAppPanel:6 dispEvents()
1995166154-warden_bin_i18n_warden.js:56 Net state changed from BUSY to IDLE
userCodeAppPanel:15 openEventDescriptionEditDialog: idS=05 , text=Second Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 50924.50000000008, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Third time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 50924.50000000008, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Third time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 50924.50000000008, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Third time
1995166154-warden_bin_i18n_warden.js:56 Net state changed from IDLE to BUSY
3userCodeAppPanel:6 dispEvents()
1995166154-warden_bin_i18n_warden.js:56 Net state changed from BUSY to IDLE
userCodeAppPanel:15 openEventDescriptionEditDialog: idS=05 , text=Third time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 63643.79999999983, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Fourth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 63643.79999999983, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Fourth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 63643.79999999983, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Fourth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 63643.79999999983, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Fourth Time
1995166154-warden_bin_i18n_warden.js:56 Net state changed from IDLE to BUSY
4userCodeAppPanel:6 dispEvents()
1995166154-warden_bin_i18n_warden.js:56 Net state changed from BUSY to IDLE
userCodeAppPanel:15 openEventDescriptionEditDialog: idS=05 , text=Fourth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 85540.60000000027, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Fifth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 85540.60000000027, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Fifth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 85540.60000000027, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Fifth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 85540.60000000027, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Fifth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 85540.60000000027, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Fifth Time
1995166154-warden_bin_i18n_warden.js:56 Net state changed from IDLE to BUSY
5userCodeAppPanel:6 dispEvents()
1995166154-warden_bin_i18n_warden.js:56 Net state changed from BUSY to IDLE
userCodeAppPanel:15 openEventDescriptionEditDialog: idS=05 , text=Fifth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 100964.39999999985, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Sixth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 100964.39999999985, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Sixth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 100964.39999999985, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Sixth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 100964.39999999985, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Sixth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 100964.39999999985, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Sixth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 100964.39999999985, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Sixth Time
1995166154-warden_bin_i18n_warden.js:56 Net state changed from IDLE to BUSY
5userCodeAppPanel:6 dispEvents()
1995166154-warden_bin_i18n_warden.js:56 Net state changed from BUSY to IDLE
userCodeAppPanel:6 dispEvents()
1995166154-warden_bin_i18n_warden.js:56 Net state changed from IDLE to BUSY
1995166154-warden_bin_i18n_warden.js:56 Net state changed from BUSY to IDLE
userCodeAppPanel:15 openEventDescriptionEditDialog: idS=05 , text=Sixth Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 120348.50000000006, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Seventh Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 120348.50000000006, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Seventh Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 120348.50000000006, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Seventh Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 120348.50000000006, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Seventh Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 120348.50000000006, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Seventh Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 120348.50000000006, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Seventh Time
userCodeAppPanel:21 n.Event {originalEvent: MouseEvent, type: "click", isDefaultPrevented: ƒ, timeStamp: 120348.50000000006, jQuery112407953633868134593: true, …}
userCodeAppPanel:38 saveEventDescription: idS=05 , text=Seventh Time
1995166154-warden_bin_i18n_warden.js:56 Net state changed from IDLE to BUSY
7userCodeAppPanel:6 dispEvents()
1995166154-warden_bin_i18n_warden.js:56 Net state changed from BUSY to IDLE
*/
Затем я сделал то же самое с кнопками Edt и Sav. Я использовал те же функции, что и в методе диалога, но вместо перехода к диалогу я поместил текст в текстовое поле сверху и отредактировал его, а затем нажал кнопку «Sav», и, выполнив несколько раз, обнаружил, что он работает отлично.
Я сократил код настолько, насколько смог.
code.gs
function dialogtestStartUp()
{
SpreadsheetApp.getUi().createMenu('Dialog Test')
.addItem('Test Dialog', 'showDialogTest')
.addToUi();
}
function setupStartUpTrigger(){
if(!isTrigger('dialogtestStartUp')){
ScriptApp.newTrigger('dialogtestStartUp').forSpreadsheet(gSSID).onOpen().create();
}
}
function showDialogTest(){
var ui=HtmlService.createHtmlOutputFromFile('dialogtest').setHeight(550).setWidth(400);
SpreadsheetApp.getUi().showModelessDialog(ui, 'Dialog Test')
}
function saveMyEventDescription(evObj){
Logger.log('saveMyEventDescription:\nevObj.text=%s\nevObj.calId=%s\nevObj.evId=%s\nevObj.idS=%s',evObj.text,evObj.calId,evObj.evId,evObj.idS);
CalendarApp.getCalendarById(evObj.calId).getEventById(evObj.evId).setDescription(evObj.text);
return true;
}
function getEventDescription(evObj){
evObj['text']=CalendarApp.getCalendarById(evObj.calId).getEventById(evObj.evId).getDescription();
Logger.log('getEventDescription:\nevObj.text=%s\nevObj.calId=%s\nevObj.evId=%s\nevObj.idS=%s',evObj.text,evObj.calId,evObj.evId,evObj.idS);
return evObj;
}
function getMyEvents(){//This is where the event descriptions and buttons are generated. Then they're loaded into the html page when it loads.
Logger.log('getMyEvents');
var allCals=CalendarApp.getAllCalendars();
var s=Utilities.formatString('<strong>%s</strong>',Utilities.formatDate(new Date(),Session.getScriptTimeZone(),"E MMM d, yyyy HHmm"));
var min=60 * 1000;
var hr=60 * min;
var day=24 * hr;
var wk=7 * day;
var start = new Date(new Date().setHours(0,0,0));
var end=new Date(start.valueOf() + (5 * wk));
var incl=['Daily Events'];
for(var i=0;i<allCals.length;i++)
{
if(incl.indexOf(allCals[i].getName())>-1)
{
s+=Utilities.formatString('<br /><strong>%s</strong>',allCals[i].getName());
var events=allCals[i].getEvents(start, end);
if(events)
{
s+='<br /><ul>';
for(j=0;j<events.length;j++)
{
var calId=allCals[i].getId();
var evId=events[j].getId();
var evDesc=events[j].getDescription();
var idS=String(i)+String(j);
if(events[j].isAllDayEvent())
{
s+=Utilities.formatString('<li><strong>%s</strong>-AllDay %s <input type="hidden" id="ids-%s" value="%s,%s" /> <input type="button" title="Move or Delete Event Dialog" name="MoveOrDeleteEvent" value="Remove" onClick="movdelDialog(\'ids-%s\',\'%s\',\'%s\');" /></li>',events[j].getTitle(),Utilities.formatDate(events[j].getStartTime(),Session.getScriptTimeZone(),"E MMM d"),idS,calId,evId,idS,calId,evId);
}
else
{
s+=Utilities.formatString('<li><strong>%s</strong>-%s <input type="hidden" id="ids-%s" value="%s,%s" /><input type="button" title="Move or Delete Event Dialog" name="MoveOrDeleteEvent" value="Remove" onClick="movdelDialog(\'%s\',\'%s\',\'%s\');" /></li>',events[j].getTitle(),Utilities.formatDate(events[j].getStartTime(),Session.getScriptTimeZone(),"E MMM d - HHmm"),idS,calId,evId,idS,calId,evId);
}
s+=Utilities.formatString('<br /><div id="evdesc-%s">%s</div> <input id="edtbtn-%s" type="button" value="Edit" title="Edit Dialog" onClick="editEventDescription(\'%s\',\'%s\',\'%s\',\'%s\');" /></li>',idS,evDesc,idS,calId,evId,idS,evDesc);
s+=Utilities.formatString('<input type="button" id="edt-%s" value="Edt" onClick="edtEvntDesc(\'%s\',\'%s\',\'%s\',\'%s\');" />',idS,calId,evId,idS,evDesc);
s+=Utilities.formatString('<input type="button" id="sav-%s" value="Sav" onClick="savEvntDesc(\'%s\',\'%s\',\'%s\',\'%s\');" />',idS,calId,evId,idS,evDesc);
}
s+='</ul>';
}
}
}
return s;
}
function delMyEvents(idA)
{
if(idA)
{
for(var i=0;i<idA.length;i++)
{
var cal=CalendarApp.getCalendarById(idA[i][0]);//calendarId
cal.getEventById(idA[i][1]).deleteEvent();//eventId
}
}
return true;
}
function getTimeStamp()
{
return Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "E MMM dd, yyyy hh:mm a");
}
HTML, который я называю dialogtest.html:
<html>
<head>
<base target="_top">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script>
$(function(){
dispEvents();
});
function dispEvents(){
console.log('dispEvents()');
google.script.run
.withSuccessHandler(upDateEvents)
.getMyEvents();
}
function upDateEvents(hl){
$('#hotbox').html(hl);
}
function openEventDescriptionEditDialog(evObj){
console.log('openEventDescriptionEditDialog: idS=%s , text=%s',evObj.idS,evObj.text);
var alreadySent=false;
$('#dialog-1').dialog({autopen:true,width:250,height:300});
$('#dialog-1 #evdesc').val(evObj.text);
$('#dialog-1 #saveBtn').button().click(function(e){
e.preventDefault();
console.log(e);
evObj.text=$('#dialog-1 #evdesc').val();
if(true){
saveEventDescription(evObj);
alreadySent=true;
}
//$(this).parent().dialog('close');
});
$('#dialog-1 #clsBtn').button().click(function(e){
$(this).parent().dialog('close');
});
}
function editEventDescription(calId,evId,idS,evDesc){
var evObj={calId:calId,evId:evId,idS:idS,text:evDesc};
openEventDescriptionEditDialog(evObj);
}
function saveEventDescription(evObj){
console.log('saveEventDescription: idS=%s , text=%s',evObj.idS,evObj.text);
google.script.run
.withSuccessHandler(function(evObj){
dispEvents();
$('#dialog-1').dialog('close');
})
.saveMyEventDescription(evObj);
}
function edtEvntDesc(calId,evId,idS,evDesc){
var evObj={calId:calId,evId:evId,idS:idS,text:evDesc};
$('#ta1').val(evObj.text);
console.log(evObj);
}
function savEvntDesc(calId,evId,idS,evDesc){
var evObj={calId:calId,evId:evId,idS:idS,text:evDesc};
evObj.text=$('#ta1').val();
console.log(evObj);
google.script.run
.withSuccessHandler(function(Obj){
dispEvents();
})
.saveMyEventDescription(evObj);
}
console.log("My code");
</script>
<style>
#dialog-1{display:none;}
input[type="button"]{background-color:#ffffff;border:1px solid #000;-webkit-appearance:none;}
#dialogs input[type="button"]{margin:10px 0;}
#ta1{direction:ltr;}
</style>
</head>
<body>
<div class="container">
<div id="div1"><textarea id="ta1" rows="10" cols="40"></textarea></div>
<div id="hotbox"></div>
</div>
<input type="button" value="Display Events" onClick="dispEvents();" />
<div id="dialogs">
<div id="dialog-1" title="Edit Event Description">
<textarea id="evdesc" cols="25" rows="6"></textarea>
<input type="button" value="Save Edits" id="saveBtn" title="Save Edits" /><br />
<input type="button" value="Close" id="clsBtn" title="Close Dialog" />
</div>
<input type="button" value="Close" onClick="google.script.host.close();" />
</div>
</body>
</html>
В попытке решить проблему, фактически не понимая, что ее вызывает, я добавил в диалог следующее:
function openEventDescriptionEditDialog(evObj){
console.log('openEventDescriptionEditDialog: idS=%s , text=%s',evObj.idS,evObj.text);
var alreadySent=false;//Added this to mitigate the problem
$('#dialog-1').dialog({autopen:true,width:250,height:300});
$('#dialog-1 #evdesc').val(evObj.text);
$('#dialog-1 #saveBtn').button().click(function(e){
e.preventDefault();
console.log(e);//you will still see these on the console but only one saveEventDescription
evObj.text=$('#dialog-1 #evdesc').val();
if(!alreadySent){//Keeps the additional events from occuring
saveEventDescription(evObj);
alreadySent=true;
}
//$(this).parent().dialog('close');
});
$('#dialog-1 #clsBtn').button().click(function(e){
$(this).parent().dialog('close');
});
}
Итак, мой вопрос: вам действительно нужно отменить переключатели диалога? Поэтому я надеюсь, что кто-то знает, что здесь происходит.
Получив ваши полезные предложения, я внес большинство изменений в html-файл, как показано ниже. Главное не повторять команду инициализации несколько раз.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script>
var gEvObj={};
$(function(){
dispEvents();
$('#dialog-1').dialog({autoOpen: false, width: 250, height: 300, resizable: true, draggable: true});
$('#dialog-1 #saveBtn').button().click(function(e){
saveEventDescription();
});
$('#dialog-1 #clsBtn').button().click(function(e){
$(this).parent().dialog('close');
});
});
function dispEvents(){
console.log('dispEvents()');
google.script.run
.withSuccessHandler(upDateEvents)
.getMyEvents();
}
function upDateEvents(hl){
$('#hotbox').html(hl);
}
function editEventDescription(calId,evId,idS,evDesc){
gEvObj={calId:calId,evId:evId,idS:idS,text:evDesc};
$('#dialog-1 #evdesc').val(gEvObj.text);
$('#dialog-1').dialog("open");
}
function saveEventDescription(){
gEvObj.text=$('#dialog-1 #evdesc').val();
google.script.run
.withSuccessHandler(function(){
dispEvents();
$('#dialog-1').dialog('close');
})
.saveMyEventDescription(gEvObj);
}
console.log("My code");
</script>
<style>
#dialog-1{display:none;}
input[type="button"]{background-color:#ffffff;border:1px solid #000;-webkit-appearance:none;}
#dialogs input[type="button"]{margin:10px 0;}
</style>
</head>
<body>
<div class="container">
<div id="hotbox"></div>
</div>
<input type="button" value="Display Events" onClick="dispEvents();" />
<div id="dialogs">
<div id="dialog-1" title="Edit Event Description">
<textarea id="evdesc" cols="25" rows="6"></textarea>
<input type="button" value="Save" id="saveBtn" title="Save Edits" /><br />
<input type="button" value="Close" id="clsBtn" title="Close Dialog" />
</div>
<input type="button" value="Close" onClick="google.script.host.close();" />
</div>
</body>
</html>
Потом я вошел в другую программу и сделал то же самое, и теперь она работает очень гладко. Спасибо за вашу помощь. Я ценю это.