Programmatically temporarily altering a Google Docs and then replacing with the pre-altered version

做~自己de王妃 提交于 2020-01-07 07:43:49

问题


I am trying to do the following, which would seem to be a straightforward task. After 2 weeks of trying various approaches, I am still failing at Step 4:

  1. Starting with an existing Google Doc (Gdoc) file,
  2. programmatically accept all suggested changes,
  3. and then export file as a text file (this step goes quickly),
  4. and then undo the temporary changes so that file is identical to how it started out in Step 1.

My approach (see attached code) was to write a JavaScript (which I have made into a bookmarklet) to:

  1. save content of the original Gdoc (the version in Step 1),
  2. then accept suggested changes (a real life-saver here, btw: http://www.tcg.com/blog/accept-all-bookmark-for-google-docs-suggestions/)
  3. export the file locally as plain text (globally accepting the suggested changes allows those edits to be incorporated into the text!)
  4. restore the document to the saved version.

The Javascript code follows. My question is: why doesn't my approach of saving original file content through sessionStorage.setItem, and then retrieving it to restore the document in the last step, not working? ("Not working" in this context means that when viewing the document after running the script, the "suggested changes" do not go back to being indicated as "suggestions" as in the original document).

In addition to the sessionStorage.setItem approach, I've tried lots of others, including storing document.getElementsByClassName("*stuff*").innerHTML, .outerHTML, .innerTEXT, .outerTEXT in variables inH, outH, inT, outT, respectively, at the beginning of the script and then equating document.getElementsByClassName("*stuff*").innerHTML, outerHTML, innerTEXT, .outerTEXT to inH, outH, resp. Didn't work. ("stuff" is "docos-icon-accept-suggestion-checkmark", btw)

I've also tried making a "backup copy" of document.getElementsByClassName("*stuff*") by cloning it: backupD = document.getElementsByClassName("*stuff*").cloneNode(true) then later restoring by document.getElementsByClassName("*stuff*").replaceWith(backupD) Didn't work, either.

Is it possible that something other than .getElementsByClassName("*stuff*") is what I should be storing then using to restore the Gdoc? I'm using the above node because it is what is used to globally accept the suggested changes, which would seem to be the relevant thing to "undo" the process.

Speaking of "undo", I also looked into trying to programmatically "undo" to restore all of the accepted suggested changes. My code knows how many times that "undo" would need to be evoked (and when I click the undo arrow on the Gdocs menu manually by that many times, I get back the original document), but I could not find anything written about how the "undo" button is implemented in Gdoc and how to programmatically "hit" the undo button.

Finally, the other alternative that I thought of (was my first idea to explore) was to somehow programmatically make a copy of the GDoc on the Google Drive (there's probably lots of guidance out there to do this), then use that copy as my "scratch copy" for accepting all suggested changes so that I didn't have to worry about restoring original content to a file. But the hurdle there is that when I fire-up this javascript, it operates on the file that was opened when I clicked on the bookmarklet, without any obvious way to open up and then "accept all suggested changes" on the copied file.

Here's my code (which fails to restore the Gdoc to its original state). Any advice regarding what approach I should be using to get my Gdoc to the original state it was in before doing a global "accept all suggested changes" would be very much appreciated:

javascript:(function()  {sessionStorage.setItem("backup",document.getElementsByClassName("docos-icon-accept-suggestion-checkmark")); var d = document.getElementsByClassName("docos-icon-accept-suggestion-checkmark"); d = Array.prototype.slice.call(d); var cnt = 0;  d.forEach(function(n){ var e = document.createEvent("MouseEvents");  e.initEvent("click", true, false);  n.dispatchEvent(e,true); e = document.createEvent("MouseEvents");  e.initEvent("mousedown", true, false);  n.dispatchEvent(e,true); e = document.createEvent("MouseEvents");  e.initEvent("mouseup", true, false);  n.dispatchEvent(e,true); cnt++; }); alert('JUST ACCEPTED ALL SUGGESTED EDITS: ' + cnt.toString()); document.getElementsByClassName("docos-icon-accept-suggestion-checkmark").replaceChild(sessionStorage.setItem("backup")); alert('JUST FINISHED RESTORING TO ORIGINAL FILE');}) (); 

Some possibly useful/relevant links:

  • scripting a google docs form submission (has problem of how the Javascript running from the opened "permanent" file, would be able to open the cloned document -- the script could probably copy and upload the doc without problems, however).
  • Programmatically edit a Google doc with JavaScript (quite related to my question, but answers implied that one cannot change Gdoc content without Google Apps Script, which I find confusing because I definitely was able to "accept suggested changes" and change the apparent content of the document. I had the same problem with my attempts at Google Apps as I have with the current javascript: I am tied to the opened document and unable to open and manipulate other documents programmatically. Also, I was unable to get Google Apps to execute the script that accepts all suggestions).
  • How to clone (and restore) a DOM subtree (one of the references from which I got the idea of using .cloneNode, which proved to be another dead end for my project).

回答1:


The following JavaScript, written as a bookmarklet, achieves all of the above objectives, in case this solution might help others who similarly would like to temporarily "accept all suggested changes" in a Google Doc, and then revert the document back to the original state. The specific steps and how they were accomplished follows, if you have a Google Docs on display at the time that you execute the Bookmarklet given at the bottom of this answer.

  1. Programmatically accept all suggested changes. (Algorithm from http://www.tcg.com/blog/accept-all-bookmark-for-google-docs-suggestions/):

    var d=document.getElementsByClassName("docos-accept-suggestion"); d = Array.prototype.slice.call(d); d.forEach(function(n){ var e = document.createEvent("MouseEvents");  e.initEvent("click", true, false);  n.dispatchEvent(e,true); e = document.createEvent("MouseEvents");  e.initEvent("mousedown", true, false);  n.dispatchEvent(e,true); e = document.createEvent("MouseEvents");  e.initEvent("mouseup", true, false);  n.dispatchEvent(e,true); });
    
  2. Programmatically export plain text (which should now have suggested changes incorporated):

    window.open(window.location.href.replace("edit","export\?format=txt"));
    
  3. Do stuff with the Google Doc and/or with the exported plain text file (for example, my files had raw LaTeX, so I compiled the file and got a pdf of my research paper).

  4. Switch the Doc back to its original, pre-accept_all_suggested_changes state.

    w=window.open(window.location.href.replace("edit","copy"));w.addEventListener('load',w.close(),true);alert('Check your download folder for the text file');setTimeout(function(){var a=document.getElementsByClassName("docs-icon-undo")[0]; for(var j=0; j<cnt; j++){e=document.createEvent("MouseEvents"); e.initEvent("click",true,false);a.dispatchEvent(e,true);e=document.createEvent("MouseEvents");e.initEvent("mousedown",true,false); a.dispatchEvent(e,true);e=document.createEvent("MouseEvents");e.initEvent("mouseup",true,false);a.dispatchEvent(e,true)}}
    

(where cnt is the number of suggested changes that were accepted in the previous step. The code figures out the value of cnt for you.)


Altogether, the functional bookmarklet is as follows (where "[DO STUFF]" is where you put in whatever code you want that utilizes the Google Doc or plain text file with all suggested changes incorporated):

javascript:(function(){var d=document.getElementsByClassName("docos-accept-suggestion"); d = Array.prototype.slice.call(d); d.forEach(function(n){ var e = document.createEvent("MouseEvents");  e.initEvent("click", true, false);  n.dispatchEvent(e,true); e = document.createEvent("MouseEvents");  e.initEvent("mousedown", true, false);  n.dispatchEvent(e,true); e = document.createEvent("MouseEvents");  e.initEvent("mouseup", true, false);  n.dispatchEvent(e,true); });window.open(window.location.href.replace("edit","export\?format=txt")); [*DO STUFF*]; w=window.open(window.location.href.replace("edit","copy"));w.addEventListener('load',w.close(),true);alert('Check your download folder for the text file');setTimeout(function(){var a=document.getElementsByClassName("docs-icon-undo")[0];for(var j=0; j<cnt; j++){e=document.createEvent("MouseEvents"); e.initEvent("click",true,false);a.dispatchEvent(e,true);e=document.createEvent("MouseEvents");e.initEvent("mousedown",true,false); a.dispatchEvent(e,true);e=document.createEvent("MouseEvents");e.initEvent("mouseup",true,false);a.dispatchEvent(e,true)}},5000);})();

The code has been tested on a Chrome browser.



来源:https://stackoverflow.com/questions/38647796/programmatically-temporarily-altering-a-google-docs-and-then-replacing-with-the

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!