0

I am using this to retrieve the count

var window.getSelection().getRangeAt(0).startOffset;

and this is what I have so far to restore the count.

var range = window.getSelection().getRangeAt(0);
range.setStart(dNode, dc);
range.insertNode (mcmsfinalLinkhandle);

I am using localStorage to hold the count. This may seem tedious but I appreciate any help. This should be an entry level javascript issue so I feel I should be able to do this without convoluted solution. So far all I am lacking is the ability to place by character instead of by node or line and to keep the caret at the point of insert. Thx again for any help.

Richard
  • 437
  • 4
  • 13

3 Answers3

0

The answer, unfortunately, is - it depends on the browser. I believe FF, Chrome and Safari use the same interface - research it more here: https://developer.mozilla.org/en/DOM/Range

IE and I think Opera, use a different interface: http://msdn.microsoft.com/en-us/library/ie/ms535872(v=vs.85).aspx

Word of advice: if you can, try to stay away from this. Either use an off-the-shelf RTE editor or just a regular text area.

MK_Dev
  • 3,291
  • 5
  • 27
  • 45
  • I am building for Chrome. I have tried setStart and setEnd but this doesn't do anything. So far, following microsoft or Moz solutions do not work. It either has no effect or it gives an error. – Richard Jun 12 '12 at 23:21
  • @Richard: There are separate Range and Selection APIs. A Range is not necessarily tied to a Selection. – Tim Down Jun 13 '12 at 11:33
0

You have to create a range with document.createRange, move it to the correct location, and then select it.

Here's a great solution https://stackoverflow.com/a/3866442/1450483

Community
  • 1
  • 1
Nathan Wall
  • 6,426
  • 2
  • 22
  • 23
  • I need to create the range based on the div, I have actually tried the solution on that thread and I can't get it to create a range for just the editable element. I'm trying again for now. thx – Richard Jun 12 '12 at 23:23
  • No, it just sets the caret at the end. The solution is addressing the entire document and selecting a bunch of erroneous markup that has nothing to do with the element in question. It's far to general to be of use. Thx tho. – Richard Jun 12 '12 at 23:26
0

First, there are separate Range and Selection APIs. A Range is just a single continuous chunk of a document and is not necessarily tied to a selection. Browsers vary as to whether changing a range obtained from the selection affects the selection (Firefox does, others don't), so to be certain of updating the selection, you need to remove and add the range:

var sel = window.getSelection();
var range = sel.getRangeAt(0);
range.setStart(dNode, dc);
range.insertNode(mcmsfinalLinkhandle);
sel.removeAllRanges();
sel.addRange(range);

Moving the caret to a specific character offset within the visible text of an editable element is non-trivial and the code to achieve it far from entry level because everything in the DOM Range API revolves around nodes rather than text, and determining the text being edited requires computing various CSS properties (display, white-space, visibility, to name a few).

You can use my Rangy library and its new TextRange module (demo) to work with the caret and selection as character offsets.

Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • After many hours of working at this, I agree completely that this is anything but trivial. This is part of what will be a free product but unfortunately the structure does not allow for libraries. I have tried the combination you are suggesting here and the result is the same as the code I posted. The code I use to collect the count returns the character offset so I am mystified as to why I cannot just do the reverse. I am all ears even for a complex solution or suggestion. Thx for the reply. – Richard Jun 14 '12 at 14:52
  • @Richard: I've provided simpler code to do it elsewhere that doesn't take into account all the subtleties but may do the job in some situations. See http://stackoverflow.com/questions/9841082/execcommand-inserthtml-breaks-stored-window-getselection/9841644#9841644, for example. – Tim Down Jun 14 '12 at 15:15
  • I feel something less convoluted is being overlooked. As I said, the code I use to collect the count window.getSelection().getRangeAt(0).startOffset; produces the count based on the character position. setStart will fulfill this need in reverse but the parent div is identified as an element node (1). If it were identified as a text node (3), it would count by character instead of by node (per documentation). Once I find a simple solution by node type manipulation or arrangement, I will post it on this thread. Thx again. – Richard Jun 14 '12 at 15:34
  • @Richard: I may be misunderstanding you then. Where is this parent div coming from? Why haven't you got the original text node? – Tim Down Jun 14 '12 at 15:49
  • I am using a standard markup of header/nav/article/footer and the article div is contenteditable='true'. The element in focus when calling window.getSelection().getRangeAt(0).startOffset; is the article div. – Richard Jun 15 '12 at 00:47
  • Also, I am using oninput to call the window.getSelection().getRangeAt(0).startOffset; function and storing the count in localstorage. – Richard Jun 15 '12 at 00:49
  • This is strange because it gives a character count when using startOffset even though it is an element node. – Richard Jun 15 '12 at 00:51