I'm working on a website that's basically a forum software, but with a different arrangement. There are only 3 levels of posts (questions, solutions, and comments), and for the comments I want to be able to have the user highlight part of a solution to comment on. To do that, I want to just have them highlight part of the reply and it will automatically recognize the targeted area.

I've been able to get the text value using document.selection.somethingOrOther, but it does nothing about the actual position of the text in the page. The problem is that if the page contains "foobar fubar foobar" and the user highlights the second foobar, I can't tell the difference between highlighting the first.

Any help is appreciated, and I'm only worried about IE compatability (odd request, I know :P), so hopefully there's something hackish out there...

Dani AI

Generated

A compact, practical plan that distinguishes identical substrings and survives page layout:

Start by recording a character-offset anchor inside the post (not just the selected text). For IE the reliable way is to use a TextRange that covers the whole post, compute how many characters come before the selection, and save that start index plus the selection length and a short “context” snippet (30–40 chars) before/after. That lets the server or a later client re-locate the exact occurrence even when the same word appears multiple times. ’s constraint (IE only) makes this approach straightforward; ’s bounding coordinates are useful for placing a popup, but pixel coords alone don’t uniquely identify repeated text.

Code to capture the data (IE TextRange):

// returns {start, length, text, before, after} or null if selection not inside containerEl
function getSelectionDataIE(containerEl, contextLen) {
  contextLen = contextLen || 32;
  if (!document.selection) return null;
  var selRange = document.selection.createRange();
  var parent = selRange.parentElement();
  var node = parent, inside = false;
  while (node) { if (node === containerEl) { inside = true; break; } node = node.parentNode; }
  if (!inside) return null;
  var fullR = containerEl.createTextRange(); fullR.moveToElementText(containerEl);
  var fullText = fullR.text;
  var startR = containerEl.createTextRange(); startR.moveToElementText(containerEl);
  startR.setEndPoint('EndToStart', selRange);
  var start = startR.text.length;
  var length = selRange.text.length;
  return {
    start: start,
    length: length,
    text: selRange.text,
    before: fullText.substring(Math.max(0, start - contextLen), start),
    after: fullText.substring(start + length, Math.min(fullText.length, start + length + contextLen))
  };
}

Persistence/recovery notes

  • Best option: immediately wrap the selection in a tiny server-saved span (unique ID) and save the updated post HTML — deterministic and simple.
  • If immediate DOM mutation isn’t acceptable, store start/length + before/after + selectedText in DB. On render, try the exact index first; if that fails, search nearby for the same text using the context snippets.
  • Sanitize any HTML when saving and check containment before accepting an anchor.
  • ’s marker idea works only if users follow rules; the offset+context approach is more robust.

This combination (TextRange offsets + context + optional DOM-wrapping) reliably distinguishes identical words and gives a stable anchor for comments in IE.

Recommended Answers

All 3 Replies

The only thing I can think of is having the user put a special symbol or word in the text when he posts, instead of highlighting.

Here you go MS Boy... :-)

<html>
<head>
    <script>
    function boundDim(oObject)
    {
        var oTextRange = document.selection.createRange();
        if (oTextRange != null) {
            alert("The bounding left is \n" + oTextRange.boundingLeft);
            oTextRange.pasteHTML("<b>" + oTextRange.htmlText + "</b>");
        }

    }
    </script>
</head>
<body onclick="boundDim(this);">Hello to all. Hello to me.</body>
</html>

The above is just a small example on what you can do with the API. Once the text is selected, you get its offset in pixels which you can then use to distinguish between the first and second foobar.
If my snippet doesn't give you what you need, also read on selection and range.

Do let me know if it works. :)

It's definitely a start. Hopefully I'll have some time tomorrow to look into it more...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.