两个用户界面 (ui) 之间的数据通信 - 应用程序脚本是指客户端实例化的侧边栏

Data communication between two userInterface (ui) - Apps script refer to client instantiated sidebar

提问人:bricoltou59 提问时间:1/25/2023 更新时间:1/28/2023 访问量:28

问:

对于几个人使用谷歌表格库存管理,我使用侧边栏进行身份验证(登录)。这运行良好,但我想允许不同的同时身份验证(在不同的客户端计算机上)

  • 事实上,我的谷歌脚本和 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>