Moving browser focus in Google Apps using Ui Servi

2019-09-06 18:00发布

I'm building a small script bound to a Google Document. The script creates a menu entry and a sidebar. The sidebar contains a single button that, when clicked, inserts today's date at the cursor in the document. The menu entry does the same.

When using the menu entry to insert the date, the date is inserted, and the cursor stays focused into the document editing area. But, when the button is clicked from the side-bar, the focus is lost.

Digging a bit in the docs, I found at Moving browser focus in Google Apps this blurb:

To switch focus in the user's browser from a dialog or sidebar back to the Google Docs, Sheets, or Forms editor, simply call the method google.script.host.editor.focus(). This method is particularly useful in combination with the Document service methods Document.setCursor(position) and Document.setSelection(range).

But the call to google.script.host.editor.focus() fails from within a click handler when using the Ui Service in a Google Document. What is the equivalent UI Service method(s) to force focus back to the document area?

Here is my script which is bound to the Google Document. See the commented out call to google.script.host.editor.focus() inside the myClickHandler function.

function onOpen() {
  // Add a menu with some items, some separators, and a sub-menu.
  DocumentApp.getUi().createMenu('Sidebars')
      .addItem('Insert Date at cursor', 'insertDateAtCursor')
      .addItem('Show sidebar', 'showSidebar')
      .addToUi();
}

/**
 * Insert a Date at the current cursor location.
 */
function insertDateAtCursor() {
  var cursor = DocumentApp.getActiveDocument().getCursor();

  if (cursor) {
    // Attempt to insert text at the cursor position. If insertion returns null,
    // then the cursor's containing element doesn't allow text insertions.
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
    var today = new Date;
    var element = cursor.insertText( today.getFullYear() + "-" + today.getDate() + "-" + (today.getMonth()+1) );
    if (!element) {
      DocumentApp.getUi().alert('Cannot insert text at this cursor location.');
    }
  } else {
    DocumentApp.getUi().alert('Cannot find a cursor in the document.');
  }
}

/**
 * Show the side bar:
 */
function showSidebar() {
  // https://developers.google.com/apps-script/guides/ui-service
  var app = UiApp.createApplication().setTitle('Utility Sidebar');
  var panel = app.createVerticalPanel();
  var button = app.createButton("Insert Date At Cursor");
  panel.add(button);
  app.add(panel);
  
  // https://developers.google.com/apps-script/guides/ui-service#ServerHandlers
  var handler = app.createServerHandler('myClickHandler');
  button.addClickHandler(handler);

  DocumentApp.getUi().showSidebar(app);
}

/**
 * Handle the button click:
 */
function myClickHandler(e) {
  var app = UiApp.getActiveApplication();

  insertDateAtCursor();
  
  // What is the UiApp equivalent of this?:
  // google.script.host.editor.focus();
  
  // Calling app.close() closes the side bar so comment this out:
  // app.close();
  return app;
}

2条回答
迷人小祖宗
2楼-- · 2019-09-06 18:47

I created a sidebar for a Google Sheet with buttons that executed a function, and that function changed the active range in the current sheet. Clicking the button would not allow the user to type directly in the sheet until I added the focus command to the button in the HtmlService interface, not in the function.

<button onclick="google.script.run.doSomething();google.script.host.editor.focus();"><b>Next</b></button><br>
查看更多
Explosion°爆炸
3楼-- · 2019-09-06 18:51

UiApp runs entirely on a distant server, it can't interact directly with your browser and change the focus. Sine your UI is very simple I'd suggest you convert your script to use HTMLService instead of UiApp,it will be a good occasion to give it a try without too much headache :-)

查看更多
登录 后发表回答