Custom keyboard shortcuts for Google Docs (change

2019-02-17 17:07发布

问题:

I would like to change the ForegroundColor of a selected text in a Google Docs with a keyboard shortcut.

I could make the "change the ForegroundColor" part (with a menu item bound to the function setColor() ), but not the "keyboard shortcut part".

I found this code but I have trouble implementing it:

$(document).keydown(function(e){
  //CTRL + Q keydown combo
  if(e.ctrlKey && e.keyCode == 81){
    $( '#output' ).html("I've been pressed!");
  }
})

My difficulties :

1) I am not sure where to place this code in my script editor (I tried to place it in the onOpen() function as below, but also above it without success).

2) I am not sure what the $(document) should refer to.

3) I am not sure what they mean by "having to click on / activate the sidebar first for that to happen".

function onOpen() {
  var ui = DocumentApp.getUi();
  ui.createMenu('My Menu')
      .addItem('Color', 'setColor')
      .addToUi();

  var document = DocumentApp.getActiveDocument() // should it be here?
  $(document).keydown(function(e){
    //CTRL + Q keydown combo
    if(e.ctrlKey && e.keyCode == 81){
      SpreadsheetApp.getUi().alert('Hello, world!');
    }
  })
}

function setColor1() {
    var selection = DocumentApp.getActiveDocument().getSelection();
    if (selection) {
    var elements = selection.getRangeElements();
    for (var i = 0; i < elements.length; i++) {
        var element = elements[i];

        // Only modify elements that can be edited as text; skip images and other non-text elements.
        if (element.getElement().editAsText) {
            var text = element.getElement().editAsText();

            // Edit the selected part of the element, or the full element if it's completely selected.
            if (element.isPartial()) {
                text.setForegroundColor(element.getStartOffset(), element.getEndOffsetInclusive(), "#00FFFF");
            } else {
                text.setForegroundColor("#00FFFF");
            }
        }
    }
    }
}

回答1:

In this line, the variable 'document' is an instance of the 'Document' object as defined in Google Apps Script documentation.

var document = DocumentApp.getActiveDocument() 

It's an abstraction over the Google Document sitting in your Drive that allows you to modify your Drive files using a set of methods described here https://developers.google.com/apps-script/reference/document/document

The line below is jQuery syntax.

$(document).keydown(function(e){}

jQuery is a JavaScript library for client-side development. It is used for navigating the HTML DOM tree of a webpage. $(document) is jQuery's representation of the DOM. More on jQuery http://jquery.com/

Because Google Apps Script runs on Google servers, not locally on your machine, there's no DOM tree for you to navigate. You are limited to GAS functions that are mapped to bits of code on Google servers. These two lines of code have nothing to do with each other and are not referring to the same document.

Same applies to events that you can listen to. While GAS does have some event handling capabilities, the list of events is quite short (see 'Simple Triggers' and Installable Triggers') https://developers.google.com/apps-script/guides/triggers/

UPDATE

You can achieve this by building your own custom UI using HtmlService. The caveat is that there seems to be no way to hand over control from Google Document to the UI element, so you'll have to manually set focus on the sidebar after each action.

Here's the example of how the .gs file in your project may look like. Treat this as your server app.

//creates html output from the template
function onOpen(){ 


var ui = DocumentApp.getUi();
var htmlOutput = HtmlService.createTemplateFromFile('sidebar').evaluate();
ui.showSidebar(htmlOutput);

}

function setColor1(){

  //your code

}

Below is my client-side code for the sidebar template. You create the template in your Script Editor by clicking on File -> New -> Html file. Call it sidebar or whatever you choose for the var htmlOutput in the .gsfile above. If you press 'Ctrl + Q', the sidebar will display a confirmation and call the setColor1() function in your .gs file.

More on calling server-side GAS functions from the client https://developers.google.com/apps-script/guides/html/reference/run

More on HtmlService https://developers.google.com/apps-script/guides/html/

The obvious downside is that the sidebar must acquire focus first, so you always need to click on it after making a selection.

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>

    <p> Press Ctrl + Q to change the color of selected text </p>
    <p id="log"> </p>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script>

    $(document).ready(function(){

      $(document).keydown(function(e){

      if(e.ctrlKey && e.keyCode == 81){

           $('#log').html('you pressed Ctrl + Q');

           google.script.run.setColor1();


      }

      });


    });

    </script>


  </body>
</html>

Hope this helps!



回答2:

Instead of using the sidebar as Anton Dementiev suggested, it's possible to use a modeless dialog box. It can be run from the function onOpen() or from a menu item.

  • Advantage of modeless dialog box over the sidebar: the dialog box is smaller and can be move anywhere on the screen (click on the title an drag it)
  • Inconvenient: it's easier to set the focus on the sidebar, because on the modeless dialog box, you have to click inside the content of the dialog (which can be quite small) to set the focus.

The .html is the same than the one Anton Dementiev gave, but the .gs is different:

function onOpen() {
  var ui = DocumentApp.getUi();

  ui.createMenu('My Menu')
      .addItem('Open Color Dialog', 'dialogBox')
      .addToUi();

      var htmlOutput = HtmlService   // alternative to the sidebar
        .createHtmlOutputFromFile('sidebar')
        .setWidth(50)
        .setHeight(50);
      DocumentApp.getUi().showModelessDialog(htmlOutput, 'Title');  

}


  function dialogBox() {
      var htmlOutput = HtmlService
        .createHtmlOutputFromFile('sidebar')
        .setWidth(50)
        .setHeight(50);
      DocumentApp.getUi().showModelessDialog(htmlOutput, 'Title');
}


回答3:

It's really to cumbersome to have to click in the side bar/modeless dialog box and it's sloe, so I am doing with Autohotkey. Here is a .ahk script (source)

#IfWinActive ahk_exe chrome.exe ; the shortcut will only work on chrome 

!^+p:: 
;PART 1: check if the docs is in full-screen (the script work with the mouse position)
; put the mouse on the right top corner of the screen, freeze the spy tool, copy past the relative position (1357, 6 ).
PixelGetColor ColorWin, 1357, 6 RGB  ; get the color of this area
; In my case this part should be white in full screen
if (ColorWin!="0xFFFFFF")   ; if it's white (= fullscreen is OFF)
    send {f11};  then press f11 to activate fullscreen

#
PixelGetColor ColorText, 647, 86 RGB  
;msgbox, 64, (%ColorText%)   ; uncomment if needed for debug to get color to

; get the mouse position and the color of each one you want

if (ColorText="0x000000") {   ;  black
    click,647, 86
    click,712, 120
    click, 786, 177 ; blue
} 
else If (ColorText="0xFF0000") {  ;  blue
    click,647, 86
    click,712, 120
    click, 767, 179 ; blue light
}

 else IF (ColorText="0xE8864A") {  ;  blue light
    click,647, 86
    click,712, 120
    click, 679, 176 ; red
}
else ; 
{
    click,647, 86
    click,712, 120
    click, 657, 151 ; black
}

return