- 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.- Node or character pointed by startOffset is not included in range when endOffset of the same range points to same node or character.
- 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)