打开/关闭Google Picker对话框时,如何在加载项侧栏中显示/隐藏加载微调器? [英] How to show/hide loading spinner in addon sidebar while Google Picker dialog is opened/closed?
问题描述
我遵循了本教程: https://developers.google. com/apps-script/guides/dialogs#file-open_dialogs ,然后点击插件侧边栏中的按钮即可打开Google Picker.
I followed this tutorial: https://developers.google.com/apps-script/guides/dialogs#file-open_dialogs and I can open a Google Picker after clicking a button inside my addon sidebar.
我想做两件事为用户提供更好的用户体验:
I want to do 2 things for better UX for my users:
-
第一件事是当Google Picker打开时,我想在加载项侧边栏中显示一个加载微调器(以防止用户与侧边栏进行交互),以便用户只能与Google Picker进行交互,直到它是关闭的
The first thing is when the Google Picker is open, I want to show a loading spinner inside my addon sidebar (to prevent users from interacting with the sidebar), so that users can only interact with the Google Picker until it's closed
用户选择文档或直接关闭Google Picker后,插件侧边栏中的加载微调框也会立即消失(我们不应该重新加载侧边栏),用户可以与插件侧栏正常交互
After users choose a document or directly close the Google Picker, the loading spinner in the addon sidebar will also be disappeared immediately (we shouldn't reload the sidebar), and users can interact with the addon sidebar normally
请注意:加载指示器位于插件侧栏的内部 (不在选择器对话框中)
Please note: the loading indicator is inside the addon sidebar (not inside the picker dialog)
我所做的是:
我有2个文件:
- sidebar.html
- picker.html
这两个html文件都包含运行每个文件所需的html,css和js.
Both these html files contain html, css, js that you need to run each of them.
在sidebar.html
内,当我需要打开选择器时,我会打电话:
Inside the sidebar.html
, when I need to open the Picker, I will call:
function openPicker() {
// Show spinner here
showSpinner()
google.script.run
.withSuccessHandler(function() { console.log('ok') })
.showPicker()
}
上面的函数将在Code.gs
中调用此showPicker()函数:
Above function will call this showPicker() function in Code.gs
:
function showPicker() {
var html = HtmlService.createHtmlOutputFromFile('picker.html')
.setWidth(800)
.setHeight(600)
FormApp.getUi().showModalDialog(html, 'Select a file')
}
在picker.html
内,我有一个回调:
function pickerCallback(data) {
var action = data[google.picker.Response.ACTION]
if (action === google.picker.Action.PICKED) {
var doc = data[google.picker.Response.DOCUMENTS][0]
var id = doc[google.picker.Document.ID]
var url = doc[google.picker.Document.URL]
var title = doc[google.picker.Document.NAME]
document.getElementById('result').innerHTML =
'<b>You chose:</b><br>Name: <a href="' + url + '">' + title + '</a><br>ID: ' + id
} else if (action === google.picker.Action.CANCEL) {
google.script.host.close()
}
// This is a good place to hide the spinner,
// but this is picker.html, so it can not control code in sidebar.html to hide the spinner
}
这里的问题是,sidebar.html
仅知道何时显示微调器,而不知道何时关闭它.
The problem here is, the sidebar.html
can only know when to show the spinner, not when to close it.
检测何时应该关闭微调器的逻辑在于picker.html本身(只有选择器才知道用户何时选择了文档或取消了选择器).
The logic to detect when we should close the spinner lies in the picker.html itself (only the picker knows when the user has selected a document or canceled the picker).
而且我不知道如何将该逻辑传递给sidebar.html
,以便它可以在sidebar.html
内部的某个地方运行hideSpinner()
.
And I don't know how to pass that logic to the sidebar.html
so that it can run hideSpinner()
somewhere inside sidebar.html
.
推荐答案
问题:
侧边栏和模式对话框尽管起源相同,但仍无法通信.
Issue:
Sidebar and modal dialog are not able to communicate despite having same origin.
可以通过window.top
从模态对话框中获取对侧边栏html的引用.从那里,可以
It is possible to get a reference to the sidebar html from modal dialog through window.top
. From there, it is possible to
- 直接相互交流
- 使用
window.postMessage()
相互交流 - 使用Cookie/本地存储彼此通信
- directly communicate with each other
- use
window.postMessage()
to communicate with each other - use cookies/localstorage to communicate with each other
在没有相互引用的情况下,仍然可以通过
Without a reference to each other, it is still possible to communicate with each other through
- 服务器和脚本属性服务.但是,在这里,其中一个需要按设定的时间间隔轮询服务器,以获取另一个的更新.
addOn.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>Addon</title>
<style>
#spinner {
display: none;
background-color: tomato;
position: absolute;
top: 1%;
width: 100%;
justify-items: center;
}
</style>
</head>
<body>
<div id="spinner"><p>Loading modal dialog...</p></div>
<div id="output"></div>
<script charset="utf-8">
google.script.run.withSuccessHandler(spinner).testModal();
function spinner(e) {
document.getElementById('spinner').style.display = e || 'flex';
}
(async () => {
//After modal dialog has finished, receiver will be resolved
let receiver = new Promise((res, rej) => {
window.modalDone = res;
});
var message = await receiver;
document.querySelector('#output').innerHTML = message;
//Do what you want here
})();
</script>
</body>
</html>
modalAddOn.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title></title>
</head>
<body>
Modal Dialog
<script>
(function findSideBar(limit) {
let f = window.top.frames;
for (let i = 0; i < limit; ++i) {
try {
if (
f[i] /*/iframedAppPanel*/ &&
f[i].length &&
f[i][0] && //#sandboxFrame
f[i][0][0] && //#userHtmlFrame
window !== f[i][0][0] //!== self
) {
console.info('Sidebar found ');
alert('Removing loadbar and closing self');
var sidebar = f[i][0][0];
sidebar.spinner('none'); //Remove sidebar spinner
sidebar.modalDone('Modal says Hi'); //Modal has finished
google.script.host.close();
}
} catch (e) {
console.error(e);
continue;
}
}
})(10);
</script>
</body>
</html>
code.gs
function testModal() {
SpreadsheetApp.getUi().showModelessDialog(
HtmlService.createHtmlOutputFromFile('modalAddOn')
.setHeight(500)
.setWidth(300),
' '
);
}
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu('Sidebar')
.addItem('Show Add-On', 'showSidebar')
.addToUi();
}
function showSidebar() {
SpreadsheetApp.getUi().showSidebar(
HtmlService.createTemplateFromFile('addOn.html').evaluate()
);
}
阅读:
- Window#frames
- Window#postMessage
- 相同的来源政策
- Document#cookie
- Window#storage
- 承诺
- PropertiesService
- Window#frames
- Window#postMessage
- Same origin policy
- Document#cookie
- Window#storage
- Promises
- PropertiesService
- Window#postMessage
- Window#storage
- Origin
To Read:
这篇关于打开/关闭Google Picker对话框时,如何在加载项侧栏中显示/隐藏加载微调器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!