admin管理员组文章数量:1279018
I would like to programmatically edit my Google Doc externally via a Google Chrome extension or a simple JavaScript and see the changes live (in real-time) in the Google Doc. When this question came up, I was looking for Chrome Extensions that edit a Google Doc and save the changes programmatically. During my research, I came across Grammarly. I am impressed by how they manage to apply their spelling corrections to the Google Doc in near real-time. You can reproduce it like this:
- Install Grammarly Chrome Extension
- Open/create a Google Doc
- Let Grammarly check your text (words that contain errors are highlighted)
- Left click on a highlighted word
- Click on the suggested correction
Grammarly will then update the Google Doc. What I noticed thereby:
- The Google Doc doesn't seem to be updated via the Google Docs API or Google AppScript
- The saving process seems to behave the same as the official autosave mechanism of Google Docs itself when the user manually edits the doc. This can be explained as follows:
- Autosave indicator is triggered
- Google Docs
save
HTTP request is executed
The HTTP FormData also contains the appropriate parameter bination (an existing word within the index rangesi
(startIndex) andei
(endIndex) defined in the 1st mand of the array is replaced by the new word in the 2nd mand)
- Autosave indicator is triggered
[{"mands":[{"ty":"ds","si":229,"ei":232}, {"ty":"is","ibi":229,"s":"Test"}]}]
I have already tried the following solutions:
- Use the Google Docs API.
Result: ✓ works but with a noticeable delay of up to 5 seconds
gapi.client.docs.documents.batchUpdate({
documented: <docId>,
requests: [
{
deleteContentRange: {
range: {
startIndex: 1,
endIndex: 10,
},
},
},
{
insertText: {
location: {
index: 1,
},
text: 'Lorem ipsum',
},
},
],
})
- Use the Google Script API to execute AppScript function.
Result: ✓ works but with a noticeable delay of up to 5 seconds
// API call
await gapi.client.script.scripts.run({
scriptId: <scriptId>,
resource: {
function: 'myFunction'
}
})
// AppScript function from Google Script Editor
function myFunction() {
var body = DocumentApp.openById(<docId>).getBody()
body.appendParagraph("Lorem ipsum")
}
- Manipulate the DOM directly in the Google Doc (here I tried to edit the text of the Google Doc with JavaScript and then save it).
Result: ✗ I couldn't find a way to trigger the autosave mechanism - Manual execution of the internal Google Docs (auto-) save method.
Result: ✗ led to an Internal Server Error
Unfortunately, all attempts so far have been unsuccessful or have not delivered the desired result.
I would like to programmatically edit my Google Doc externally via a Google Chrome extension or a simple JavaScript and see the changes live (in real-time) in the Google Doc. When this question came up, I was looking for Chrome Extensions that edit a Google Doc and save the changes programmatically. During my research, I came across Grammarly. I am impressed by how they manage to apply their spelling corrections to the Google Doc in near real-time. You can reproduce it like this:
- Install Grammarly Chrome Extension
- Open/create a Google Doc
- Let Grammarly check your text (words that contain errors are highlighted)
- Left click on a highlighted word
- Click on the suggested correction
Grammarly will then update the Google Doc. What I noticed thereby:
- The Google Doc doesn't seem to be updated via the Google Docs API or Google AppScript
- The saving process seems to behave the same as the official autosave mechanism of Google Docs itself when the user manually edits the doc. This can be explained as follows:
- Autosave indicator is triggered
- Google Docs
save
HTTP request is executed
The HTTP FormData also contains the appropriate parameter bination (an existing word within the index rangesi
(startIndex) andei
(endIndex) defined in the 1st mand of the array is replaced by the new word in the 2nd mand)
- Autosave indicator is triggered
[{"mands":[{"ty":"ds","si":229,"ei":232}, {"ty":"is","ibi":229,"s":"Test"}]}]
I have already tried the following solutions:
- Use the Google Docs API.
Result: ✓ works but with a noticeable delay of up to 5 seconds
gapi.client.docs.documents.batchUpdate({
documented: <docId>,
requests: [
{
deleteContentRange: {
range: {
startIndex: 1,
endIndex: 10,
},
},
},
{
insertText: {
location: {
index: 1,
},
text: 'Lorem ipsum',
},
},
],
})
- Use the Google Script API to execute AppScript function.
Result: ✓ works but with a noticeable delay of up to 5 seconds
// API call
await gapi.client.script.scripts.run({
scriptId: <scriptId>,
resource: {
function: 'myFunction'
}
})
// AppScript function from Google Script Editor
function myFunction() {
var body = DocumentApp.openById(<docId>).getBody()
body.appendParagraph("Lorem ipsum")
}
- Manipulate the DOM directly in the Google Doc (here I tried to edit the text of the Google Doc with JavaScript and then save it).
Result: ✗ I couldn't find a way to trigger the autosave mechanism - Manual execution of the internal Google Docs (auto-) save method.
Result: ✗ led to an Internal Server Error
Unfortunately, all attempts so far have been unsuccessful or have not delivered the desired result.
Share Improve this question edited Jun 29, 2020 at 12:01 Druux asked Jun 29, 2020 at 10:21 DruuxDruux 1531 gold badge3 silver badges8 bronze badges 15- 1 You have used the two options you have for updating google docs. The Google docs api and app script. As there is nothing else i dont think this question can be anwsered. – Linda Lawton - DaImTo Commented Jun 29, 2020 at 10:26
- @DaImTo I'm afraid so. Even though I'm assuming that there must be a rational explanation for why it works faster at Grammarly? There may be a special agreement between Grammarly and Google... – Druux Commented Jun 29, 2020 at 10:29
- I think you would have to ask Grammarly. SO cant tell you that – Linda Lawton - DaImTo Commented Jun 29, 2020 at 10:59
- 1 Maybe api is not accessed client side in the browser. Detect errors>user clicked highlighted word>Ping to grammerly server> server accesses docs-api – TheMaster Commented Jun 29, 2020 at 11:27
-
Yeah, I think your thinking is going in the right direction @TheMaster. I took a closer look at Grammarly's minified client script of the Chrome Extension and it seems that they municate with their server via WebSockets. I can well imagine that this can improve performance. Nevertheless, I can't explain why Google Docs'
save
function is executed - exactly with the parameters that are responsible for replacing one word with another. – Druux Commented Jun 29, 2020 at 11:53
2 Answers
Reset to default 9(This methods works even with new canvas-based rendering)
Turns out it's super easy; we were all overthinking it. You can just simulate a keypress with an event, and use a for loop to instantly replace whatever text you need to modify. However, Google Docs listens to key events using an Iframe with the contents
<html>
<head></head>
<body spellcheck="false" role="textbox" aria-label="Document content" contenteditable="true" style="background-color: transparent;"></body>
</html>
so we have to trigger the event on the IFrame rather than the document. Also, it wasn't working for me from the content script, so I had to inject another script into the page and use a custom event to tell the injected script to simulate a keypress. You can inject a script as described here, then, from the injected script, you can simulate keypresses on the document like this:
const keyEvent = document.createEvent('Event')
keyEvent.initEvent('keypress', true, true)
keyEvent.key = KEY // A key like 'a' or 'B' or 'Backspace'
// You will need to change this line if you want to use other special characters such as the left and right arrows
keyEvent.keyCode = KEY.charCodeAt(0)
document.querySelector('.docs-texteventtarget-iframe')
.contentDocument.activeElement
.dispatchEvent(keyEvent)
(obtained from this answer).
You can wrap the above code in an event listener in your injected script and dispatch a custom event , with the detail
as the key name, from your content script, to trigger a keypress like this.
For my use case I didn't care where the cursor was, but if you need to find our where the cursor is so you can know how many times to simulate the left/right keys, you can get the index easily by counting the length of all the text classes and finding where the cursor is relative to each character. I found a nice little library for doing this (although, it has caveats as Google Docs apparently only loads one page at a time) that's too long to include here but you can view it on GitHub.
As already answered here - yes, you need send key events to special iframe, not current document.
I'm searched for same functionality recently. After finding it, i made a library. In further you can use this - google-docs-utils
.
- GitHub - https://github./Amaimersion/google-docs-utils
- NPM - https://www.npmjs./package/google-docs-utils
You can use it with Node.js or directly in browser:
- Node.js: npm install google-docs-utils
- Browser: https://unpkg./google-docs-utils@latest/dist/iife/index.js
Here is the code which solves your task using google-docs-utils
package:
GoogleDocsUtils.typeText('test text'); // types at current caret position
GoogleDocsUtils.pressOn.Enter(); // move to new line
GoogleDocsUtils.typeText('another test text');
I looked at the source code of Grammarly - it uses same approach as this lib.
本文标签:
版权声明:本文标题:javascript - How to programmatically update Google Docs in real-time (via Chrome Extension or external JS) - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741242367a2364226.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论