HTML5 how to get selected text out of a textarea - javascript

I was able to get the highlighted text out of a textarea by recording onselect and storing the beginning and end each time. Then, when I click a button, I build the substring myself. Isn't there a simpler way of simply querying the selection?
I was kind of expecting that there would be methods in html5 dom for all these things, something like:
textarea.getSelectedStart()
textarea.getSelectedEnd();
textArea.setSelected(start,end);
Also, is there a way of programmatically deselecting text in a textarea?
I am putting in code based on the first solution below. This sort of works, but has a weird problem:
<script language=javascript>
function replaceCLOZE(code, questionType) {
var v = code.value;
var s = code.selectionStart;
var e = code.selectionEnd;
var t = v.substr(s, e-s);
var rep = "{:" + questionType + ":="+t+"}";
code.value = v.substr(0,s) + rep + v.substr(e,v.length-e+1);
}
function shortAnswer(code) {
replaceCLOZE(code, "SA");
}
function shortAnswerCaseSensitive(code) {
replaceCLOZE(code, "SAC");
}
function multipleChoice(code) {
replaceCLOZE(code, "MC");
}
The text area does in fact have attributes code.selectionStart and code.selectionEnd. But the code above, which now works, sets the highlighted text on the screen to be the first word in the textarea. Mind you, the selectionStart is still correct, but what is actually highlighted in Firefox is wrong.
In Chrome it works fine. Maybe this is just a bug in firefox or is there something else which should be done to properly update the textarea visually?

Following is simple way to get selected text of textarea of html. Still not clear what you want as following method simply will give you selected text in alert.
<html><head>
<script>
function alertme(){
var textarea = document.getElementById("textArea");
var selection = (textarea.value).substring(textarea.selectionStart,textarea.selectionEnd);
alert (selection);
}
</script>
</head>
<body>
<p><textarea class="noscrollbars" id="textArea"></textarea></p>
<button onclick="alertme()">Click me</button>
</body></html>
When you select text, the button will alert you what you have selected. selectionStart gives you starting point and selectionEnd gives you end point, while substring needs three arguments string, starting point and ending point.

Related

(answered) php or js: Is there a way to echo something at the area you are typing?

The answer is using a html[pre] tag to insert the text into the database.
So I have a <textarea id="something" name ="name"></textarea> where you can write something for the contents of the post. Problem is, you need to type br instead of enter because of my shitty way of programming a database.
So I made a little javascript program that detects the keypress of enter and echos it (this is litterally the first thing I ever did with javascript) and it works somehow code or:
var input = document.getElementById("id"); // put the id of where you want to put this
input.addEventListener("keyup", function(event) { //looks if key is pressed <br>
if (event.keyCode === 13) { //13 is the enter key <br>
document.getElementById("id").innerHTML = 'text'; //echos it?
}
});
But I don't know how I can paste the br in the correct spot (inside the textarea), is there any way to do it? If there is a php solution I would much rather use that, because I actually know how it works.
If your problem is to show the text entered in the textarea field as the same format. Then you can use an alternative way to achieve your goal.
use pre tag to show your text
Example:
<pre> "your text" </pre>
The pre tag displays the text without formatting by browser again. But it retains the format at the time of insertion into the textarea field
It sounds like it should be the other way around—textareas are preformatted, they don't require <br> tags in them. As some of the commenters noted, it would be helpful to understand what you are trying to do to suggest a simpler way of doing it.
However, to directly answer your question, you can detect current cursor position in a textarea with jQuery:
$('#something').prop('selectionStart');
That way you can insert any string in that position, for example (not really good code, just an example):
$('#something').keyup(function(e) {
if (e.which === 13) {
let pos = $(this).prop('selectionStart');
let text = $(this).val();
$(this).val(text.slice(0, pos) + '<br>' + text.slice(pos));
}
});
Fiddle: https://jsfiddle.net/w7349rqj/

Reset content editable caret position

