0

我希望通过单击 Google Form 附加边栏中的按钮来加载 Google Drive 文件选择器。

问题

我无法弄清楚如何直接从侧边栏加载选择器(在模式对话框中),然后将文档 ID 回调到侧边栏。

我已经能够成功加载模态对话框,然后从模态对话框加载选择器,但是我很难理解如何直接从侧边栏加载选择器。

任何指导表示赞赏。我当前的代码如下所示。

.gs 文件:

function onOpen(e) {
  FormApp.getUi()
  .createAddonMenu()
  .addItem('Picker', 'showSidebar')
  .addToUi();
}

function showSidebar(){

    var ui = HtmlService.createHtmlOutputFromFile('Sidebar')
  .setSandboxMode(HtmlService.SandboxMode.IFRAME)
  .setTitle('Title');
  FormApp.getUi().showSidebar(ui);

}

function openPicker(){

  var html = HtmlService.createHtmlOutputFromFile('Picker')
  .setWidth(600)
  .setHeight(425)
  .setSandboxMode(HtmlService.SandboxMode.IFRAME);
  FormApp.getUi().showModalDialog(html, 'Select a file');

}


function getOAuthToken() {
  DriveApp.getRootFolder();
  return ScriptApp.getOAuthToken();
}

侧边栏 html

<!DOCTYPE html>
<html>
  <head>
  <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
    <base target="_top">
  </head>
  <body>
    <button onclick='openPicker()'>Select a file</button>
  </body>
</html>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>


function openPicker() {
google.script.run
.withSuccessHandler(success)
.withFailureHandler(failure)
.openPicker();
}

function success() {
console.log('success');
}

function failure() {
console.log('failure');
}

</script>

选择器 html

 <!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
  <script>

    var DEVELOPER_KEY = '';
    var DIALOG_DIMENSIONS = {width: 600, height: 425};
    var pickerApiLoaded = false;


    function onApiLoad() {
      gapi.load('picker', {'callback': function() {
        pickerApiLoaded = true;
      }});
     }


    function getOAuthToken() {
      google.script.run
      .withSuccessHandler(createPicker)
      .withFailureHandler(showError)
      .getOAuthToken();
    }


    function createPicker(token) {
    console.log("here");
      if (pickerApiLoaded && token) {
        var picker = new google.picker.PickerBuilder()
            // Instruct Picker to display only spreadsheets in Drive. For other
            // views, see https://developers.google.com/picker/docs/#otherviews
            .addView(google.picker.ViewId.DOCUMENTS)
            // Hide the navigation panel so that Picker fills more of the dialog.
            .enableFeature(google.picker.Feature.NAV_HIDDEN)
            // Hide the title bar since an Apps Script dialog already has a title.
            .hideTitleBar()
            .setOAuthToken(token)
            .setDeveloperKey(DEVELOPER_KEY)
            .setCallback(pickerCallback)
            .setOrigin(google.script.host.origin)
            // Instruct Picker to fill the dialog, minus 2 pixels for the border.
            .setSize(DIALOG_DIMENSIONS.width - 2,
                DIALOG_DIMENSIONS.height - 2)
            .build();
        picker.setVisible(true);
      } else {
        showError('Unable to load the file picker.');
      }
    }


    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) {
        document.getElementById('result').innerHTML = 'Picker canceled.';
      }
    }


    function showError(message) {
      document.getElementById('result').innerHTML = 'Error: ' + message;
    }
  </script>
</head>
<body>
  <div>
    <button onclick='getOAuthToken()'>Select a file</button>
    <p id='result'></p>
  </div>
  <script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
</html>
4

2 回答 2

1

这是我想出的快速而肮脏的解决方案。我的“.gs”文件包含用于显示通过HtmlService提供的 UI 容器和获取 OAuth 令牌的函数。请注意,您可以在将数据模型转换为原始 HTML 并传递给客户端之前将它们传递给HtmlTemplate对象。当我们从自定义菜单调用“showSidebar”函数时,没有传递任何参数,所以这是第一次调用。如果 'params' 不是 'undefined',我们就知道调用来自模态对话框。

代码.gs

