I have this html: <span>some words here</span>
. When that span
is clicked it turns into a textbox with that string in it. Is there a way to find out which character the click occurred at and put the cursor at that point in the string once the textbox with the string appears?
Asked
Active
Viewed 1,272 times
1

chromedude
- 4,246
- 16
- 65
- 96
-
You could programmatically surround each character with `span`s of their own, then either apply event listeners to each or use `document.getElementFromPoint`. – Waleed Khan Jun 07 '12 at 01:42
-
What you're looking for is a variation of [setting a cursor position in Javascript](http://stackoverflow.com/questions/512528/set-cursor-position-in-html-textbox) combined with an [introduction to `range`s](http://www.quirksmode.org/dom/range_intro.html). Note, the Quirksmode link is a bit old, but it gives a good overview. Refer to MDN for more updated information. – Jared Farrish Jun 07 '12 at 02:01
-
1Here is a simple demo I've only tested in Firefox 12: http://jsfiddle.net/sQduu/ Browser support varies, so unless you are only targeting Firefox, you should only view that as a demo of what you could do. – Jared Farrish Jun 07 '12 at 02:30
1 Answers
2
Here's a quick Fiddle (tested in Chrome) that works for a <span>
that includes line breaks, which the above solution choked on:
Summarized below:
function swapArea(baseEl) {
// Display <textarea> element, hide the <span>
}
function getCursorLoc (nodes, range) {
var prevChars = 0;
var clickContent = range.startContainer.textContent;
var clickLine;
//iterate backwards through nodes constituting <span> element contents
for (x = nodes.length - 1; x >= 0; x--) {
node = nodes[x];
if (clickContent == node.textContent) {
clickLine = node; //this is the line user clicked in
}
else if (clickLine && (node.nodeName == "#text") ) {
//sum up length of text lines prior, +1 for the NewLine
prevChars += node.textContent.length + 1;
}
}
//return offset in line clicked + sum length of all previous lines' content
return range.startOffset + prevChars;
}
function replaceAndSet(e) {
//Capture the click target as Selection(), convert to Range();
var userRange = window.getSelection().getRangeAt();
newArea = swapArea(source);
//spanLines holds siblings (nodeName #Text or <BR>) constituting <span> contents
var spanLines = userRange.startContainer.parentElement.childNodes;
var clickChar = getCursorLoc(spanLines, userRange);
newArea.focus();
newArea.setSelectionRange(clickChar, clickChar);
}
var source = someSpan; //the span user clicks on
source.onclick = replaceAndSet;

Jared Farrish
- 48,585
- 17
- 95
- 104

BooDooPerson
- 316
- 1
- 9
-
1Keep in mind, you don't have to and should not ask for upvotes in your answer. Keep it straight-forward and just about the answer (within reason). You'll earn the privilege to comment soon, which will also help. But do not ask for upvotes. `:)` You'll get them if it's a quality answer (in most cases). – Jared Farrish Jun 07 '12 at 22:28