I am currently trying to create a syntax highlighter for Javascript and I currently facing the issue which I have found out is common with creating something like this which is setting the caret position to the end while the user types or edit contentEditable text.
I researched and found this and many other solutions here on SO but none works. It gets the position of the caret but never resets it so I am trying to find a workaround for this problem.
Below is the code I came up with.
html
<div id="editor" contentEditable="true" onkeyup="resetPosition(this)"></div>
<input type="text" onkeyup="resetPosition(this)" />
js
function getPos(e) {
// for contentedit field
if (e.isContentEditable) {
e.focus()
let _range = document.getSelection().getRangeAt(0)
let range = _range.cloneRange()
range.selectNodeContents(e)
range.setEnd(_range.endContainer, _range.endOffset)
return range.toString().length;
}
// for texterea/input element
return e.target.selectionStart
}
function setPos(pos, e) {
// for contentedit field
if (e.isContentEditable) {
e.focus()
document.getSelection().collapse(e, pos);
return
}
e.setSelectionRange(pos, pos)
}
function resetPosition(e) {
if(e.isContentEditable) {
let currentPosition = getPos(e);
e.innerHTML=e.innerHTML.replace(/[0-9]/g, "a");
setPos(currentPosition, e);
return;
}
e.value = e.value.replace(/[0-9]/g, "a");
setPos(currentPosition, e);
}
This works fine for text input but not for contentEditable divs.
When I type something like function, I get otincfun.
UPDATE: I was able to fix the setPos function by changing this line from document.getSelection().collapse(e, pos); to document.getSelection().collapse(e.firstChild, pos); but a new bug arose.
When I press ENTER Key, the caret goes back to the first line and first character. Please how do I fix?
Below is the fiddle link
https://jsfiddle.net/oketega/bfeh9nm5/35/
Thanks.
The Problems
document.getSelection().collapse(element, index) collapses the cursor to the child node that index points to, not the character index.
I was able to fix the setPos function by changing this line from document.getSelection().collapse(e, pos); to document.getSelection().collapse(e.firstChild, pos);
That will work if you are only replacing characters, but if you are creating a syntax highlighter, you will want to encase characters in span elements to style them. e.firstChild would then only set the position to an index within e's first child, excluding latter span's
Another thing to consider is that you may want to autocomplete the certain chars. The caret position before you manipulate the text may not be the same as after you do so.
The Solution
I recommend creating a <span id="caret-position"></span> element to track where the caret is.
It would work like this:
function textChanged(element) {
// 1
const text = setCursorMarker(element.innerText, element);
// 2
const html = manipulate(text);
element.innerHTML = html;
// 3
const index = findCursorIndex(element);
document.getSelection().collapse(element, index)
}
Every time the user types, you can get the current caret position and slip in the #caret-position element in there.
Overwrite the existing html with the syntax highlighted text
Find out where #caret-position is and put the caret there.
Note: The recommended way to listen for when the user types in the content-editable element is with the oninput listener, not onkeyup. It is possible to insert many characters by holding down a key.
Example
There is a working js fiddle here: https://jsfiddle.net/Vehmloewff/0j8hzevm/132/
Known Issue: After you hit Enter twice, it looses track of where the caret is supposed to be. I am not quite sure why it does that.

selectionStart ignoring new line/line break in textarea in Chrome

I am trying to insert text into a textarea at the cursor position or to replace a selected piece of text. The code works in that the text is inserted and if a selection of text is made it is replaced.
The problem is if the user inserts several line breaks first then tries to insert the text. Then instead of inserting the text at the point of the cursor it inserts it at the second line. So for example if the user inserts line breaks and ends on line 5 then clicks the input to insert the text, the text is inserted at line 2.
var holdFocus;
function updateFocus(x) {
holdFocus = x;
}
Triggered by:
<textarea onFocus="updateFocus(this)" cols="53" rows="10" name="entry" id="report" style="width: 98%;"></textarea>
Then the insertion of the text:
function InsertCodeInTextArea(text){
var tav = $(holdFocus).val(),
strPos = $(holdFocus)[0].selectionStart;
var endPos = $(holdFocus)[0].selectionEnd;
front = (tav).substring(0,strPos),
back = (tav).substring(endPos,tav.length);
var textValue = text.split("%lb%").join("\r\n");
$(holdFocus).val(front+ textValue + back);
}
Triggered by clicking on:
<input class="input" type="button" name="LODCTRRAPPA" value ="LODCTRRAPPA" onClick="InsertCodeInTextArea('Location: %lb%Onset: %lb%Duration: %lb%Course: %lb%Type of pain/symptom: %lb%')"/>
This problem seems to only be occurring in Chrome. Safari and FF are okay. Not tested IE. I am sure that this also wasn't happening until a few weeks ago.
Use vanilla JavaScript
From jQuery docs on val():
Note: At present, using .val() on elements strips carriage return characters from the browser-reported value. When this value is sent to the server via XHR, however, carriage returns are preserved (or added by browsers which do not include them in the raw value). A workaround for this issue can be achieved using a valHook as follows:$.valHooks.textarea = {
get: function( elem ) {
return elem.value.replace( /\r?\n/g, "\r\n" );
}
};
Something like the following should suffice:
var holdFocus;
function updateFocus(x) {
holdFocus = x;
}
function InsertCodeInTextArea(text){
var tav = holdFocus.value;
holdFocus.value = tav.substring(0, holdFocus.selectionStart) +
text.split("%lb%").join("\r\n") +
tav.substring(holdFocus.selectionEnd, tav.length);
}
<textarea autofocus onFocus="updateFocus(this)" cols="53" rows="10" name="entry" id="report" style="width: 98%;">foo
bar
baz</textarea>
<input class="input" type="button" name="LODCTRRAPPA" value ="LODCTRRAPPA" onClick="InsertCodeInTextArea('Location: %lb%Onset: %lb%Duration: %lb%Course: %lb%Type of pain/symptom: %lb%')"/>
Update
It's a bug! See productforums.google.com
... if you click out of the textarea and then click back in, and then hit the button the error is now gone and it works.
Tested my snippet, and it did indeed work after clicking out (losing focus) then clicked back in (regaining focus).
This would obviously cause loss of any selections made, and is impractical to ask users to do.
If I find a programmatic workaround, I'll update this answer.

