Last active
October 26, 2020 15:46
-
-
Save germain-gg/664ce3284fefa38e52d4 to your computer and use it in GitHub Desktop.
Utils to get and set the caret position in a content editable
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var getCaretOffsetWithin = function(node) { | |
var treeWalker = createTreeWalker(node); | |
var sel = window.getSelection(); | |
var pos = { | |
start: 0, | |
end: 0 | |
}; | |
var isBeyondStart = false; | |
while(treeWalker.nextNode()) { | |
// anchorNode is where the selection starts | |
if (!isBeyondStart && treeWalker.currentNode === sel.anchorNode ) { | |
isBeyondStart = true; | |
// sel object gives pos within the current html element only | |
// the tree walker reached that node | |
// and the `Selection` obj contains the caret offset in that el | |
pos.start += sel.anchorOffset; | |
if (sel.isCollapsed) { | |
pos.end = pos.start; | |
break; | |
} | |
} else if (!isBeyondStart) { | |
// The node we are looking for is after | |
// therefore let's sum the full length of that el | |
pos.start += treeWalker.currentNode.length; | |
} | |
// FocusNode is where the selection stops | |
if (!sel.isCollapsed && treeWalker.currentNode === sel.focusNode) { | |
// sel object gives pos within the current html element only | |
// the tree walker reached that node | |
// and the `Selection` obj contains the caret offset in that el | |
pos.end += sel.focusOffset; | |
break; | |
} else if (!sel.isCollapsed) { | |
// The node we are looking for is after | |
// therefore let's sum the full length of that el | |
pos.end += treeWalker.currentNode.length; | |
} | |
} | |
return pos; | |
}; | |
var setCaretPositionWithin = function(node, index) { | |
var treeWalker = createTreeWalker(node); | |
var currentPos = 0; | |
while(treeWalker.nextNode()) { | |
// while we don't reach the node that contains | |
// our index we increment `currentPos` | |
currentPos += treeWalker.currentNode.length; | |
if (currentPos >= index) { | |
// offset is relative to the current html element | |
// We get the value before reaching the node that goes | |
// over the thresold and then calculate the offset | |
// within the current node. | |
var prevValue = currentPos - treeWalker.currentNode.length; | |
var offset = index - prevValue; | |
// create a new range that will set the caret | |
// at the good position | |
var range = document.createRange(); | |
range.setStart(treeWalker.currentNode, offset); | |
range.collapse(true); | |
// Update the selection to reflect the range | |
// change on the UI | |
var sel = window.getSelection(); | |
sel.removeAllRanges(); | |
sel.addRange(range); | |
break; | |
} | |
} | |
}; | |
var createTreeWalker = function(node) { | |
return document.createTreeWalker( | |
node, | |
NodeFilter.SHOW_TEXT, | |
{ acceptNode: function(node) { return NodeFilter.FILTER_ACCEPT; } }, | |
false | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment