public
Created

Cross-Browser Cursor Position Detection in Javascript (amazing!)

  • Download Gist
cursor.position.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
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;
 
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.