Saving a selection for later use in JS

I've got a rich text editor in an iframe with designMode that does syntax highlighting for small blocks of text. I'd like it to update the highlighting on keyup, but messing with the DOM causes the frame to blur, thus every time you push a key the caret disappears and you can't type anymore. That wouldn't be a problem if the parser could remember where the caret is, and then refocus the iframe and replace the caret. I've read up on getSelection() and its relatives, but apparently onkeyup removes the selection, at least in Chrome - calling getSelection() inside an onkeyup always yields a null selection. Is there a way around this?
This is what I have:
<iframe>
<html>
<head>
<script>
function parse() {
if(window.getSelection().type != 'None') {
var range = window.getSelection().getRangeAt(0);
}
var text = document.body.textContent;
//Parse text, output is stored in newtext
document.body.innerHTML = newtext;
document.body.focus();
if(range) {
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
}
</script>
</head>
<body onload="document.designMode = 'on'; document.onkeyup = parse;">
Text entered appears here
</body>
</html>
</iframe>
I would recommend to use some other code highlighter. Like CodeMirror for example.
not sure if you're open to using a JS framework, but mootools has some pretty nifty selection utilities (e.g., http://mootools.net/docs/more/Element/Element.Forms#Element:getCaretPosition)

Div Editable and More... More

Well,
I need to replace a word, in a div contentEdible property on, by the same word but formatted...
Like this:
<div> My balls are big </div>
To this (replace the word: balls):
<div> My <font style="color:blue;">balls</font> are big </div>
In a contentEditable this happens dinamically, while the user type the text the replacements happens. I think that a simple event onkeydown, onkeyup, or onkey press, can solve this part.
But, the trouble is with the caret, that after all that i tryed, it stay before the word replaced, when should be stay after. I tryed write some js code, tryed find some jquery scripts, but all them failed in this situation...
Any one has some ideia, or trick ?
I think:
--> Record the length of the word unformatted.
--> Delete this word
--> Put new word formatted.
--> Walk with the caret, to position based this formatted word length.
--> Is it?
PS: I have to considerate a word in any place of this div.
I don't know how to write this code that do what i say above.
Correct me, if i'm wrong.
Since yet, thanks!
Edit[1]: I want that this works on Mozilla Firefox, specificlly;
I only have IE6/7 on this machine, but maybe you can apply the concept to other browser versions of Ranges (or maybe this is cross-browser?).
Basically we store the cursor position, make our search/replacement, then put the cursor back where it was:
html:
<div id="content" contentEditable="true" onkeyup="highlight(this)">This is some area to type.</div>
and the script:
function highlight(elem) {
// store cursor position
var cursorPos=document.selection.createRange().duplicate();
var clickx = cursorPos.getBoundingClientRect().left;
var clicky = cursorPos.getBoundingClientRect().top;
// copy contents of div
var content = elem.innerHTML;
var replaceStart = '<font style="color:blue">';
var replaceEnd = '</font>';
// only replace/move cursor if any matches
// note the spacebands - this prevents duplicates
if(content.match(/ test /)) {
elem.innerHTML = content.replace(/ test /g,' '+replaceStart+'test'+replaceEnd+' ');
// reset cursor and focus
cursorPos = document.body.createTextRange();
cursorPos.moveToPoint(clickx, clicky);
cursorPos.select();
}
}

Categories