提问人:bricoltou59 提问时间:1/25/2023 更新时间:1/28/2023 访问量:28
两个用户界面 (ui) 之间的数据通信 - 应用程序脚本是指客户端实例化的侧边栏
Data communication between two userInterface (ui) - Apps script refer to client instantiated sidebar
问:
对于几个人使用谷歌表格库存管理,我使用侧边栏进行身份验证(登录)。这运行良好,但我想允许不同的同时身份验证(在不同的客户端计算机上)
- 事实上,我的谷歌脚本和 Z html 表单(集成在用户界面中)应该能够知道和使用当前的代理,通过侧边栏字段记住,只要它没有关闭。
我尝试使用 userProperties、scriptProperties、documentProperties 和 cacheService,但连接的代理随后被记住并供所有用户通用,而不是特定于运行应用程序的每个工作站。我必须在客户端工作。
我知道如何通过我放置在那里的 javascript 代码读取和修改侧边栏的 DOM,并在我的谷歌脚本中恢复此信息。但这里实际上是一个从实例化的侧边栏中查找信息的问题。
我的应用脚本:
function init_SideBar(e) { // init & show the sidebar
htmlSideBar = HtmlService.createHtmlOutputFromFile('htmlSideBar')
.setTitle('htmlSideBar')
.setWidth(300);
htmlSideBar.info="blabla"; // could it be a lead ?
SpreadsheetApp.getUi().showSidebar(htmlSideBar);
}
function gScriptFcGiveToSidebar() { // to send datas in an array to html page
let jSONforSheet= JSON.stringify(objForSheet);
return jSONforSheet;
}
function calledFromFormSubmit(sidebarForm) { // Receive datas from html sidebar
agentConnected=sidebarForm;
if(agentConnected=="Deconnecté"){
ss.toast("Deconnecté")
}else{
ss.toast("Bonjour "+agentConnected);
}
}
html侧边栏.html:
<html>
<head>
<title>HTML DOM Objects</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
</head>
<body>
<label for="dowloading">dowloading</label>
<script>
function submitForm() { // envoi les données du form "sidebarForm" vers la fonction qui dans google script va les récupérer
// login & password verification (tablUser contains a column au login and a column of mp)
var elmts=document.getElementById("sidebarForm");
for(let iUsers=0;iUsers<sidebarObj.tablUser.length;iUsers++){
if (sidebarObj.tablUser[iUsers][0]==elmts.agentId.value){
if(sidebarObj.tablUser[iUsers][1]==elmts.mpId.value ){
document.getElementById('labelConnectId').innerHTML =elmts.agentId.value;
google.script.run.calledFromFormSubmit(elmts.agentId.value);
return;
}
}
}
alert ("password false, try again");
}
function deconnect(){
document.getElementById('labelConnectId').innerHTML ="Deconnecté";
document.getElementById('agentId').value ="Deconnecté";
google.script.run.calledFromFormSubmit("Deconnecté");
}
function jsFcGiveToForm(jSONforSheet){ //
$('#rangeResult').text(jSONforSheet); //$('#rangeResult').text(<nom de la variable qui va finalement délivrer au js, les données du google script>)
sidebarObj=JSON.parse(jSONforSheet);
document.write('<label id="labelConnectId" form="sidebarForm" > '+sidebarObj.agentConnected+'</label>');
document.write('<br><input type="button" value="Deconnect" onclick="deconnect();" />');
document.write('<form id="sidebarForm">');
document.write('<select name="agent" id="agentId">');
document.write('<option value="'+sidebarObj.agentConnected+'">'+sidebarObj.agentConnected+'</option>');
for(let iUsers=0;iUsers<sidebarObj.tablUser.length;iUsers++){
document.write('<option value="'+sidebarObj.tablUser[iUsers][0]+'">'+sidebarObj.tablUser[iUsers][0]+'</option>');
}
document.write('</select>');
document.write('<br /><input type="text" name="mp" id="mpId" value="password">');
document.write('<br /><input type="button" value="Submit" onclick="submitForm();" />');
document.write('<input type="button" value="Close" onclick="google.script.host.close()" />');
}
document.close(); // HYPER IMPORTANT !! libere le navigateur pour qu il continu a charger la page
google.script.run.withSuccessHandler(jsFcGiveToForm).gScriptFcGiveToSidebar();
</script>
</form>
</body>
</html>
一些线索?:
- 我必须使用无脚本吗
<?= blablabla?>
- 使用 Meta 标签 :
var x = document.createElement("META");
x.setAttribute("name", "description");
x.setAttribute("content", "blablabla");
document.head.appendChild(x);
- 使用 htmlOutpu 的属性:
htmlSideBar.info="blabla";
非常感谢您的参与!:)
答:
0赞
bricoltou59
1/28/2023
#1
我找到了一个解决方案,并使用注释的步骤 A1-4 和 B1-12) 描述了序列,您只需要遵循这些步骤即可
Sidebar.gs:
function init_SideBar(e) { //A-1) init & show the sidebar.html
htmlSideBar = HtmlService.createHtmlOutputFromFile('htmlSideBar')
.setTitle('htmlSideBar')
.setWidth(300);// n'est plus modifiable fixé par google à 300 px
htmlSideBar.info="blabla";
HtmlService.SandboxMode=HtmlService.XFrameOptionsMode;
SpreadsheetApp.getUi().showSidebar(htmlSideBar);
}
function gScriptFcGiveToSidebar() { // A-3) to send google sheet datas (array or json...) to htmlSideBar.html page
let jSONforSheet= JSON.stringify(objForSheet);
ss.toast("json"+jSONforSheet);
return jSONforSheet;
}
function gScriptFromSidebarThenGiveToFormIn(sidebarAgent,provenanceFlag){
//Browser.msgBox("2 4 sidebarAgent="+sidebarAgent+" cache="+cacheService.get('sidebarAgent')+"init="+init);
if (provenanceFlag==false) { // B-7) Called by the de html htmlFormIn...withSuccessHandler(jsFcGiveToFormIn)
// Utilities.sleep(8000); // simulating an excess of a retention time of the cache
sidebarAgent=cacheService.get('sidebarAgent'); // B-8) Retieve the useful data in the cache
if (sidebarAgent==null) {return "echec";} // B-9) Abort in case the cache got lost (retention time exceeded)
cacheService.remove('sidebarAgent'); // B-10) Free the cache
return sidebarAgent; //B-11) give to formIn.html the data it expects
}else{ // B-2) provenanceFlag=true means that the call is from the htmlSideBar.html file buton.onclick , (sidebarAgent has the useful data)
if (cacheService.get('sidebarAgent')!=null) return false // B-3) cache not freed, abort proces for try again in a few time
cacheService.put('sidebarAgent',sidebarAgent,5); // B-4) Stock in cache the data for 5 secondes
initFormIn(sidebarAgent); //B5 open the user interface formIn.html that will have to take imediately the data in the cache, then free it
}
}
function calledFromFormSubmit(sidebarForm) { // Receive datas from html sidebar
agentConnected=sidebarForm;
//userProperties.setProperty('agentConnected', agentConnected);
if(agentConnected=="Deconnecté"){
ss.toast("Deconnecté")
}else{
ss.toast("Bonjour "+agentConnected);
}
//SpreadsheetApp.getActiveSheet().appendRow(["test",sidebarForm]);
}
html侧边栏.html:
<!DOCTYPE html>
<html>
<head>
<style>
body { font-size:1em; }
p { color : red; }
</style>
<title>HTML DOM Objects</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
</head>
<body>
<label for="dowloading">dowloading</label>
<?= info?>
<script>
function callFormIn(){ google.script.run.gScriptFromSidebarThenGiveToFormIn(document.getElementById("labelConnectId").innerHTML,true);
}
function submitForm() { // My connect process
var elmts=document.getElementById("sidebarForm");
for(let iUsers=0;iUsers<sidebarObj.tablUser.length;iUsers++){
if (sidebarObj.tablUser[iUsers][0]==elmts.agentId.value){
if(sidebarObj.tablUser[iUsers][1]==elmts.mpId.value ){
document.getElementById('labelConnectId').innerHTML =elmts.agentId.value;
google.script.run.calledFromFormSubmit(elmts.agentId.value);
return;
}
}
}
alert ("mp faux");
}
function writeLabelAndTxtBox(name,id,value){
document.write('<br /><label for="'+name+'">'+name+': </label>');
document.write('<br /><input type="text" name="'+name+'" id="'+id+'" value="'+value+'">');
}
function writeLabel(name){
document.write('<br /><label for="'+name+'">'+name+': </label>');
}
function writeTxtBox(name,id,value){
document.write('<br /><input type="text" name="'+name+'" id="'+id+'" value="'+value+'">');
}
// -----------------------------------------------------------------------------------------------------------------
function clearAndClose(){
google.script.host.close();
}
function deconnect(){
document.getElementById('labelConnectId').innerHTML ="Deconnecté";
document.getElementById('agentId').value ="Deconnecté"; // facultatif ?
google.script.run.calledFromFormSubmit("Deconnecté");
}
function jsFcGiveToSidebar(jSONforSheet){ // A-4) I can Fill the sidebar.html page with json datas received from apps script about goole sheet
// End of the A1-4) states
sidebarObj=JSON.parse(jSONforSheet); // in particular sidebarObj.tablUser[] that contains the sheet columns of logins and passwords
/* sidebarObj.agentConnected was used to don't have to connect when open a new sidebar
(I dont speak aubout the google acount connection)
sidebarObj.keepConnectPropertie==false desactive this mode
i prefer now have to connect on each new sidebar instentiation.
the login is preserved while the sidebar is instantiated.
*/
document.write(new Date().toLocaleDateString());
if (sidebarObj.keepConnectPropertie==false){sidebarObj.agentConnected="Deconnecté"}
document.write('<label id="labelConnectId" form="sidebarForm" > '+sidebarObj.agentConnected+'</label>');
document.write('<br><input type="button" value="Deconnect" onclick="deconnect();" />');
document.write('<form id="sidebarForm">');
document.write('<select name="agent" id="agentId">');
document.write('<option value="'+sidebarObj.agentConnected+'">'+sidebarObj.agentConnected+'</option>');
for(let iUsers=0;iUsers<sidebarObj.tablUser.length;iUsers++){
document.write('<option value="'+sidebarObj.tablUser[iUsers][0]+'">'+sidebarObj.tablUser[iUsers][0]+'</option>');
}
document.write('</select>');
writeTxtBox('mp','mpId','password')
document.write('<br><input type="button" value="Submit" onclick="submitForm();" />');
document.write('<br><input type="button" value="FormIn" onclick="callFormIn();" />'); // B-1) run gScriptFromSidebarThenGiveToFormIn() with data parameter needed
document.write('<input type="button" value="Close" onclick="google.script.host.close()" />');
}
document.close();
google.script.run.withSuccessHandler(jsFcGiveToSidebar).gScriptFcGiveToSidebar(); // A-2) give to jsFcGiveToSidebar() the return of gScriptFcGiveToSidebar()
</script>
</form>
</body>
</html>
htmlFormIn.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<style type="text/css">
.myDiv {cursor:pointer;}
.divBlack{background-color:#000; color:#fff;}
</style>
<label for="dowloading">dowloading</label>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
// ---------------------------------------------- Functions for Javascript ------------------
function writeLabel(name){
document.write('<br /><label for="'+name+'">'+name+': </label>');
}
function writeTxtBox(name,id,value,prefix){
prefix=prefix||'<br />';
document.write(prefix+'<input type="text" name="'+name+'" id="'+id+'" value="'+value+'">');
}
// -------------------------------------------------Wrinting in Body -----
function addRow(){
cptLine++;
//alert(sidebarAgent); // alert(document.getElementById("idLblSidebarAgent").innerHTML);
//document.getElementById("tableForm").appendChild("tr");
let newLin = document.getElementById("tableForm").insertRow(-1); // ajoute un <tr> à la fin de la table
let newCell=newLin.insertCell(0); // ajoute un <td>
newCell.innerHTML = '<input type="text" name="" id=c"'+cptLine+'" value="v'+cptLine+'"> <input type="text" name="" id=d"'+cptLine+'" value="'+sidebarAgent+'">';
//alert("ajouté");
}
function jsFcGiveToFormIn(aagent){ // B-12) aagent receive the data value return from gScriptFromSidebarThenGiveToFormIn that have been called in A6 state
// B-13) the formIn.html can fill its fields :) - End of the B1-12) states
if (aagent=="echec"){ alert ("htmlFormIn 71 le cache service n'a pas memorisé assez longemps le transfert de donnée depuis la sidebar")}
sidebarAgent=aagent; // pour étendre la portée de cette info dans le script de cette page html
document.write('<label id="idLblSidebarAgent" for="info">'+sidebarAgent+'</label>')
writeTxtBox("Saisie","idSaisie","Entrez un code");
document.getElementById("idSaisie").addEventListener("click", addRow);
document.write('<form id="sidebarForm">');
document.write('<table id="tableForm"><tr id="r'+cptLine+'""><td>');writeTxtBox("Date","iddat","date"," ");writeTxtBox("Ref","idRef"+cptLine,""," ");
writeTxtBox("agent","idAgent",sidebarAgent," ");
document.write('</td></tr>')
document.write('</table>')
document.write('</form>');
}
document.close();
var cptLine=0;
var sidebarAgent;
google.script.run.withSuccessHandler(jsFcGiveToFormIn).gScriptFromSidebarThenGiveToFormIn("",false); // B-6) give to jsFcGiveToFormIn the return of gScriptFromSidebarThenGiveToFormIn("",provenanceFlag=false) with provenanceFlag=false that meaning the call is from formIn.html file.
</script>
</body>
</html>
评论