Okay, I solved it on firefox. Turns out that passing the span element
isn't what it wants... it wants the text node within the span element.
My lord.
if( document.createRange ) {
// firefox
range = document.createRange();
range.setStart( domElement.firstChild, offset );
range.setEnd( domElement.firstChild, offset );
} else if( document.selection &&
document.selection.createRange ) {
// supposed to be IE
range = document.selection.createRange();
range.move( 'character', offset );
}
The very last problem now is on IE side of things. I have no idea how
to associate a range to a dom node. Not a clue. The apis are so
craptastic. Everything is string-based. If you get the user selection,
most cases (like bolding the selection), it doesn't matter what the
container node is. But for what I need to do - it really matters. IE
has a way to find out who the parent node is for a user selection,
it's a read only getter method. I have no idea how to set it.
Help?
On Apr 7, 3:33 pm, egervari <[email protected]> wrote:
> Okay, I find half of the solution. I still need help with the other
> half.
>
> To get the caret position within an editable content div, we need to
> the following:
>
> 1) Turn all nodes into HTML elements. Meaning, nothing can be a
> regular text node. Basically, we need to wrap everything in a <span>
> tag that doesn't do anything. This makes sure that all children are
> ordered and accounted for.
>
> 2) Get the current selection and range object. If none exists, just
> stop running the function ;)
>
> 3) Create a variable to track the caret position. Set it to 0.
>
> 4) Next, loop through all the children of the editable content div.
> For each child, we check to see if that child is the same as the
> startContainer of the selection's range.
>
> -> If it isn't, we add the length of the text of the <span> to the
> caretPosition counter. We keep iterating.
> -> If it is, we take the range's offset and add it to the
> caretPosition counter. We are done.
>
> Since the children come in the order they are in the div container,
> this works. It is a bit verbose, but it works. There are a few outlier
> cases at the beginning and end of the container, but I'll worry about
> those later.
>
> To set the caret position, we basically do the reverse.
>
> 1) Make a new variable called "charactersLeft" and set it to the
> desired caret position.
>
> 2) Loop through all the children of the editable content div. For each
> child
>
> -> if the length of the span element is <= charactersLeft, we
> subtract that number from charactersLeft and keep looping.
> -> otherwise, we found the text node that caret is supposed to be
> in. We are done with the loop. We return the childNode and
> charactersLeft.
>
> 3) We create a new range and set it's startContainer and endContainer
> to the childNode and we set its text offset to "charactersLeft".
>
> This is pretty simple solution. In theory it should work. However, the
> range object in Mozilla isn't doing what I'm telling it what to do.
>
> if( document.createRange ) {
> range = document.createRange();
> range.setStart( domElement, offset );
> range.setEnd( domElement, offset );
> range.select();
>
> }
>
> Basically, any offset I send to this, Firefox gets it entirely wrong.
> It either resets the cursor to the beginning of the div container, or
> to the beginning/end of some other node entirely. ARGH!
>
> This is kind of crappy because I really thought I had a solution. It
> is logical and I know "my part" works, just the browser part of it
> doesn't work.
>
> Help? :/
>
> On Apr 7, 1:38 pm, egervari <[email protected]> wrote:
>
> > Yes, I am using jQuery.
>
> > I found that it's pretty trivial to set the position for a single text
> > node.
>
> > The problem I run into is when there are multiple elements within the
> > div. For example:
>
> > <div editableContent="true>
> > Here is <span class="GrammarError" message="Repeated Word">some
> > some</span> text.
> > </div>
>
> > It is easy to set the position to "4" in this case, because the first
> > text node will report the offset as "4".
>
> > The problem is if the user has the cursor within "some some". If they
> > had it between the "so" and "me", it would report an offset of 1 (or
> > 2) - not 10 (or 11) like you would expect.
>
> > Basically, the cursor position resets to 0 for every kind of node
> > inside of the div.
>
> > I will try out that jquery code just to make sure. Maybe it'll work.
> > It's looks too simple though as I have built my own abstractions on
> > the around selection/range to take care of cross browser and find
> > myself trying the same kind of thing as suggested on that page :(
>
> > On Apr 7, 1:09 pm, Steel City Phantom <[email protected]> wrote:
>
> > > are you using jquery? if so,
>
> > >http://stackoverflow.com/questions/499126/jquery-set-cursor-position-...
>
> > > <http://stackoverflow.com/questions/499126/jquery-set-cursor-position-...>i
> > > have to put some more thought on which event you would have to use to
> > > trigger it.
>
> > > in worst case, pull down the jquery code and find the method and see how
> > > they do it. i switched to jquery a long time ago, makes everything much
> > > easier and you have a fairly reasonable guarantee that it will work cross
> > > browser.
>
> > > On Wed, Apr 7, 2010 at 9:49 AM, egervari <[email protected]> wrote:
> > > > I'm a long time listener. I'm actually the guy that sent him that
> > > > scala question with the name "Huge G. Rection" if you remember that ;)
> > > > That crazy guy from Canada!
>
> > > > Anyway... I'm having a problem with JavaScript and I thought since
> > > > this community is way smarter than average communities, I might be
> > > > able to find an answer here.
>
> > > > If I'm using editable content divs... is there a way to easily get/set
> > > > the cursor? Gmail makes this look easy, but it's actually not an easy
> > > > problem.
>
> > > > My div contains text and other html elements - notably several
> > > > <span>'s. These span's indicate grammar errors and the like. So when
> > > > the person types text into the editor, we have to drop some text nodes
> > > > from the div and replace them with the spans. These spans add those
> > > > nice red squiggles and also provide tooltips indicating how to fix the
> > > > grammar error.
>
> > > > Every time I change the contents of the editable div, firefox will
> > > > reset the cursor to the beginning of the content box (annoying!) and
> > > > IE will reset it to the end (not as bad, but still a problem if they
> > > > edit text in the middle).
>
> > > > Now, I know there's selection objects and range objects. The problem
> > > > with these is that if the anchor/start nodes they were pointing to are
> > > > deleted, the browser auto-magically points them to other elements of
> > > > the DOM. In Firefox, it's the parent div container. In IE, it's
> > > > something else.
>
> > > > Is there another way I can save/restore selection (i.e. cursor) state?
> > > > Or do I have to wrap every word and space character with a <span> tag
> > > > just to avoid deletions?
>
> > > > I've spent about 6 hours on this problem, which is actually more than
> > > > it took to build the entire ajax grammar checker. I'm a little
> > > > frustrated and looking for help.
>
> > > > I realize this is a JavaScript question, but it's for a Java
> > > > application :)
>
> > > > Thanks!
>
> > > > --
> > > > You received this message because you are subscribed to the Google
> > > > Groups
> > > > "The Java Posse" group.
> > > > To post to this group, send email to [email protected].
> > > > To unsubscribe from this group, send email to
> > > > [email protected]<javaposse%[email protected]>
> > > > .
> > > > For more options, visit this group at
> > > >http://groups.google.com/group/javaposse?hl=en.
>
> > > --
> > > You want it fast, cheap, or right. Pick two!!
--
You received this message because you are subscribed to the Google Groups "The
Java Posse" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/javaposse?hl=en.