Search code examples
javascriptgoogle-apps-scriptgoogle-docsgoogle-appsgoogle-docs-api

Change the color of the word where the cursor is with Google Apps Script in a Google Document


I'm trying to change the color of the word the current google docs cursor is over (when a server function is executed). I'm not sure how to do that. I saw: Get current word in google-apps-script which explained how to get the last word of the line, but that doesn't really work, this is what I have (very rough code):

function clientize() {///
  var t = Date.now();
  var doc = DocumentApp.getActiveDocument().getCursor();
  var els = doc.getElement();
  var txt = els.asText().getText().split(" ");
  var word = txt[txt.length - 1];
  var offset = doc.getOffset();
  var highlightStyle = {};
  highlightStyle[DocumentApp.Attribute.FOREGROUND_COLOR] = '#FF0000';
  els.setBold(offset - 5,offset , true)
 // els.setAttributes(4,10,highlightStyle);

  return (word)
}

but it only gives me the last word on the line, not the word that the cursor is actually in, and also I don't know how to change the color of the word in the document once I find the text. I know I can change the color based on a certain range, but it only works on the getElement(), but how do I change the specific range of the whole word that the cursor is on?

For example, say I have the line, with the cursor:

hello world ho|w are you today

then when I activate the server function, only the word "how" should be changed to red, for example.

How is this possible????


Solution

  • enter image description here

    You can do so, the trick is to get the offsets for the start & end of the current user's word.

    function clientize() {
    
      // Get the Position of the user's cursor
      var position = DocumentApp.getActiveDocument().getCursor();
    
      // Get the element that contains this Position
      var ref_element = position.getElement();
    
      // Get the text in the element
      var text = ref_element.asText().getText(); 
    
      // Get the cursor's relative location within ref_element.
      // Verify if cursor is within text elem. or paragraph elem.
      var ref_offset = position.getOffset();
      if (ref_element.getType() == DocumentApp.ElementType.PARAGRAPH){
    
        // Cursor is at beginning or end of line
        if (ref_offset == 1){
    
          // Cursor is at last word. Move to the left into TEXT
          ref_offset = text.length - 1;
    
        }
      }
    
      // Get offset for current word's initial char
      var offset_first = ref_offset - text.substring(0,ref_offset).split(" ")[text.substring(0,ref_offset).split(" ").length - 1].length;
    
      // Get how many chars to the end of current word
      var chars_to_end;
      if (text.substring(ref_offset, ref_offset + text.length - 1).indexOf(" ") > -1) {
    
        // if word has a trailing space exclude it from count
        chars_to_end = text.substring(ref_offset, ref_offset + text.length - 1).indexOf(" ");
    
      } else {
        chars_to_end = text.substring(ref_offset, ref_offset + text.length - 1).length - 1;
      }
    
      // Get offset for current word's last char
      var offset_last = ref_offset + chars_to_end;
    
      // Define the styling attributes
      var style = {};
      style[DocumentApp.Attribute.FOREGROUND_COLOR] = '#FF00FF';
    
      // Apply styling to current word
      ref_element.asText().setAttributes(offset_first, offset_last, style);
    }
    

    Note: You will have to filter the returned word if it has comas or other characters trailing or preceding. Hint: use regex. Have a look at this test document with it's bound script to see it working.

    Also for reference the key function here is: setAttributes(startOffset, endOffsetInclusive, attributes)

    Please note there is many ways to go about this, this is just one way to achieve it.