How to get selected text in Google Docs with JavaScript? - javascript

I'm building a Chrome Extension for Google Docs, and I am trying to get the selected text from the current document being edited:
However when I trying running this code, it's returning an empty string ' ':
const docsFrame = document.getElementsByClassName('docs-texteventtarget-iframe')[0]
docsFrame.contentDocument.getSelection().toString()
There was a library called Google Docs Utils that used to be able to do this, but since Docs switched to Canvas-based rendering, the library no longer works.
EDIT:
Here's an example Google Docs to test it out
EDIT # 2:
Made some progress, found this thread with a lot of potential soltutions on it:
https://github.com/Amaimersion/google-docs-utils/issues/10

The most direct way you can do this is by using a Google Add-on script.
You'll get dropped into the Google App Scripts interface, which gives you access to Google Doc's canvas APIs, allowing you to do exactly what you're currentlty struggling to do.
Your challenge then will probably be reconciling the fact that the Google Extension store/marketplace is a different entity from the Google Add-on/Workspace marketplace.
Personally, I think you should just go all-in on writing a Google add-on. Makes life way simpler than writing a Chrome extension.

I figured out how to accomplish it with the help of the thread I mentioned above and through studying some open source code. I am not sure if I am allowed to post open source code here and to avoid licensing conflicts, I will post here the general steps I found:
Enable screen reader functionality / SVG reading. Google will add svg and rect elements to ".kix-canvas-tile-selection" that contain the text that was typed in. Look towards the second half of this thread for different solutions to enabling this.
Use $(".kix-page-paginated").get() to get the current page on Google Docs. Then use $(window).height() calculations to figure out what page the user is currently on.
After accomplishing the two above, you can use a function like so below to get the line of text
function getSelectedLineOfText(page) {
const overlaps = (a, b) => a.left < b.right && a.right > b.left && a.top < b.bottom && a.bottom > b.top
const selectionRects = $(".kix-canvas-tile-selection > svg > rect", page).get()
.map(el => el.getBoundingClientRect())
// Using text elements on that page and the selection rects, find the actual selected line of text.
const textElements $("svg > g[role=paragraph] > rect", page).get();
Note: as you can see from the function name, this can only get an entire selected line in the file. It can't get the specific text selected within a line.
So here, "name is Bob. Hi my name is Bob. Hi my name is Bob." will be returned. I was struggling to get more specific than this, so if anyone has a clue, please feel free to add / create another answer.

Related

Vertical to Horizontal Google App Script Index Result

I came across an interesting way to combine CSE (Custom Search Engine) and PSE (Programmable Search Engine) and use it as a function in Sheets using the following AppScripts code:
Article Link Credits < the great Giacomo Melzi >
Code <
Now , on passing '0' as the value for 'index' parameter, the results are displayed vertically.
Can anyone change it to display the results horizontally across the same row using some code in Google App Script?
I expect someone to answer this soon, Thanks!
You should be able to do it with =TRANSPOSE(LINKEDINPROFILE(A3,0))

How to force Google Docs to render HTML instead of Canvas from Chrome Extension?

After Google Docs' update to canvas based rendering instead of HTML rendering, is it possible to force Google Docs' to render HTML from a chrome extension instead of a canvas? Somehow chrome extensions like Grammarly are able to do it but I'm not entirely sure how.
From my research though I think what allows them to do it through the _docs_force_html_by_ext variable, however I believe this is only for whitelisted extensions.
Is there some sort of alternative or a form I can fill out to get my extension whitelisted?
_docs_force_html_by_ext is undefined:
_docs_force_html_by_ext is set through Grammarly:
There are two solutions to the problem: For older versions of Google Docs And for new versions.
Solution is for older versions of Google Docs
You need to add the GET-parameter ?mode=html to the URL.
For example if document URL is:
docs.google.com/document/exampleId/edit
Change URL to:
docs.google.com/document/d/exampleId/edit?mode=html
This will force Google Docs to use HTML-renderer.
Update March 4, 2022
Google changed the html render activation code.
The html renderer is in the current code, and it works if you turn it on manually.
I'm now looking into what new conditions need to be met to enable it automatically.
I will report the results later.
Update March 9, 2022
The New solution
Once again, it proves that Google programmers are not as good as they are made out to be.
So...
Now there are three ways to enable html rendering.
At least I found three:
Before the start of the Google Docs code:
window._docs_force_html_by_ext == true ? 'html render' : 'canvas render'
Before the start of the Google Docs code:
(GET['mode']=='html' && window._docs_flag_initialData['kix-awcp'] == true) ? 'html' : 'canvas'
Set the required parameters manually in the right place in the Google Doc code.
But, programmers at Google forgot that the window object also contains references to elements that have an id attribute set.
For example:
HTML:
<span id="spanId"></id>
JS:
window['spanId'] == true;
That is, if we can add an id attribute to any element on the page, the value of which will be equal to _docs_force_html_by_ext, then we will automatically receive an identifier in the window object with !=false value. From which it follows that html rendering will turn on, since the conditions of method 1 are met.
For example
<body id="_docs_force_html_by_ext ">
Hint 1: As far as I know, any browser plugin can run before the main code and add an id attribute to any element.
Hint 2: link element can have an id attribute to. I think you get the hint.
Google is whitelisting some applications which can use a script forcing the document to a HTML Fallback version which reminds of the time before canvas or as an Annotated Canvas which makes it possible to make extension integrations with the SVG canvas.
You need to apply for whitelisting to access these features: https://docs.google.com/forms/d/e/1FAIpQLScFxMgvXlq2KMsp0UIM66pvThTF1hpojiXQTqyq9txW79OWag/viewform

Change the Value of Scratch Variables with a Bookmarklet

I am making an engine on Scratch that works with a bookmarklet to provide more functionality without creating a Scratch extension. I have had no trouble reading variables through the DOM when they are showing. However, I am trying to find a way to change the values of the variables so that the bookmarklet can return data to the engine instead of just reading data. The link to the project is https://scratch.mit.edu/projects/574836102/.
I have searched Google and read the Blockly documentation, and couldn't find anything. Scratch has also appeared to have removed the "Blocks", "Variables", and "JavaScript" from the Blockly object. Does anyone know a way that I can write to project variables so the project can read them?
i have not found a way to make a Bookmarklet change a Variable, but i found an other idea...you could make in your scratch project a [ASK()] block and insert text in to the answer. i found 2 bookmarklets 1 does the inserting text and the other presses the enter button, but i did not found a way to get it displayed in the answer Variable... i think the problem is it does not record it as a Users input and does not store it...
https://scratch.mit.edu/projects/610547353/
my remix press space and then 1st bookmarklet and 2ond bookmarklet.
First bookmarklet
javascript: var els=document.getElementsByClassName("question_question-submit-button_3nYah"); if(els.length == 0) alert("Button not found"); else els[0].click();
Second Bookmarklet
javascript:(function(a){a.value=a.value.slice(0,a.selectionStart)+"Hello"+a.value.slice(a.selectionEnd);})(document.activeElement);

PDF-catalogue run over by Emojis

I am managing the website filuren.dk, and we run a pdf-based catalogue, which is driven purely by JavaScript. No problem with this. However, our client have had customers experiencing that the pdf catalogue, has been run over by emojis as seen on the pictures.
I haven't been able to recreate the issue myself, so i have absolutely no idea how to fix it and what to do here. Can anybody enlighten me?
NB: It only happens on certain iPads..
Screenshot 1
Screenshot 2
this is what people use to add imges,
.this.getField('imageField').importImage('path_to_img');
instead of images you can add custom Emojis(.svg or something)
like this:
var f = this.getField("btnImage");
f.buttonSetCaption("Title");
if (f.buttonImportIcon("/C/image.pdf") == 0){ // if 0 == no error
f.buttonImportIcon("/C/image.pdf");
}
you can find the full discussion at Adobe forums on Insert an image into pdf (Adobe Acrobat Pro DC) using javascript.
https://forums.adobe.com/message/8694023#8694023

how apply scroll-sneak to my site

Hello I am currently look for solutions for keeping my scroll position on page load and I found this page ( http://mrcoles.com/blog/scroll-sneak-maintain-position-between-page-loads/ ). Its javascript to keep scroll bar location on page load, but I just cant seem to get it working after looking through the page source and trying different things for a while (im not very experienced with JS) Could someone check this out and see if they can break it down a bit more for me ?
Thanks!
Seems like this git page comments the script a bit more.https://gist.github.com/ohaal/6882141 I'll give you an update when I have applied this to my own site. Probably I can give you a better explanation. What first comes in mind is that you need to set a ID by the latest script explained in the git page above.
// Example of applying sneak to a link:
/*
(function() {
var sneaky = new ScrollSneak(location.hostname);
document.getElementById('sneakytest').onclick = sneaky.sneak;
})();
*/

Categories