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