The caret and the stick
PZI'er Andre wonders, if only I could know where in some formatted HTML the user has clicked. I know I can use a textarea but I want to have html, and I don't really want the text in question to be editable.
Here's a solution using html5's new contenteditable attribute and some helpful "selection" code from a popular answer website.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="/lib/jquery/jquery.js"></script>
<script>
$(document).ready(function () {
$("#editable").focus(function() {
captureSelection();
console.log("change of focus", selection, range);
$(this).blur();
});
// Populates selection and range variables
var editable = document.getElementById('editable'),
selection, range;
var captureSelection = function(e) {
// Don't capture selection outside editable region
var isOrContainsAnchor = false,
isOrContainsFocus = false,
sel = window.getSelection(),
parentAnchor = sel.anchorNode,
parentFocus = sel.focusNode;
while(parentAnchor && parentAnchor != document.documentElement) {
if(parentAnchor == editable) {
isOrContainsAnchor = true;
}
parentAnchor = parentAnchor.parentNode;
}
while(parentFocus && parentFocus != document.documentElement) {
if(parentFocus == editable) {
isOrContainsFocus = true;
}
parentFocus = parentFocus.parentNode;
}
if(!isOrContainsAnchor || !isOrContainsFocus) {
return;
}
selection = window.getSelection();
// Get range (standards)
if(selection.getRangeAt !== undefined) {
range = selection.getRangeAt(0);
// Get range (Safari 2)
} else if(
document.createRange &&
selection.anchorNode &&
selection.anchorOffset &&
selection.focusNode &&
selection.focusOffset
) {
range = document.createRange();
range.setStart(selection.anchorNode, selection.anchorOffset);
range.setEnd(selection.focusNode, selection.focusOffset);
} else {
// Failure here, not handled by the rest of the script.
// Probably IE or some older browser
}
};
// Recalculate selection while typing
editable.onkeyup = captureSelection;
});
</script>
<style>
body { margin: 50px; }
</style>
</head>
<body>
<div contenteditable id="editable">
Hello <s>world</s>.
</div>
</body>
</html>