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.
Related
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);
Please do not report this question as a duplicate. I have seen similar questions on stackoverflow, but they don't answer my specific need.
I have some text selected and highlighted on a web page and I'd like to be able to shift-click away from the selected text without extending the selection of text.
I have created a function that sets the variable shiftkey to true whenever the shift key is pressed and I have another function that gets called on a mouse click. The latter function tests if the shiftkey var is set to true to determine if I have a shift-click event. If so, I thought e.preventDefault();
would prevent extending the selected text, but it doesn't!
Using
document.getElementsByTagName("body").style.userSelect = "none";
followed by
window.getSelection().toString();
and finally
document.getElementsByTagName("body").style.userSelect = "auto";
doesn't work either!
Any ideas how this can be made to work?
I found the solution to my problem by reading this page about the selection object and this page about the range object.
I had to assign the original selection to a range and save it to a variable.
var sel = window.getSelection();
var range = sel.getRangeAt(0);
Then, after shift-clicking, the selection would get extended so I would have to empty the selection using either:
sel.empty();
or
sel.removeAllRanges();
Thereafter, I could add the original saved range to the empty selection using:
sel.addRange(range);
I am working on a Firefox add-on that converts onscreen temperatures that the use highlights via the user selection. Once it is converted the user selection is replaced with a span HTML element with the ID of alreadyconverted that contains the original temperature and the converted temperature in brackets. An obvious glitch in the code is that the user can then go through and select the converted temperature and infinitely convert it.
What I want is for my Javascript code to detect when the user selection is contained within the span element, overlapping the span element or contains the entire span element. How can I have Javascript detect when the user has selected that span in full or in part?
I saw a similar question on StackOverflow, but it wanted to know when the user selection was contained entirely within the certain element. That's not completely what I want, but I'm not sure what I would need to change in the code to make it suit my needs.
View the JS Fiddle for that thread: http://jsfiddle.net/eT8NQ/
Looking at MDN's documentation for Select, it appears this functionality is already directly supported. See Selection.containsNode().
I've updated your fiddle, and now it properly returns a boolean whether any portion of the element is in your selection.
function elementContainsSelection(el) {
if (window.getSelection) {
var sel = window.getSelection();
if (sel.rangeCount > 0) {
return sel.containsNode(el, true);
}
}
return false;
}
This function is defaulted to return false unless the aPartlyContained flag is set. Then partial containment will also return true.
aPartlyContained
When true, containsNode() returns true when a part of
the node is part of the selection.
When false, containsNode() only
returns true when the entire node is part of the selection.
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.
I've been calling execCommand on the document to make the selected text bold or to set its color. But recently I need to use execCommand on a certain range and not the selected text.
Can I do this and if so how?
You can, but it needs to be the selection. So in other words, do the following:
Store the current selection
Make a new selection based on the Range
Perform the execCommand
Restore the previous selection
You can create a selection from ranges (non-IE browsers) with the following:
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
With IE, you can directly execute execCommand on TextRange objects, so this whole process won't be necessary.