Hello www-style:
I would like to propose a new method addition to the CaretPosition
interface (editor's draft of the spec available here:
http://dev.w3.org/csswg/cssom-view/ ).
== Summary ==
I propose we add a new method, getClientRect(), to the CaretPosition
interface, for tracking changes to caret positions across reflows.
== Rationale ==
Currently, the document.caretPositionFromPoint() method allows us to
convert from a point in CSS page coordinates to a CaretPosition, which
represents a Node and offset within that Node. At Mozilla, we have
developed a set of tools that allows for what we call "reflow-on-zoom"
(note: this is not a new idea - Opera mobile implements a similar
algorithm). The reflow-on-zoom feature limits the width of line boxes to
be, at a maximum, the width of the viewport, and then generates a reflow
in order to force this option to take effect.
One challenge we faced while developing this feature was the ability to
maintain scroll position within a large amount of text after the reflow
took effect. In order to overcome this, we utilize a point retrieved
from the device (the center of the pinching gesture) and convert this to
a CaretPosition using document.caretPositionFromPoint. This must be
performed before the reflow/zoom operations, so that the correct text
that the user is currently interested in can be identified. After the
reflow/zoom operation is performed, we need to convert the CaretPosition
back to a location, in page coordinates, so that we can move the
viewport (which may now be over different text than what the user wanted
to view, due to line-wrapping) to the correct position. Although I
describe a detailed use-case for this particular feature, it's not
specific to reflow-on-zoom. Any time we wish to track the location of a
CaretPosition before and after a reflow, this method would be useful.
== Solution ==
We'd like to define a new method on the CaretPosition interface,
getClientRect(), that returns the bounding rect of the CaretPosition
object upon which it is called. It would likely have the following
interface definition: ClientRect getClientRect();
== Questions ==
1) Why shouldn't we implement a getBoundingClientRect() on CaretPosition
instead, to be consistent with the Element interface?
getBoundingClientRect(), and its partner method, getClientRects(), is
the usual technique of doing this in cssom-view standards.
getClientRects() returns the list of client rects for all of the
sub-pieces of a particular entity in the DOM. The
getBoundingClientRect() method then returns the bounding box for the
union of all of these client-rects. This is useful for situations where,
the entity upon which it is called may have a number of sub-content
elements (e.g. the individual lines of a piece of text). With
A CaretPosition is not an Element (to which the getBoundingClientRect()
and getClientRects() methods already are available), so we can't use
these on objects of type CaretPosition. Additionally, because
CaretPosition is essentially a collapsed DOMRange we will never have a
situation where we have sub-entities, such as those mentioned above.
getClientRects(), in this case, will always return a single rect that
will be identical to the return value of getBoundingClientRect(). As
such, for brevity, we should combine these two methods into a single
getClientRect() method.
I am happy to take questions and comments regarding this proposal. I
look forward to the discussion to follow.
~Scott Johnson
Platform Engineer, Mozilla Corporation