For those who haven't worked with the Google Docs editor here's a short explanation of how it works:
With that out of the way, here's my request:
I'm working on a plugin that interacts with the Google Doc and I need to be able to do two things:
I've been exhausting a lot of ideas about just how to handle this, but so far I've only manage to get a buggy solution for the latter problem (I perform a backspace, determine where the text changed and undo the backspace).
I'm looking for all the best ideas you can come up with to solve these problems. They don't need to be cross browser, but they do need to be able to be turned into something robust that will also handle things such as font size changed mid line.
A little bit of extra info explaining what a Google Doc looks like in HTML:
<wrapper> // Simplified wrapper containing margins, pagination and similar
<div class="kix-paragraphrenderer"> // single DIV per page wrapping all content
// Multiple paragraphs separated by linebreak created by Enter key:
<div class="kix-paragraphrendeder">...</div>
<div class="kix-paragraphrendeder">...</div>
<div class="kix-paragraphrendeder">
// Multiple wrapper divs created by Google's word wrapping:
<div class="kix-lineview">...</div>
<div class="kix-lineview">...</div>
<div class="kix-lineview">
// Single inner wrapper, still full width of first wrapper paragraph:
<div class="kix-lineview-content">
// Single wrapper SPAN containing full text of the line, but not display:block
<span class="kix-lineview-text-block">
// Multiple spans, one per new font change such as normal/bold text,
// change in font size, indentation and similar:
<span>This is normal text</span>
<span style="font-size:40px; padding-left:4px;">This larger text.</span>
<span style="font-weight:bold; padding-left:10px;">This is bold text</span>
<span style="padding-left:4px;">More normal text</span>
</span>
</div>
</div>
</div>
</div>
</wrapper>
After more tinkering I came to the conclusion that it is extremely troublesome - if not impossible - to try and programmatically determine cursor position with regard to a letter inside a <span>
, simply because the <span>
is the smallest element that is measurable (correct me if I am wrong).
So how to solve the problem? Here's what I ended up doing:
<div>
<div class="kix-paragraphrenderer">
) - I could get the entire text, but wanted to limit the computational load.<div class="kix-lineview">
)<div class="kix-lineview-content">
)<span class="kix-lineview-text-block">
)<span>
's of the text blockinnerText
of the <span>
<div>
with the currently applied style extracted from style.cssText
of the current <span>
<div>
and save this in an array. I now have a position of each single character.This is obviously a bit simplied (I left out details about margins and paddings of the different elements), but it covers the idea behind how it's possible to get the cursor position.
It works quite well, but there are many pitfalls and a lot of measuring required. On top of that it's also required to post-parse the text if you want to use it for anything, since tabs, spaces and linebreaks aren't always included in innerText
(depending on where these are in the text, Google may or may not make them through positioning of new elements).