Skip to content

Instantly share code, notes, and snippets.

@rubensanroman
Created March 23, 2012 23:32
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rubensanroman/2176368 to your computer and use it in GitHub Desktop.
Save rubensanroman/2176368 to your computer and use it in GitHub Desktop.
Cross-Browser Cursor Position Detection in Javascript (amazing!)
function cursorPosition() {
var textarea = document.getElementById("dncanvas");
var pos = '';
textarea.focus();
// get selection in firefox, opera, …
if (typeof(textarea.selectionStart) == 'number') {
pos = textarea.selectionStart;
}
else if (document.selection) {
var selection_range = document.selection.createRange().duplicate();
if (selection_range.parentElement() == textarea) {
// Check that the selection is actually in our textarea
// Create three ranges, one containing all the text before the selection,
// one containing all the text in the selection (this already exists), and one containing all
// the text after the selection.
var before_range = document.body.createTextRange();
before_range.moveToElementText(textarea); // Selects all the text
before_range.setEndPoint("EndToStart", selection_range); // Moves the end where we need it
var after_range = document.body.createTextRange();
after_range.moveToElementText(textarea); // Selects all the text
after_range.setEndPoint("StartToEnd", selection_range); // Moves the start where we need it
var before_finished = false, selection_finished = false, after_finished = false;
var before_text, untrimmed_before_text, selection_text, untrimmed_selection_text, after_text, untrimmed_after_text;
// Load the text values we need to compare
before_text = untrimmed_before_text = before_range.text;
selection_text = untrimmed_selection_text = selection_range.text;
after_text = untrimmed_after_text = after_range.text;
// Check each range for trimmed newlines by shrinking the range by 1 character and seeing
// if the text property has changed. If it has not changed then we know that IE has trimmed
// a \r\n from the end.
do {
if (!before_finished) {
if (before_range.compareEndPoints("StartToEnd", before_range) == 0) {
before_finished = true;
}
else {
before_range.moveEnd("character", -1);
if (before_range.text == before_text) {
untrimmed_before_text += "\r\n";
}
else {
before_finished = true;
}
}
}
if (!selection_finished) {
if (selection_range.compareEndPoints("StartToEnd", selection_range) == 0) {
selection_finished = true;
}
else {
selection_range.moveEnd("character", -1);
if (selection_range.text == selection_text) {
untrimmed_selection_text += "\r\n";
}
else {
selection_finished = true;
}
}
}
if (!after_finished) {
if (after_range.compareEndPoints("StartToEnd", after_range) == 0) {
after_finished = true;
}
else {
after_range.moveEnd("character", -1);
if (after_range.text == after_text) {
untrimmed_after_text += "\r\n";
}
else {
after_finished = true;
}
}
}
}
while ((!before_finished || !selection_finished || !after_finished));
// Untrimmed success test to make sure our results match what is actually in the textarea
// This can be removed once you're confident it's working correctly
var untrimmed_text = untrimmed_before_text + untrimmed_selection_text + untrimmed_after_text;
var untrimmed_successful = false;
if (textarea.value == untrimmed_text) {
untrimmed_successful = true;
}
// ** END Untrimmed success test
var startPoint = untrimmed_before_text.length;
pos = startPoint;
}
}
return pos;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment