从附加边栏打开Goog​​le File Picker

时间:2017-12-15 09:51:54

标签: google-apps-script

我希望通过点击Google表单插件侧边栏中的按钮来加载Google云端硬盘文件选择器。

问题

我无法直接从侧边栏找出如何加载选择器(在模态对话框中),然后将文档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>

2 个答案:

答案 0 :(得分:1)

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

... 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活动的详情,请参阅here

希望有所帮助。

答案 1 :(得分:1)

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

<强> Code.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();
}

<强> sidebar.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>

&lt ;?之间的小脚架当'evaluate()'在属于 HtmlTemplate 类的对象上调用时,将触发?&gt; 。有几种类型的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应用程序。希望这会有所帮助。