var ui = SpreadsheetApp.getUi()


//add custom menu to the spreadsheet;
function onOpen() {

ui.createMenu('Sidebar')
.addItem('Show sidebar', 'showSidebar')
.addToUi();

}

function showSidebar(params){

var sidebar = HtmlService.createTemplateFromFile('sidebar');
var model = "your selection"; //default message to be displayed

  if (params) { //if arguments are passed, it's a callback from modal dialog
    model = "You selected document with id: " +     
                  params.id + ", title: " + params.title + 
                  " url: " + params.url; 
  }  

sidebar.model = model; // pass model to the template
var htmlOutput = sidebar.evaluate(); //execute inline scriplets from the template to complete DOM construction. 
ui.showSidebar(htmlOutput); //pass resulting UI object to sidebar container

}

function showModalDialog() {

// produce HtmlOutput for modal dialog
var modalDialog = HtmlService.createTemplateFromFile('modal_dialog')
                             .evaluate()
                             .setWidth(600)
                             .setHeight(425)
                             .setSandboxMode(HtmlService.SandboxMode.IFRAME); 

ui.showModalDialog(modalDialog, 'Picker');


}

function getOAuthToken() {
  DriveApp.getRootFolder();
  return ScriptApp.getOAuthToken();
}

边栏.html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
  <input type="button" id="button" value="Open picker">
  <div>  Selection:  <?!=  model ?> </div>  

  <script>

  window.onload = (function(){

  var button = document.getElementById('button');
  button.addEventListener('click', function(event){

  google.script.run
               .withSuccessHandler(function(){             

                 google.script.host.close();             

               })
               .showModalDialog(); 

  });


  })();  
  </script>
  </body>
</html>

< ? ?>将在对属于HtmlTemplate类的对象调用'evaluate()'时触发。有几种类型的 scriptlet - 更多关于 scriptlet 的信息:

https://developers.google.com/apps-script/guides/html/templates#scriptlets

添加“!” 紧接在第一个“?”之后 将结果强制打印到页面。加载 DOM 树后,当用户单击按钮时 ,我在“.gs”文件中添加执行“showDialog()”函数的事件侦听器。

对话框窗口的模板来自此处的选择器快速入门

https://developers.google.com/apps-script/guides/dialogs

我修改了“onApiLoaded”函数以在加载后立即显示选择器。

 function onApiLoad() {
      gapi.load('picker', {'callback': function() {
        pickerApiLoaded = true;
        getOAuthToken();

      }});
     }

最后,我将以下代码添加到“pickerCallback”函数中。

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];

        google.script.run.withSuccessHandler(function(){

           google.script.host.close();

        }).showSidebar({id: id, url: url, title: title});

当用户进行选择时,数据将作为参数传递给“.gs”文件中的“showSideBar”函数。由于“google.script.host(run)”调用是异步的,我将关闭窗口的调用放在“withSuccessHandler”中以防止提前关闭。

结果:选择数据显示在边栏中。

还有另一种我更喜欢的方法。在 GAS 中,即使是文件绑定脚本也可以发布为 Web 应用程序,因此您基本上可以通过 UrlFetchApp.fetch() 调用来创建多页应用程序。例如,您可以定义一个包含单个“容器”div 的母版页。您还可以存储所有 JS 代码并在母版页上加载 API。如果您需要导航到另一个页面,您可以简单地通过 fetch(url) 查询 Web 应用程序并将生成的 html 粘贴到母版页上的容器中

containerDiv.innerHTML = html;

可以通过调用 ScriptApp.getService().getUrl() 动态获取 Web 应用的 url。但是,该脚本必须首先作为可匿名访问的 Web 应用程序发布。希望这可以帮助。

于 2017-12-16T17:31:43.713 回答
0

只需修改您的选择器 Html 代码以getOAuthToken()在模态对话框上的 html 加载时自动运行函数,如下所示:

... Code till here remains as above
<body onload = 'getOAuthToken()'>
  <div>
    <p id='result'></p>
  </div>
  <script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
</html>

有关onload活动的更多详细信息,请参阅此处

希望有帮助。

于 2017-12-15T17:11:32.560 回答