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