How do I move the caret in a Window.selection() textbox? - javascript

I can identify my currently focussed textbox with Window.selection:
var selection = window.getSelection();
I can identify the caret position with Selection.focusOffset:
var focus = selection.focusOffset;
Let's say that focus is currently 8, so the caret is 8 characters in.
How do I move the caret position, so it's e.g. 5 characters in?
Example method:
selection.setFocusOffset(5); // this method does not exist, so I need something similar
The Selection.extend() and Selection.modify() methods are able to move around the caret to some extend, but in my usecase where I manipulate and replace content inside the selection I need a more simple way to just determine how many characters in I want to place the caret. Btw: my textbox is a wysihtml textarea, which means that it's not technically a textarea div.

If I'm understanding correctly, you are wanting to change the start offset of focus, but Selection.extend() is only used to change the end offset. Since Selection.modify() is not on any standards track, there will not be a "simple way".
You will need to use Selection.getRangeAt() which returns a range object. Use the range objects API to set the start offset of your returned range, then use Selection.addRange() to make the new selection. You may want/need to removeRange() to clear the previous selection. I don't know how the browsers would handle overlapping selections.

Related

If there is a way to specify caret position using fireEvents or userEvents in testing library?

I am trying to simulate a simple click but at a specific position of the value of an input. For example if the value of the input is abcd, I want to click in the middle and leave caret between b and c.
With the normal functionality it always place it at the end.

Is it possible to capture the value prior to an input type insertReplacementText event in a textarea?

When an insertReplacementText input event type, as defined in this W3C Editor's Draft, takes place on a textarea element, the data property or attribute provides the text that was added to the textarea value, replacing some other text, such as when right-click on a misspelled word and the context menu provides suggested words.
The misspelled word does not have to be selected first; and, if the textarea has the focus (the cursor could be far from the misspelled word), when the right click takes place, the cursor is not moved at all.
After the replacement, the cursor is positioned to the right of the new text, as in a paste event. The difficulty is determining the length of the text that was replaced and or it's value.
I ask because I'd like to capture the needed information to undo/redo this event.
Thank you.
Update:
If you maintain a copy of the last value of the textarea in RAM or other lcoal storage options, then there is a way to accomplish this; although the event itself provides little data. I was rather stupid at first, as I was testing this in a separate piece of code, because I forgot that, in the code of my particular project, there is always in RAM a copy of the last value in the textarea. Having that information makes this operation very similar to a paste event when there is a selection before the paste that is replaced by the pasted text. After the replacement is performed, the cursor is positioned immediately to the right of the last character of the replacement text. The data property of the insertReplacementText event contains the value of the inserted text.
Thus, it is a matter of arithmetic involving the length of the new text, the difference in the length of the previous copy of the textarea value's length and the length of the DOM element's value after replacement, and the cursor position after the replacement has been performed. The difference in the length's of the textarea values is the difference in the length of the old text and new text. This provides the selection range from which to extract the old text from the saved copy before updating the copy to the new value. The selectionStart is the same for both the old text and new text; the difference is in the selectionEnd based on the lengths, if not equal.
As long as the browser keeps positioning the cursor to the right of the last character of the replacement text, and you maintain a copy of the last value of the textarea, it appears that this ought to work.
Thank you.

JavaScript: Multi-Line Selection on <textarea> field

Hellow,
Mozilla's Firefox Browser allows doing multi-line selections on the default HTML <textarea> field, using the common way by pressing CTRL while selecting some text using the mouse.
My question: Is it possible to receive the respective selection data?
I already tried using the getSelection() method on the global window object, but this contains just nothing. The selectionStart and selectionEnd properties on the HTMLTextAreaElement itself also just contains the last selection made and I also didn't found any other - may Firefox own - attributes or functions which allows me to get access to them.
Of course, it is also possible to create an own listener using the select event on the respective <textarea> field. However, I guess this is a horrible idea and leads to incorrect information if not all possible procedures, which manipulates or changes the selections in any way, are really covered and on track.
Thanks.
Is this what you're looking for?
First you get the whole value of the textarea. Then you take the substring between the selectionStart and selectionEnd - which is the selected portion of the content.
// Create a reference to the textarea object for simpler code after this
var textarea = document.getElementById('textareaId');
// Get the part of the value that is selected
var selected = textarea.value.substring(textarea.selectionStart,
textarea.selectionEnd);

Expanding a JS range/selection in an HTML textbox

Given a text box that a user has made a selection in, I would like to be able to expand the selection (by a word or character) with JS.
I know that in some browsers I can use window.getSelection(); (see here) to get the current selection, and in FireFox you can use selection.modify("extend", "forward", "word"); there is also a TextRange object that IE supports.
This is a requirement as I need to inspect the selection and compare it to the text that comes before and after it (so obviously i will reset the selection when I am done).
I need to support IE9 (though maybe I can get away with IE10), Chrome and FF, and I have JQuery but can use any third party JS library.
This article is interesting, but not quite what want: Selection ranges in webkit (Safari/Chrome)
Textareas have their own selection API that is different from the API for regular selections within the page or in contenteditable elements. It's pretty simple: a textarea has readable and writable selectionStart and selectionEnd properties which represent the selection start and end positions respectively within the textarea's value. IE <= 8 had a different API for this but IE 9 supports it.
You don't get an equivalent of Selection.modify() but you may not need it anyway since it is generally easy enough to work with the textarea's value.
MDN: https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
You can change the active selection by:
var selection = window.getSelection();
var range = selection.getRangeAt(0);
range.setStart(range.startContainer, 0); // set to the beginning
selection.setSingleRange(range);
Modifying the range wont update the UI, you have to set the range.

multiple contenteditable elements, using arrow keys to navigate

I got multiple <p contenteditable="true"></p> elements on a page. I'm looking for a solution to use arrow keys for navigating across those disjoint elements just as if they were one single editable element.
So for instance, if the caret is at the 10th character on the last line of the 1st paragraph and the user hits the down arrow key, the caret should jump to the 2nd paragraph and place the caret at the 10th character (if there's one) on its first line.
Appreciate any comments.
Revised answer
You can detect that the caret is at the start or end of the current editable element by using something like the following (example is for down array on the last line):
Detect the down arrow keydown event
Check if the caret is at the end of the paragraph by doing one of the following:
Create a Range (or TextRange in IE) from the selection object and comparing it to another Range that encompasses the whole paragraph. This is the slightly trickier but more seamless option. OR:
Store the selection and set a brief timer (say 1 millisecond) to allow the keypress to take effect. The function passed to the timer calls compares the current selection with the previously stored selection. If they're the same, the caret has not moved and must have been at the end of the paragraph.
If the caret is at the end of the paragraoph, move it to the start of the next editable paragraph.
This isn't the the usual behaviour of the caret but is reasonably easy to achieve and could be a reasonable compromise. The problem is that there's no reliable cross-browser way to work out the caret's coordinates.
What if you would make the container element editable, instead of every single paragraph?
For example:
<div contenteditable="true">
<p>Lorem ipsum</p>
<p>dolor sit</p>
</div>

Categories

Resources