简体   繁体   中英

Caching Selected Text Element with Google Doc Apps Script

Update: This is a better way of asking the following question.

Is there an Id like attribute for an Element in a Document which I can use to reach that element at a later time. Let's say I inserted a paragraph to a document as follows:

var myParagraph = 'This should be highlighted when user clicks a button';
body.insertParagraph(0, myParagraph);

Then the user inserts another one at the beginning manually (ie by typing or pasting). Now the childIndex of my paragraph changes to 1 from 0 . I want to reach that paragraph at a later time and highlight it. But because of the insertion, the childIndex is not valid anymore. There is no Id like attribute for Element interface or any type implementing that. CahceService and PropertiesService only accepts String data, so I can't store myParagraph as an Object .

Do you guys have any idea to achieve what I want?

Thanks,

Old version of the same question (Optional Read):

Imagine that user selects a word and presses the highlight button of my add-on. Then she does the same thing for several more words. Then she edits the document in a way that the start end end indexes of those highlighted words change.

At this point she presses the remove highlighting button . My add-on should disable highlighting on all previously selected words. The problem is that I don't want to scan the entire document and find any highlighted text. I just want direct access to those that previously selected.

Is there a way to do that? I tried caching selected elements. But when I get them back from the cache, I get TypeError: Cannot find function insertText in object Text. error. It seems like the type of the object or something changes in between cache.put() and cache.get() .

var elements = selection.getSelectedElements();
    for (var i = 0; i < elements.length; ++i) {
      if (elements[i].isPartial()) {
        Logger.log('partial');
        var element = elements[i].getElement().asText();

        var cache = CacheService.getDocumentCache();
        cache.put('element', element);  


        var startIndex = elements[i].getStartOffset();
        var endIndex = elements[i].getEndOffsetInclusive();
     }
    // ...
   }

When I get back the element I get TypeError: Cannot find function insertText in object Text. error.

 var cache = CacheService.getDocumentCache();
 cache.get('text').insertText(0, ':)');  

I hope I can clearly explained what I want to achieve.

One direct way is to add a bookmark , which is not dependent on subsequent document changes. It has a disadvantage: a bookmark is visible for everyone...

More interesting way is to add a named range with a unique name. Sample code is below:

function setNamedParagraph() {
  var doc = DocumentApp.getActiveDocument();
  // Suppose you want to remember namely the third paragraph (currently)
  var par = doc.getBody().getParagraphs()[2];
  Logger.log(par.getText());
  var rng = doc.newRange().addElement(par);
  doc.addNamedRange("My Unique Paragraph", rng);
}


function getParagraphByName() {
  var doc = DocumentApp.getActiveDocument();
  var rng = doc.getNamedRanges("My Unique Paragraph")[0];
  if (rng) {
    var par = rng.getRange().getRangeElements()[0].getElement().asParagraph();
    Logger.log(par.getText());
  } else {
    Logger.log("Deleted!");
  }
}

The first function "marks" the third paragraph as named range. The second one takes this paragraph by the range name despite subsequent document changes. Really here we need to consider the exception, when our "unique paragraph" was deleted.

Not sure if cache is the best approach. Cache is volatile, so it might happen that the cached value doesn't exist anymore. Probably PropertiesService is a better choice.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM