Monday, December 3, 2007

Mozilla/Firefox Range - Part 2: setStart and collapse Methods

As the continuation of Range setEnd investigation (see first article from Range cycle) let's go on and start from the beginning: setStart method.

Range startOffset Property and setStart Method
Range collapse Method (Solves Contradiction)
Range startOffset not Existing Target
Conclusions

Range startOffset Property and setStart Method
  • range.startContainer - points to the node where the range starts
  • range.startOffset - is shift inside the startContainer to point exactly to the place where range starts
  • range.setStart(newStartContainer, newStartOffset) – sets new start boundary of the range
As opposed to range.endOffset method range.startOffset means exactly what you've thought about - is index of child node or character of range.startContainer that is the first node that belongs to the range.







In terms of
previous example here we see range.startContainer is equal to text node 'day' and dayRange.startOffset is 0 (which points to 'd' letter - the first character that belongs to dayRange).

It looks like we shouldn't have any surprises with unexpected behavior or misunderstanding of startOffset property.

But here is also same warning as in case of endOffset property:
As it turns out node or character that startOffset points at may not exist.

We will see an illustration of this situation in the
below section of the article.

Range collapse Method (Solves Contradiction)
  • range.collapse(toStart) - furls range to a point. Depending on toStart value (boolean) range is collapsed to startNode and startOffset or endNode and endOffset.
Let's continue considering our example with dayRange.

So dayRange has next properties set:
  • commonAncestorContainer - Text node ‘day’
  • startContainer - Text node ‘day’
  • startOffset - 0
  • endContainer - Text node ‘day’
  • endOffset - 3

Now, let's collapse dayRange to start:

dayRange.collase(true);

After this call dayRange gonna hold no text information and its properties will be set to:

  • commonAncestorContainer - Text node ‘day’
  • startContainer - Text node ‘day’
  • startOffset - 0
  • endContainer - Text node ‘day’
  • endOffset - 0






Note that endOffset is set to 0 now. What does it mean? Remembering what we've investigated about endOffset we know, that it points right before the node or character that belongs to the range. As a consequence from this we conclude that 'd' does not belongs to the dayRange and that dayRange is ended right before it.

From the other side startOffset is also 0. This means that 'd' is the first letter of
dayRange and 'd' does belong to dayRange.

A little contradictious, yeah?

* * *
Here i have a question to mathematicians:
what is resulting range for [0,0)?

Is it point 0? Or is it empty range? Or this this is simply wrong question? ;)
* * *

In Mozilla's interpretation we have next explanation:
method collapse makes dayRange do not contain any text data. That means that 'd' does not belong to it.

Conclusion: endOffset exclusion has more strength than startOffset inclusion.


Range startOffset not Existing Target

Again, suppose we have initial dayRange (text node 'day' is selected):

  • commonAncestorContainer - Text node ‘day’
  • startContainer - Text node ‘day’
  • startOffset - 0
  • endContainer - Text node ‘day’
  • endOffset - 3







Now let's execute (collapse
dayRange to end)

dayRange.collase(false);

After execution dayRange properties will be set to:
  • commonAncestorContainer - Text node ‘day’
  • startContainer - Text node ‘day’
  • startOffset - 3
  • endContainer - Text node ‘day’
  • endOffset - 3







Now we have another situation: both
startOffset and endOffset point to fourth letter of the 'day' node. This is the case when startOffset points to nonexisting element.



Conclusions

We've determined two cases when we should be careful with startOffset.

  1. Node or character pointed by startOffset is not included in range when endOffset of the same range points to same node or character.

  2. Node or character pointed by startOffset may not exist in the case when it is not inclused into the range (because of 1. for example)

No comments: