How to find where user's cursor is in Document

2020-06-30 02:45发布

I have a google apps script that is container-bound to a Google Document, and invoked from a custom menu. I would like it to be able to act upon the currently selected text, but I have not found a way for the script to know what text is selected.

My hope is that I could make this code work. The addMyLink() function will attach a custom url (based on some baseUrl) to the selected text.

function onOpen() {
  DocumentApp.getUi().createMenu('Linker')
      .addItem('Add awesome link', 'addMyLink')
      .addToUi();
}

function addMyLink(event) {
  var doc = DocumentApp.getActiveDocument();
  var currElement = event.element;
  var currSelection = {
     startOffset: event.startOffset,
     endOffset:   event.endOffset
  };

  // if selected text does not have a link already, add one
  if (currElement.asText().getLinkUrl(currSelection.startOffset) == null) {
    //Logger.log('no link')
    var url = baseUrl.replace('%target%',matchString)
    //Logger.log(url);
    currElement.asText().setLinkUrl(currSelection.startOffset, currSelection.endOffset, url);
  }
}

Unfortunately, functions invoked from custom menus don't receive events, so this code is only a dream. Is there some other way to get this information?


I've entered a new issue on the issue tracker, please star if you're interested in it:

Issue 2865: Get current user location & state information in Document

2条回答
看我几分像从前
2楼-- · 2020-06-30 03:19

As of right now, this is not possible. If you watch the "Extend Your Script to Google Docs" video, they mention that this feature will be available soon though: http://www.youtube.com/watch?v=KIiCSdRCqXc#t=26m59s

查看更多
贪生不怕死
3楼-- · 2020-06-30 03:25

The ability to work with cursor position and selected text was added yesterday, addressing Issue 2865: Get current user location & state information in Document. See the blog post as well.

The approach provided by Google is different than the one described in the question above - there is no event, instead the information about cursor position and element selection is available through Document.getCursor() and Document.getSelection(), respectively.

Here's the code from the question, adapted to the new APIs. With this example, you can select any text in your document and add a link to a google search using the selected text.

/**
 * If user has selected text, add a url link there, unless
 * the text already has a link.
 */
function addMyLink() {
  var doc = DocumentApp.getActiveDocument();
  var selection = doc.getSelection();

  // get a URL pattern containing %target%.
  // For this example, assume we want to build a google query
  var baseUrl = "https://www.google.com/search?q=%target%";

  if (!selection) {
    tryAgain( "No current selection." );
  }
  else {
    var elements = selection.getSelectedElements();

    // We'll only put a hyperlink on text within a paragraph - if the selection
    // spans paragraphs, reject it.
    if (elements.length > 1) { tryAgain( "Selection cannot span paragraphs." ); return;}

    var element = elements[0].getElement();
    var elementText = element.asText();
    var startOffset = elements[0].getStartOffset();      // -1 if whole element
    var endOffset = elements[0].getEndOffsetInclusive(); // -1 if whole element
    var selectedText = element.asText().getText();       // All text from element
    // Is only part of the element selected?
    if (elements[0].isPartial())
      selectedText = selectedText.substring(startOffset,endOffset+1);

    // Google Doc UI "word selection" (double click) selects trailing spaces - trim them
    selectedText  = selectedText.trim();
    endOffset = startOffset + selectedText.length - 1;

    // If you have poo, fling it now...
    // I mean - if you have other validation steps, put them here.

    // Check if there's a link here already.
    // Caveat: if there a link that starts INSIDE the selection,
    // this won't find it.
    if (elementText.getLinkUrl(startOffset) == null) {
       // Generate the URL, and set it on the selected text
       var url = baseUrl.replace('%target%',selectedText);
      elementText.setLinkUrl(startOffset, endOffset, url);
    }
    else {
      tryAgain( "Remove existing link first." );
    }
  }
}


/*
 * Use Dialog Box to deliver a message to user, with
 * "try again" message.
 *
 * @param {String} message The message to display in the dialog box
 *
 * @return {Button} The button the user clicked
 */
function tryAgain ( message ) {
  var ui = DocumentApp.getUi();
  return ui.alert("Please try again",message,ui.ButtonSet.OK);
}

function onOpen() {
  DocumentApp.getUi().createMenu('Selection')
    .addItem("Add Google Link", 'addMyLink' )
    .addToUi();
}
查看更多
登录 后发表回答